Created
October 26, 2012 02:44
-
-
Save kubo/3956611 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/ChangeLog b/ChangeLog | |
index 73e1c10..5ca1e38 100644 | |
--- a/ChangeLog | |
+++ b/ChangeLog | |
@@ -1,3 +1,7 @@ | |
+2012-10-26 KUBO Takehiro <kubo@jiubao.org> | |
+ * ext/oci8/lob.c, ext/oci8/oci8.c, ext/oci8/oci8.h, ext/oci8/oci8lib.c: | |
+ Fix github issue #20 | |
+ | |
2012-04-28 KUBO Takehiro <kubo@jiubao.org> | |
* NEWS: add changes between 2.1.2 and 2.1.1 | |
* VERSION: change the version to 2.1.2. | |
diff --git a/ext/oci8/lob.c b/ext/oci8/lob.c | |
index 4289a3a..b9d2400 100644 | |
--- a/ext/oci8/lob.c | |
+++ b/ext/oci8/lob.c | |
@@ -98,6 +98,18 @@ static void oci8_lob_mark(oci8_base_t *base) | |
rb_gc_mark(lob->svc); | |
} | |
+#ifdef HAVE_RB_THREAD_BLOCKING_REGION | |
+static void oci8_lob_free_func(oci8_svcctx_t *svchp, void *arg1, void *arg2) | |
+{ | |
+ OCIError *errhp = (OCIError*)arg1; | |
+ OCILobLocator *lob = (OCILobLocator*)arg1; | |
+ | |
+ /* FIXME: This may stops all ruby threads. */ | |
+ OCILobFreeTemporary(svchp->base.hp.svc, errhp, lob); | |
+ OCIHandleFree(errhp, OCI_HTYPE_ERROR); | |
+} | |
+#endif | |
+ | |
static void oci8_lob_free(oci8_base_t *base) | |
{ | |
oci8_lob_t *lob = (oci8_lob_t *)base; | |
@@ -106,9 +118,23 @@ static void oci8_lob_free(oci8_base_t *base) | |
if (lob->svchp != NULL | |
&& OCILobIsTemporary(oci8_envhp, oci8_errhp, lob->base.hp.lob, &is_temporary) == OCI_SUCCESS | |
&& is_temporary) { | |
+ oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc); | |
- /* FIXME: This may stall the GC. */ | |
- OCILobFreeTemporary(lob->svchp, oci8_errhp, lob->base.hp.lob); | |
+#ifdef HAVE_RB_THREAD_BLOCKING_REGION | |
+ if (NIL_P(svcctx->executing_thread)) { | |
+#endif | |
+ /* FIXME: This may stall the GC. */ | |
+ OCILobFreeTemporary(lob->svchp, oci8_errhp, lob->base.hp.lob); | |
+#ifdef HAVE_RB_THREAD_BLOCKING_REGION | |
+ } else { | |
+ OCIError *errhp; | |
+ sword rv = OCIHandleAlloc(oci8_envhp, (void*)&errhp, OCI_HTYPE_ERROR, 0, 0); | |
+ | |
+ if (rv != OCI_SUCCESS) | |
+ oci8_env_raise(oci8_envhp, rv); | |
+ oci8_add_pending_command(svcctx, oci8_lob_free_func, errhp, lob->base.hp.lob); | |
+ } | |
+#endif | |
} | |
lob->svc = Qnil; | |
lob->svchp = NULL; | |
diff --git a/ext/oci8/oci8.c b/ext/oci8/oci8.c | |
index f951cda..7abc62f 100644 | |
--- a/ext/oci8/oci8.c | |
+++ b/ext/oci8/oci8.c | |
@@ -41,6 +41,13 @@ static VALUE cServer; | |
static ID id_at_session_handle; | |
static ID id_at_server_handle; | |
+struct oci8_command { | |
+ struct oci8_command *next; | |
+ void (*func)(oci8_svcctx_t *svcctx, void *arg1, void *arg2); | |
+ void *arg1; | |
+ void *arg2; | |
+}; | |
+ | |
typedef struct oci8_svcctx_associate { | |
oci8_base_t base; | |
oci8_svcctx_t *svcctx; | |
@@ -1156,3 +1163,30 @@ void oci8_check_pid_consistency(oci8_svcctx_t *svcctx) | |
} | |
} | |
+void oci8_add_pending_command(oci8_svcctx_t *svcctx, void (*func)(oci8_svcctx_t *, void *, void *), void *arg1, void *arg2) | |
+{ | |
+ oci8_command_t *cmd = ALLOC(oci8_command_t); | |
+#if 0 | |
+ fprintf(stderr, "add pending_command %p\n", cmd); | |
+#endif | |
+ cmd->next = svcctx->pending_commands; | |
+ cmd->func = func; | |
+ cmd->arg1 = arg1; | |
+ cmd->arg2 = arg2; | |
+ svcctx->pending_commands = cmd; | |
+} | |
+ | |
+void oci8_execute_pending_commands(oci8_svcctx_t *svcctx) | |
+{ | |
+ oci8_command_t *cmd, *cmd_next; | |
+ | |
+ for (cmd = svcctx->pending_commands; cmd != NULL; cmd = cmd_next) { | |
+#if 0 | |
+ fprintf(stderr, "call pending_command %p\n", cmd); | |
+#endif | |
+ cmd_next = cmd->next; | |
+ cmd->func(svcctx, cmd->arg1, cmd->arg2); | |
+ xfree(cmd); | |
+ } | |
+ svcctx->pending_commands = NULL; | |
+} | |
diff --git a/ext/oci8/oci8.h b/ext/oci8/oci8.h | |
index 96190f2..0243264 100644 | |
--- a/ext/oci8/oci8.h | |
+++ b/ext/oci8/oci8.h | |
@@ -332,6 +332,7 @@ struct oci8_bind { | |
}; | |
typedef struct oci8_logoff_strategy oci8_logoff_strategy_t; | |
+typedef struct oci8_command oci8_command_t; | |
typedef struct oci8_svcctx { | |
oci8_base_t base; | |
@@ -346,6 +347,7 @@ typedef struct oci8_svcctx { | |
char non_blocking; | |
#endif | |
VALUE long_read_len; | |
+ oci8_command_t *pending_commands; | |
} oci8_svcctx_t; | |
struct oci8_logoff_strategy { | |
@@ -477,6 +479,8 @@ oci8_svcctx_t *oci8_get_svcctx(VALUE obj); | |
OCISvcCtx *oci8_get_oci_svcctx(VALUE obj); | |
OCISession *oci8_get_oci_session(VALUE obj); | |
void oci8_check_pid_consistency(oci8_svcctx_t *svcctx); | |
+void oci8_add_pending_command(oci8_svcctx_t *svcctx, void (*)(oci8_svcctx_t *, void *, void *), void *, void *); | |
+void oci8_execute_pending_commands(oci8_svcctx_t *svcctx); | |
#define TO_SVCCTX oci8_get_oci_svcctx | |
#define TO_SESSION oci8_get_oci_session | |
diff --git a/ext/oci8/oci8lib.c b/ext/oci8/oci8lib.c | |
index 9cc39bc..9d0330d 100644 | |
--- a/ext/oci8/oci8lib.c | |
+++ b/ext/oci8/oci8lib.c | |
@@ -246,6 +246,7 @@ sword oci8_blocking_region(oci8_svcctx_t *svcctx, rb_blocking_function_t func, v | |
svcctx->executing_thread = rb_thread_current(); | |
/* Note: executing_thread is cleard at the end of the blocking function. */ | |
rv = (sword)rb_thread_blocking_region(func, data, oci8_unblock_func, svcctx); | |
+ oci8_execute_pending_commands(svcctx); | |
if (rv == OCI_ERROR) { | |
if (oci8_get_error_code(oci8_errhp) == 1013) { | |
rb_raise(eOCIBreak, "Canceled by user request."); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment