Skip to content

Commit dd4338d

Browse files
committed
Fix executor routing for multi-executor and free-threaded modes
The executor_enqueue function was always routing requests to the single executor queue, but multi-executor mode uses separate per-executor queues and free-threaded mode requires direct execution without an executor. This fix routes requests based on execution mode: - FREE_THREADED: Execute directly with PyGILState management - MULTI_EXECUTOR: Route to multi-executor pool via select_executor - SUBINTERP/fallback: Use single executor queue This fixes the timeout issues on FreeBSD Python 3.11 and free-threaded Python 3.13t where requests were being enqueued but never processed.
1 parent 587a06a commit dd4338d

File tree

1 file changed

+36
-1
lines changed

1 file changed

+36
-1
lines changed

c_src/py_nif.c

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2940,9 +2940,44 @@ static void *executor_thread_main(void *arg) {
29402940
}
29412941

29422942
/**
2943-
* Enqueue a request to the executor thread.
2943+
* Enqueue a request to the appropriate executor based on execution mode.
2944+
* Routes to multi-executor pool, single executor, or executes directly.
29442945
*/
29452946
static void executor_enqueue(py_request_t *req) {
2947+
switch (g_execution_mode) {
2948+
#ifdef HAVE_FREE_THREADED
2949+
case PY_MODE_FREE_THREADED:
2950+
/* Execute directly in free-threaded mode - no executor needed */
2951+
{
2952+
PyGILState_STATE gstate = PyGILState_Ensure();
2953+
process_request(req);
2954+
PyGILState_Release(gstate);
2955+
/* Signal completion immediately */
2956+
pthread_mutex_lock(&req->mutex);
2957+
req->completed = true;
2958+
pthread_cond_signal(&req->cond);
2959+
pthread_mutex_unlock(&req->mutex);
2960+
}
2961+
return;
2962+
#endif
2963+
2964+
case PY_MODE_MULTI_EXECUTOR:
2965+
if (g_multi_executor_initialized) {
2966+
/* Route to multi-executor pool */
2967+
int exec_id = select_executor();
2968+
multi_executor_enqueue(exec_id, req);
2969+
return;
2970+
}
2971+
/* Fall through to single executor if multi not initialized */
2972+
break;
2973+
2974+
case PY_MODE_SUBINTERP:
2975+
default:
2976+
/* Use single executor */
2977+
break;
2978+
}
2979+
2980+
/* Single executor queue */
29462981
pthread_mutex_lock(&g_executor_mutex);
29472982
req->next = NULL;
29482983
if (g_executor_queue_tail == NULL) {

0 commit comments

Comments
 (0)