Skip to content

Commit d8fb49a

Browse files
committed
Add init_error flag for fast OWN_GIL init failure detection
1 parent 380228f commit d8fb49a

2 files changed

Lines changed: 15 additions & 9 deletions

File tree

c_src/py_nif.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3208,7 +3208,7 @@ static void *owngil_context_thread_main(void *arg) {
32083208
fprintf(stderr, "OWN_GIL: Py_NewInterpreterFromConfig failed: %s\n",
32093209
status.err_msg ? status.err_msg : "unknown error");
32103210
PyGILState_Release(gstate);
3211-
atomic_store(&ctx->thread_running, false);
3211+
atomic_store(&ctx->init_error, true);
32123212
return NULL;
32133213
}
32143214

@@ -3223,7 +3223,7 @@ static void *owngil_context_thread_main(void *arg) {
32233223
fprintf(stderr, "OWN_GIL: create_erlang_module failed\n");
32243224
PyErr_Print();
32253225
Py_EndInterpreter(ctx->own_gil_tstate);
3226-
atomic_store(&ctx->thread_running, false);
3226+
atomic_store(&ctx->init_error, true);
32273227
return NULL;
32283228
}
32293229

@@ -3232,7 +3232,7 @@ static void *owngil_context_thread_main(void *arg) {
32323232
fprintf(stderr, "OWN_GIL: create_py_event_loop_module failed\n");
32333233
PyErr_Print();
32343234
Py_EndInterpreter(ctx->own_gil_tstate);
3235-
atomic_store(&ctx->thread_running, false);
3235+
atomic_store(&ctx->init_error, true);
32363236
return NULL;
32373237
}
32383238

@@ -3242,12 +3242,13 @@ static void *owngil_context_thread_main(void *arg) {
32423242
ctx->module_cache = PyDict_New();
32433243

32443244
if (ctx->globals == NULL || ctx->locals == NULL || ctx->module_cache == NULL) {
3245+
fprintf(stderr, "OWN_GIL: PyDict_New failed for namespace dicts\n");
32453246
Py_XDECREF(ctx->globals);
32463247
Py_XDECREF(ctx->locals);
32473248
Py_XDECREF(ctx->module_cache);
32483249
Py_EndInterpreter(ctx->own_gil_tstate);
32493250
/* Don't call PyGILState_Release - interpreter is gone */
3250-
atomic_store(&ctx->thread_running, false);
3251+
atomic_store(&ctx->init_error, true);
32513252
return NULL;
32523253
}
32533254

@@ -3642,6 +3643,7 @@ static int owngil_context_init(py_context_t *ctx) {
36423643
ctx->own_gil_interp = NULL;
36433644
ctx->local_env_ptr = NULL;
36443645
atomic_store(&ctx->thread_running, false);
3646+
atomic_store(&ctx->init_error, false);
36453647
atomic_store(&ctx->shutdown_requested, false);
36463648
ctx->request_type = CTX_REQ_NONE;
36473649
ctx->response_ok = false;
@@ -3680,16 +3682,17 @@ static int owngil_context_init(py_context_t *ctx) {
36803682
return -1;
36813683
}
36823684

3683-
/* Wait for thread to initialize - up to 5 seconds on slow CI */
3685+
/* Wait for thread to initialize or fail */
36843686
int wait_count = 0;
3685-
while (!atomic_load(&ctx->thread_running) && wait_count < 5000) {
3687+
while (!atomic_load(&ctx->thread_running) &&
3688+
!atomic_load(&ctx->init_error) &&
3689+
wait_count < 2000) {
36863690
usleep(1000); /* 1ms */
36873691
wait_count++;
36883692
}
36893693

3690-
if (!atomic_load(&ctx->thread_running)) {
3691-
/* Thread failed to start - check if there's an init error */
3692-
fprintf(stderr, "OWN_GIL thread failed to initialize after %d ms\n", wait_count);
3694+
if (atomic_load(&ctx->init_error) || !atomic_load(&ctx->thread_running)) {
3695+
/* Thread failed to start */
36933696
pthread_join(ctx->own_gil_thread, NULL);
36943697
enif_free_env(ctx->shared_env);
36953698
pthread_cond_destroy(&ctx->response_ready);

c_src/py_nif.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,9 @@ typedef struct {
855855
/** @brief True when worker thread is running */
856856
_Atomic bool thread_running;
857857

858+
/** @brief True if thread initialization failed */
859+
_Atomic bool init_error;
860+
858861
/** @brief True when shutdown has been requested */
859862
_Atomic bool shutdown_requested;
860863
#else

0 commit comments

Comments
 (0)