| 94 | static PyMethodDef callDispatchFuncDef = {"JsDispatchCallable", callDispatchFunc, METH_NOARGS, NULL}; |
| 95 | |
| 96 | bool JobQueue::dispatchToEventLoop(void *closure, JS::Dispatchable *dispatchable) { |
| 97 | JSContext *cx = (JSContext *)closure; |
| 98 | |
| 99 | // The `dispatchToEventLoop` function is running in a helper thread, so |
| 100 | // we must acquire the Python GIL (global interpreter lock) |
| 101 | // see https://docs.python.org/3/c-api/init.html#non-python-created-threads |
| 102 | PyGILState_STATE gstate = PyGILState_Ensure(); |
| 103 | |
| 104 | PyObject *dispatchFuncTuple = PyTuple_Pack(2, PyLong_FromVoidPtr(cx), PyLong_FromVoidPtr(dispatchable)); |
| 105 | PyObject *pyFunc = PyCFunction_New(&callDispatchFuncDef, dispatchFuncTuple); |
| 106 | |
| 107 | // Avoid using the current, JS helper thread to send jobs to event-loop as it may cause deadlock |
| 108 | PyThread_start_new_thread((void (*)(void *)) &sendJobToMainLoop, pyFunc); |
| 109 | |
| 110 | PyGILState_Release(gstate); |
| 111 | return true; |
| 112 | } |
| 113 | |
| 114 | bool sendJobToMainLoop(PyObject *pyFunc) { |
| 115 | PyGILState_STATE gstate = PyGILState_Ensure(); |
nothing calls this directly
no outgoing calls
no test coverage detected