Skip to content

Commit 4321817

Browse files
committed
Fix reactor NIFs to use py_context_acquire for subinterpreter support
The reactor NIFs were using gil_acquire() which doesn't switch to the context's subinterpreter state, causing segfaults when running Python code in the wrong interpreter. Changed nif_reactor_on_read_ready, nif_reactor_on_write_ready, and nif_reactor_init_connection to use py_context_acquire/py_context_release which properly handles thread state switching for subinterpreters.
1 parent 87303b5 commit 4321817

1 file changed

Lines changed: 28 additions & 19 deletions

File tree

c_src/py_event_loop.c

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3084,14 +3084,17 @@ ERL_NIF_TERM nif_reactor_on_read_ready(ErlNifEnv *env, int argc,
30843084
return make_error(env, "invalid_fd");
30853085
}
30863086

3087-
/* Acquire GIL and call Python */
3088-
gil_guard_t guard = gil_acquire();
3087+
/* Acquire context (handles both worker mode and subinterpreter mode) */
3088+
py_context_guard_t guard = py_context_acquire(ctx);
3089+
if (!guard.acquired) {
3090+
return make_error(env, "acquire_failed");
3091+
}
30893092

3090-
/* Import erlang_reactor module */
3093+
/* Import erlang.reactor module */
30913094
PyObject *reactor_module = PyImport_ImportModule("erlang.reactor");
30923095
if (reactor_module == NULL) {
30933096
PyErr_Clear();
3094-
gil_release(guard);
3097+
py_context_release(&guard);
30953098
return make_error(env, "import_erlang_reactor_failed");
30963099
}
30973100

@@ -3102,7 +3105,7 @@ ERL_NIF_TERM nif_reactor_on_read_ready(ErlNifEnv *env, int argc,
31023105

31033106
if (result == NULL) {
31043107
PyErr_Clear();
3105-
gil_release(guard);
3108+
py_context_release(&guard);
31063109
return make_error(env, "on_read_ready_failed");
31073110
}
31083111

@@ -3122,7 +3125,7 @@ ERL_NIF_TERM nif_reactor_on_read_ready(ErlNifEnv *env, int argc,
31223125
}
31233126

31243127
Py_DECREF(result);
3125-
gil_release(guard);
3128+
py_context_release(&guard);
31263129

31273130
return enif_make_tuple2(env, ATOM_OK, action);
31283131
}
@@ -3149,14 +3152,17 @@ ERL_NIF_TERM nif_reactor_on_write_ready(ErlNifEnv *env, int argc,
31493152
return make_error(env, "invalid_fd");
31503153
}
31513154

3152-
/* Acquire GIL and call Python */
3153-
gil_guard_t guard = gil_acquire();
3155+
/* Acquire context (handles both worker mode and subinterpreter mode) */
3156+
py_context_guard_t guard = py_context_acquire(ctx);
3157+
if (!guard.acquired) {
3158+
return make_error(env, "acquire_failed");
3159+
}
31543160

3155-
/* Import erlang_reactor module */
3161+
/* Import erlang.reactor module */
31563162
PyObject *reactor_module = PyImport_ImportModule("erlang.reactor");
31573163
if (reactor_module == NULL) {
31583164
PyErr_Clear();
3159-
gil_release(guard);
3165+
py_context_release(&guard);
31603166
return make_error(env, "import_erlang_reactor_failed");
31613167
}
31623168

@@ -3167,7 +3173,7 @@ ERL_NIF_TERM nif_reactor_on_write_ready(ErlNifEnv *env, int argc,
31673173

31683174
if (result == NULL) {
31693175
PyErr_Clear();
3170-
gil_release(guard);
3176+
py_context_release(&guard);
31713177
return make_error(env, "on_write_ready_failed");
31723178
}
31733179

@@ -3187,7 +3193,7 @@ ERL_NIF_TERM nif_reactor_on_write_ready(ErlNifEnv *env, int argc,
31873193
}
31883194

31893195
Py_DECREF(result);
3190-
gil_release(guard);
3196+
py_context_release(&guard);
31913197

31923198
return enif_make_tuple2(env, ATOM_OK, action);
31933199
}
@@ -3219,23 +3225,26 @@ ERL_NIF_TERM nif_reactor_init_connection(ErlNifEnv *env, int argc,
32193225
return make_error(env, "invalid_client_info");
32203226
}
32213227

3222-
/* Acquire GIL and call Python */
3223-
gil_guard_t guard = gil_acquire();
3228+
/* Acquire context (handles both worker mode and subinterpreter mode) */
3229+
py_context_guard_t guard = py_context_acquire(ctx);
3230+
if (!guard.acquired) {
3231+
return make_error(env, "acquire_failed");
3232+
}
32243233

32253234
/* Convert Erlang map to Python dict */
32263235
PyObject *client_info = term_to_py(env, argv[2]);
32273236
if (client_info == NULL) {
32283237
PyErr_Clear();
3229-
gil_release(guard);
3238+
py_context_release(&guard);
32303239
return make_error(env, "client_info_conversion_failed");
32313240
}
32323241

3233-
/* Import erlang_reactor module */
3242+
/* Import erlang.reactor module */
32343243
PyObject *reactor_module = PyImport_ImportModule("erlang.reactor");
32353244
if (reactor_module == NULL) {
32363245
Py_DECREF(client_info);
32373246
PyErr_Clear();
3238-
gil_release(guard);
3247+
py_context_release(&guard);
32393248
return make_error(env, "import_erlang_reactor_failed");
32403249
}
32413250

@@ -3247,12 +3256,12 @@ ERL_NIF_TERM nif_reactor_init_connection(ErlNifEnv *env, int argc,
32473256

32483257
if (result == NULL) {
32493258
PyErr_Clear();
3250-
gil_release(guard);
3259+
py_context_release(&guard);
32513260
return make_error(env, "init_connection_failed");
32523261
}
32533262

32543263
Py_DECREF(result);
3255-
gil_release(guard);
3264+
py_context_release(&guard);
32563265

32573266
return ATOM_OK;
32583267
}

0 commit comments

Comments
 (0)