Skip to content

Instantly share code, notes, and snippets.

@kubo
Created October 28, 2012 03:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kubo/3967362 to your computer and use it in GitHub Desktop.
Save kubo/3967362 to your computer and use it in GitHub Desktop.
diff --git a/VERSION b/VERSION
index eca07e4..fb94c56 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.1.2
+2.1.2.1
diff --git a/ext/oci8/lob.c b/ext/oci8/lob.c
index 4289a3a..d18a539 100644
--- a/ext/oci8/lob.c
+++ b/ext/oci8/lob.c
@@ -107,8 +107,19 @@ static void oci8_lob_free(oci8_base_t *base)
&& OCILobIsTemporary(oci8_envhp, oci8_errhp, lob->base.hp.lob, &is_temporary) == OCI_SUCCESS
&& is_temporary) {
+#ifdef HAVE_RB_THREAD_BLOCKING_REGION
+ oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc);
+ oci8_temp_lob_t *temp_lob = ALLOC(oci8_temp_lob_t);
+
+ temp_lob->next = svcctx->temp_lobs;
+ temp_lob->lob = lob->base.hp.lob;
+ svcctx->temp_lobs = temp_lob;
+ lob->base.type = 0;
+ lob->base.hp.ptr = NULL;
+#else
/* FIXME: This may stall the GC. */
OCILobFreeTemporary(lob->svchp, oci8_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..55fc341 100644
--- a/ext/oci8/oci8.c
+++ b/ext/oci8/oci8.c
@@ -81,6 +81,18 @@ static void copy_server_handle(oci8_svcctx_t *svcctx)
static void oci8_svcctx_free(oci8_base_t *base)
{
oci8_svcctx_t *svcctx = (oci8_svcctx_t *)base;
+ oci8_temp_lob_t *lob;
+
+ lob = svcctx->temp_lobs;
+ while (lob != NULL) {
+ oci8_temp_lob_t *lob_next = lob->next;
+
+ OCIDescriptorFree(lob->lob, OCI_DTYPE_LOB);
+ xfree(lob);
+ lob = lob_next;
+ }
+ svcctx->temp_lobs = NULL;
+
if (svcctx->logoff_strategy != NULL) {
const oci8_logoff_strategy_t *strategy = svcctx->logoff_strategy;
void *data = strategy->prepare(svcctx);
diff --git a/ext/oci8/oci8.h b/ext/oci8/oci8.h
index 96190f2..9bee3db 100644
--- a/ext/oci8/oci8.h
+++ b/ext/oci8/oci8.h
@@ -333,6 +333,11 @@ struct oci8_bind {
typedef struct oci8_logoff_strategy oci8_logoff_strategy_t;
+typedef struct oci8_temp_lob {
+ struct oci8_temp_lob *next;
+ OCILobLocator *lob;
+} oci8_temp_lob_t;
+
typedef struct oci8_svcctx {
oci8_base_t base;
volatile VALUE executing_thread;
@@ -346,6 +351,7 @@ typedef struct oci8_svcctx {
char non_blocking;
#endif
VALUE long_read_len;
+ oci8_temp_lob_t *temp_lobs;
} oci8_svcctx_t;
struct oci8_logoff_strategy {
diff --git a/ext/oci8/oci8lib.c b/ext/oci8/oci8lib.c
index 9cc39bc..44374c6 100644
--- a/ext/oci8/oci8lib.c
+++ b/ext/oci8/oci8lib.c
@@ -234,20 +234,69 @@ static void oci8_unblock_func(void *user_data)
}
#endif
+typedef struct free_temp_lob_arg_t {
+ oci8_svcctx_t *svcctx;
+ OCISvcCtx *svchp;
+ OCIError *errhp;
+ OCILobLocator *lob;
+} free_temp_lob_arg_t;
+
+static VALUE free_temp_lob(void *user_data)
+{
+ free_temp_lob_arg_t *data = (free_temp_lob_arg_t *)user_data;
+ sword rv = OCILobFreeTemporary(data->svchp, data->errhp, data->lob);
+
+ data->svcctx->executing_thread = Qnil;
+ return (VALUE)rv;
+}
+
/* ruby 1.9 */
sword oci8_blocking_region(oci8_svcctx_t *svcctx, rb_blocking_function_t func, void *data)
{
+ oci8_temp_lob_t *lob;
+ OCIError *errhp = oci8_errhp;
+
+ if (!NIL_P(svcctx->executing_thread)) {
+ rb_raise(rb_eRuntimeError /* FIXME */, "executing in another thread");
+ }
+
+ lob = svcctx->temp_lobs;
+ while (lob != NULL) {
+ oci8_temp_lob_t *lob_next = lob->next;
+
+ if (svcctx->non_blocking) {
+ free_temp_lob_arg_t arg;
+ sword rv;
+
+ arg.svcctx = svcctx;
+ arg.svchp = svcctx->base.hp.svc;
+ arg.errhp = errhp;
+ arg.lob = lob->lob;
+
+ svcctx->executing_thread = rb_thread_current();
+ rv = (sword)rb_thread_blocking_region(free_temp_lob, &arg, oci8_unblock_func, svcctx);
+ if (rv == OCI_ERROR) {
+ if (oci8_get_error_code(errhp) == 1013) {
+ rb_raise(eOCIBreak, "Canceled by user request.");
+ }
+ }
+ } else {
+ OCILobFreeTemporary(svcctx->base.hp.svc, errhp, lob->lob);
+ }
+ OCIDescriptorFree(lob->lob, OCI_DTYPE_LOB);
+
+ xfree(lob);
+ svcctx->temp_lobs = lob = lob_next;
+ }
+
if (svcctx->non_blocking) {
sword rv;
- if (!NIL_P(svcctx->executing_thread)) {
- rb_raise(rb_eRuntimeError /* FIXME */, "executing in another thread");
- }
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);
if (rv == OCI_ERROR) {
- if (oci8_get_error_code(oci8_errhp) == 1013) {
+ if (oci8_get_error_code(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