summaryrefslogtreecommitdiff
path: root/load.c
diff options
context:
space:
mode:
authorKoichi Sasada <ko1@atdot.net>2020-11-30 16:18:43 +0900
committerKoichi Sasada <ko1@atdot.net>2020-12-01 15:44:18 +0900
commit182fb73c40351f917bf44626c44c1adb6cb1aa5a (patch)
treefe9dd0b8c312dc491b1576004ce80122b77fbfe4 /load.c
parent8247b8eddeb2a504a5c9776d1f77d413c8146897 (diff)
downloadruby-182fb73c40351f917bf44626c44c1adb6cb1aa5a.tar.gz
rb_ext_ractor_safe() to declare ractor-safe ext
C extensions can violate the ractor-safety, so only ractor-safe C extensions (C methods) can run on non-main ractors. rb_ext_ractor_safe(true) declares that the successive defined methods are ractor-safe. Otherwiwze, defined methods checked they are invoked in main ractor and raise an error if invoked at non-main ractors. [Feature #17307]
Diffstat (limited to 'load.c')
-rw-r--r--load.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/load.c b/load.c
index 00ae31e705..1c17587c47 100644
--- a/load.c
+++ b/load.c
@@ -997,6 +997,25 @@ rb_resolve_feature_path(VALUE klass, VALUE fname)
return rb_ary_new_from_args(2, sym, path);
}
+static void
+ext_config_push(rb_thread_t *th, struct rb_ext_config *prev)
+{
+ *prev = th->ext_config;
+ th->ext_config = (struct rb_ext_config){0};
+}
+
+static void
+ext_config_pop(rb_thread_t *th, struct rb_ext_config *prev)
+{
+ th->ext_config = *prev;
+}
+
+void
+rb_ext_ractor_safe(bool flag)
+{
+ GET_THREAD()->ext_config.ractor_safe = flag;
+}
+
/*
* returns
* 0: if already loaded (false)
@@ -1015,6 +1034,8 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception)
enum ruby_tag_type state;
char *volatile ftptr = 0;
VALUE path;
+ volatile bool reset_ext_config = false;
+ struct rb_ext_config prev_ext_config;
fname = rb_get_path(fname);
path = rb_str_encode_ospath(fname);
@@ -1045,6 +1066,8 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception)
break;
case 's':
+ reset_ext_config = true;
+ ext_config_push(th, &prev_ext_config);
handle = (long)rb_vm_call_cfunc(rb_vm_top_self(), load_ext,
path, VM_BLOCK_HANDLER_NONE, path);
rb_ary_push(ruby_dln_librefs, LONG2NUM(handle));
@@ -1055,9 +1078,12 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception)
}
}
EC_POP_TAG();
+
th = rb_ec_thread_ptr(ec);
th->top_self = self;
th->top_wrapper = wrapper;
+ if (reset_ext_config) ext_config_pop(th, &prev_ext_config);
+
if (ftptr) load_unlock(RSTRING_PTR(path), !state);
if (state) {