Skip to content

Instantly share code, notes, and snippets.

@kubo
Created September 18, 2011 23:57
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/1225733 to your computer and use it in GitHub Desktop.
Save kubo/1225733 to your computer and use it in GitHub Desktop.
Index: ext/oci8/oci8.h
===================================================================
--- ext/oci8/oci8.h (revision 447)
+++ ext/oci8/oci8.h (working copy)
@@ -422,6 +422,7 @@
void oci8_link_to_parent(oci8_base_t *base, oci8_base_t *parent);
void oci8_unlink_from_parent(oci8_base_t *base);
sword oci8_blocking_region(oci8_svcctx_t *svcctx, rb_blocking_function_t func, void *data);
+void oci8_blocking_function_epilogue(oci8_svcctx_t *svcctx, sword status);
sword oci8_exec_sql(oci8_svcctx_t *svcctx, const char *sql_text, ub4 num_define_vars, oci8_exec_sql_var_t *define_vars, ub4 num_bind_vars, oci8_exec_sql_var_t *bind_vars, int raise_on_error);
#if defined RUNTIME_API_CHECK
void *oci8_find_symbol(const char *symbol_name);
Index: ext/oci8/apiwrap.c.tmpl
===================================================================
--- ext/oci8/apiwrap.c.tmpl (revision 440)
+++ ext/oci8/apiwrap.c.tmpl (working copy)
@@ -33,6 +33,7 @@
* <%=f.name%>_nb
*/
typedef struct {
+ oci8_svcctx_t *svcctx;
<%
f.ret != 'void'
%> <%= f.ret %> rv;
@@ -56,9 +57,11 @@
%> data->rv = <%=f.name%>(<%= f.args.collect do |a| 'data->' + a.name; end.join(', ') %>);
<% end %>
<% if f.ret == 'sword'
-%> return (VALUE)data->rv;
+%> oci8_blocking_function_epilogue(data->svcctx, data->rv);
+ return (VALUE)data->rv;
<% else
-%> return (VALUE)0;
+%> oci8_blocking_function_epilogue(data->svcctx, 0);
+ return (VALUE)0;
<% end %>
}
#else
@@ -69,6 +72,7 @@
{
if (have_<%=f.name%>_nb) {
oci8_<%=f.name%>_data_t data;
+ data.svcctx = svcctx;
<% f.args.each do |a|
%> data.<%=a.name%> = <%=a.name%>;
<% end
Index: ext/oci8/oci8lib.c
===================================================================
--- ext/oci8/oci8lib.c (revision 447)
+++ ext/oci8/oci8lib.c (working copy)
@@ -246,8 +246,8 @@
rb_raise(rb_eRuntimeError /* FIXME */, "executing in another thread");
}
svcctx->executing_thread = rb_thread_current();
+ /* Note: executing_thread is cleard in oci8_blocking_function_epilogue(). */
rv = (sword)rb_thread_blocking_region(func, data, oci8_unblock_func, svcctx);
- svcctx->executing_thread = Qnil;
if (rv == OCI_ERROR) {
if (oci8_get_error_code(oci8_errhp) == 1013) {
rb_raise(eOCIBreak, "Canceled by user request.");
@@ -258,6 +258,15 @@
return (sword)func(data);
}
}
+
+/*
+ * Thread#kill prevents code after rb_thread_blocking_region() from running.
+ * Clean-up code must be in this function.
+ */
+void oci8_blocking_function_epilogue(oci8_svcctx_t *svcctx, sword status)
+{
+ svcctx->executing_thread = Qnil;
+}
#else /* HAVE_RB_THREAD_BLOCKING_REGION */
/* ruby 1.8 */
@@ -272,6 +281,7 @@
tv.tv_sec = 0;
tv.tv_usec = 10000;
svcctx->executing_thread = rb_thread_current();
+ /* Note: executing_thread is cleard in oci8_blocking_function_epilogue(). */
while ((rv = func(data)) == OCI_STILL_EXECUTING) {
rb_thread_wait_for(tv);
if (tv.tv_usec < 500000)
@@ -281,13 +291,18 @@
if (oci8_get_error_code(oci8_errhp) == 1013) {
if (have_OCIReset)
OCIReset(svcctx->base.hp.ptr, oci8_errhp);
- svcctx->executing_thread = Qnil;
rb_raise(eOCIBreak, "Canceled by user request.");
}
}
- svcctx->executing_thread = Qnil;
return rv;
}
+
+void oci8_blocking_function_epilogue(oci8_svcctx_t *svcctx, sword status)
+{
+ if (status != OCI_STILL_EXECUTING) {
+ svcctx->executing_thread = Qnil;
+ }
+}
#endif /* HAVE_RB_THREAD_BLOCKING_REGION */
typedef struct {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment