static PyObject * test_thread_state(PyObject *self, PyObject *args) { PyObject *fn; int success = 1; if (!PyArg_ParseTuple(args, "O:test_thread_state", &fn)) return NULL; if (!PyCallable_Check(fn)) { PyErr_Format(PyExc_TypeError, "'%s' object is not callable", fn->ob_type->tp_name); return NULL; } /* Ensure Python is set up for threading */ PyEval_InitThreads(); thread_done = PyThread_allocate_lock(); if (thread_done == NULL) return PyErr_NoMemory(); PyThread_acquire_lock(thread_done, 1); /* Start a new thread with our callback. */ PyThread_start_new_thread(_make_call_from_thread, fn); /* Make the callback with the thread lock held by this thread */ success &= _make_call(fn); /* Do it all again, but this time with the thread-lock released */ Py_BEGIN_ALLOW_THREADS success &= _make_call(fn); PyThread_acquire_lock(thread_done, 1); /* wait for thread to finish */ Py_END_ALLOW_THREADS /* And once more with and without a thread XXX - should use a lock and work out exactly what we are trying to test <wink> */ Py_BEGIN_ALLOW_THREADS PyThread_start_new_thread(_make_call_from_thread, fn); success &= _make_call(fn); PyThread_acquire_lock(thread_done, 1); /* wait for thread to finish */ Py_END_ALLOW_THREADS /* Release lock we acquired above. This is required on HP-UX. */ PyThread_release_lock(thread_done); PyThread_free_lock(thread_done); if (!success) return NULL; Py_RETURN_NONE; }
static int test_bpo20891(void) { /* bpo-20891: Calling PyGILState_Ensure in a non-Python thread before calling PyEval_InitThreads() must not crash. PyGILState_Ensure() must call PyEval_InitThreads() for us in this case. */ PyThread_type_lock lock = PyThread_allocate_lock(); if (!lock) { fprintf(stderr, "PyThread_allocate_lock failed!"); return 1; } _testembed_Py_Initialize(); unsigned long thrd = PyThread_start_new_thread(bpo20891_thread, &lock); if (thrd == PYTHREAD_INVALID_THREAD_ID) { fprintf(stderr, "PyThread_start_new_thread failed!"); return 1; } PyThread_acquire_lock(lock, WAIT_LOCK); Py_BEGIN_ALLOW_THREADS /* wait until the thread exit */ PyThread_acquire_lock(lock, WAIT_LOCK); Py_END_ALLOW_THREADS PyThread_free_lock(lock); return 0; }
static PyObject* faulthandler_dump_traceback_later(PyObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"timeout", "repeat", "file", "exit", NULL}; double timeout; PY_TIMEOUT_T timeout_ms; int repeat = 0; PyObject *file = NULL; int fd; int exit = 0; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "d|iOi:dump_tracebacks_later", kwlist, &timeout, &repeat, &file, &exit)) return NULL; timeout *= 1e6; if (timeout >= (double) PY_TIMEOUT_MAX) { PyErr_SetString(PyExc_OverflowError, "timeout value is too large"); return NULL; } timeout_ms = (PY_TIMEOUT_T)timeout; if (timeout_ms <= 0) { PyErr_SetString(PyExc_ValueError, "timeout must be greater than 0"); return NULL; } file = faulthandler_get_fileno(file, &fd); if (file == NULL) return NULL; /* Cancel previous thread, if running */ faulthandler_cancel_dump_tracebacks_later(); Py_XDECREF(thread.file); Py_INCREF(file); thread.file = file; thread.fd = fd; thread.timeout_ms = timeout_ms; thread.repeat = repeat; thread.interp = PyThreadState_Get()->interp; thread.exit = exit; /* Arm these locks to serve as events when released */ PyThread_acquire_lock(thread.join_event, 1); PyThread_acquire_lock(thread.cancel_event, 1); thread.running = 1; if (PyThread_start_new_thread(faulthandler_thread, NULL) == -1) { thread.running = 0; PyThread_release_lock(thread.join_event); PyThread_release_lock(thread.cancel_event); Py_CLEAR(thread.file); PyErr_SetString(PyExc_RuntimeError, "unable to start watchdog thread"); return NULL; } Py_RETURN_NONE; }
static PyObject * thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs) { PyObject *func, *args, *keyw = NULL; struct bootstate *boot; long ident; if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3, &func, &args, &keyw)) return NULL; if (!PyCallable_Check(func)) { PyErr_SetString(PyExc_TypeError, "first arg must be callable"); return NULL; } if (!PyTuple_Check(args)) { PyErr_SetString(PyExc_TypeError, "2nd arg must be a tuple"); return NULL; } if (keyw != NULL && !PyDict_Check(keyw)) { PyErr_SetString(PyExc_TypeError, "optional 3rd arg must be a dictionary"); return NULL; } boot = PyMem_NEW(struct bootstate, 1); if (boot == NULL) return PyErr_NoMemory(); boot->interp = PyThreadState_GET()->interp; boot->func = func; boot->args = args; boot->keyw = keyw; boot->tstate = _PyThreadState_Prealloc(boot->interp); if (boot->tstate == NULL) { PyMem_DEL(boot); return PyErr_NoMemory(); } Py_INCREF(func); Py_INCREF(args); Py_XINCREF(keyw); PyEval_InitThreads(); /* Start the interpreter's thread-awareness */ ident = PyThread_start_new_thread(t_bootstrap, (void*) boot); if (ident == -1) { PyErr_SetString(ThreadError, "can't start new thread"); Py_DECREF(func); Py_DECREF(args); Py_XDECREF(keyw); PyThreadState_Clear(boot->tstate); PyMem_DEL(boot); return NULL; } return PyLong_FromLong(ident); }
static int GPIO_set_callback(GPIO *self, PyObject *val, void *closure) { long ident; PyObject * tmp, *cb; struct poll_cb_info * poll_cb; cb = NULL; poll_cb = get_poll_cb(self->fd_val); if (poll_cb != NULL) cb = poll_cb->callback; if ( cb == val ) return 0; if ( cb != NULL ) { // printf("pre-del:\n"); // dump_poll_cb(); del_poll_cb(self->fd_val); // printf("post-del:\n"); // dump_poll_cb(); Py_DECREF( cb ); } if ( val == Py_None ) return 0; if ( !PyCallable_Check( val ) != 0 ) { PyErr_SetString(PyExc_TypeError, "set_callback: parameter must be a callable python object (function, method, class) or None"); return -1; } Py_INCREF(val); // printf("pre-add:\n"); // dump_poll_cb(); add_poll_cb(val, self->fd_val); // printf("post-add:\n"); // dump_poll_cb(); if (global_nfds == 1 && lock == NULL) { PyEval_InitThreads(); /* Start the interpreter's thread-awareness */ interp = PyThreadState_Get()->interp; lock = PyThread_allocate_lock(); if (lock == NULL) return PyErr_NoMemory(); ident = PyThread_start_new_thread(t_bootstrap, (void*) self); if (ident == -1) { PyErr_SetString(PyExc_RuntimeError, "can't start new thread"); return -1; } } return 0; }
bool PyThread::start() { PyScopedLock l(lock); if(running) return true; stopSignal = false; bool expectedRunning = false; if(running.compare_exchange_strong(expectedRunning, true)) { ident = PyThread_start_new_thread(PyThread_thread, this); if(ident == -1) { running = false; return false; } } else assert(false); return true; }
static PyObject* faulthandler_dump_tracebacks_later(PyObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"timeout", "repeat", "file", "exit", NULL}; double timeout; PY_TIMEOUT_T timeout_us; int repeat = 0; PyObject *file = NULL; int fd; int exit = 0; PyThreadState *tstate; char *header; size_t header_len; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "d|iOi:dump_tracebacks_later", kwlist, &timeout, &repeat, &file, &exit)) return NULL; if ((timeout * 1e6) >= (double) PY_TIMEOUT_MAX) { PyErr_SetString(PyExc_OverflowError, "timeout value is too large"); return NULL; } timeout_us = (PY_TIMEOUT_T)(timeout * 1e6); if (timeout_us <= 0) { PyErr_SetString(PyExc_ValueError, "timeout must be greater than 0"); return NULL; } tstate = get_thread_state(); if (tstate == NULL) return NULL; file = faulthandler_get_fileno(file, &fd); if (file == NULL) return NULL; /* format the timeout */ header = format_timeout(timeout); if (header == NULL) return PyErr_NoMemory(); header_len = strlen(header); /* Cancel previous thread, if running */ cancel_dump_tracebacks_later(); Py_XDECREF(thread.file); Py_INCREF(file); thread.file = file; thread.fd = fd; thread.timeout_us = timeout_us; thread.repeat = repeat; thread.interp = tstate->interp; thread.exit = exit; thread.header = header; thread.header_len = header_len; /* Arm these locks to serve as events when released */ PyThread_acquire_lock(thread.running, 1); if (PyThread_start_new_thread(faulthandler_thread, NULL) == -1) { PyThread_release_lock(thread.running); Py_CLEAR(thread.file); free(header); thread.header = NULL; PyErr_SetString(PyExc_RuntimeError, "unable to start watchdog thread"); return NULL; } Py_RETURN_NONE; }