• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Thread module */
2 /* Interface to Sjoerd's portable C thread library */
3 
4 #include "Python.h"
5 #include "pycore_interp.h"        // _PyInterpreterState.threads.count
6 #include "pycore_lock.h"
7 #include "pycore_moduleobject.h"  // _PyModule_GetState()
8 #include "pycore_modsupport.h"    // _PyArg_NoKeywords()
9 #include "pycore_pylifecycle.h"
10 #include "pycore_pystate.h"       // _PyThreadState_SetCurrent()
11 #include "pycore_sysmodule.h"     // _PySys_GetAttr()
12 #include "pycore_time.h"          // _PyTime_FromSeconds()
13 #include "pycore_weakref.h"       // _PyWeakref_GET_REF()
14 
15 #include <stddef.h>               // offsetof()
16 #ifdef HAVE_SIGNAL_H
17 #  include <signal.h>             // SIGINT
18 #endif
19 
20 // ThreadError is just an alias to PyExc_RuntimeError
21 #define ThreadError PyExc_RuntimeError
22 
23 // Forward declarations
24 static struct PyModuleDef thread_module;
25 
26 // Module state
27 typedef struct {
28     PyTypeObject *excepthook_type;
29     PyTypeObject *lock_type;
30     PyTypeObject *local_type;
31     PyTypeObject *local_dummy_type;
32     PyTypeObject *thread_handle_type;
33 
34     // Linked list of handles to all non-daemon threads created by the
35     // threading module. We wait for these to finish at shutdown.
36     struct llist_node shutdown_handles;
37 } thread_module_state;
38 
39 static inline thread_module_state*
get_thread_state(PyObject * module)40 get_thread_state(PyObject *module)
41 {
42     void *state = _PyModule_GetState(module);
43     assert(state != NULL);
44     return (thread_module_state *)state;
45 }
46 
47 // _ThreadHandle type
48 
49 // Handles state transitions according to the following diagram:
50 //
51 //     NOT_STARTED -> STARTING -> RUNNING -> DONE
52 //                       |                    ^
53 //                       |                    |
54 //                       +----- error --------+
55 typedef enum {
56     THREAD_HANDLE_NOT_STARTED = 1,
57     THREAD_HANDLE_STARTING = 2,
58     THREAD_HANDLE_RUNNING = 3,
59     THREAD_HANDLE_DONE = 4,
60 } ThreadHandleState;
61 
62 // A handle to wait for thread completion.
63 //
64 // This may be used to wait for threads that were spawned by the threading
65 // module as well as for the "main" thread of the threading module. In the
66 // former case an OS thread, identified by the `os_handle` field, will be
67 // associated with the handle. The handle "owns" this thread and ensures that
68 // the thread is either joined or detached after the handle is destroyed.
69 //
70 // Joining the handle is idempotent; the underlying OS thread, if any, is
71 // joined or detached only once. Concurrent join operations are serialized
72 // until it is their turn to execute or an earlier operation completes
73 // successfully. Once a join has completed successfully all future joins
74 // complete immediately.
75 //
76 // This must be separately reference counted because it may be destroyed
77 // in `thread_run()` after the PyThreadState has been destroyed.
78 typedef struct {
79     struct llist_node node;  // linked list node (see _pythread_runtime_state)
80 
81     // linked list node (see thread_module_state)
82     struct llist_node shutdown_node;
83 
84     // The `ident`, `os_handle`, `has_os_handle`, and `state` fields are
85     // protected by `mutex`.
86     PyThread_ident_t ident;
87     PyThread_handle_t os_handle;
88     int has_os_handle;
89 
90     // Holds a value from the `ThreadHandleState` enum.
91     int state;
92 
93     PyMutex mutex;
94 
95     // Set immediately before `thread_run` returns to indicate that the OS
96     // thread is about to exit. This is used to avoid false positives when
97     // detecting self-join attempts. See the comment in `ThreadHandle_join()`
98     // for a more detailed explanation.
99     PyEvent thread_is_exiting;
100 
101     // Serializes calls to `join` and `set_done`.
102     _PyOnceFlag once;
103 
104     Py_ssize_t refcount;
105 } ThreadHandle;
106 
107 static inline int
get_thread_handle_state(ThreadHandle * handle)108 get_thread_handle_state(ThreadHandle *handle)
109 {
110     PyMutex_Lock(&handle->mutex);
111     int state = handle->state;
112     PyMutex_Unlock(&handle->mutex);
113     return state;
114 }
115 
116 static inline void
set_thread_handle_state(ThreadHandle * handle,ThreadHandleState state)117 set_thread_handle_state(ThreadHandle *handle, ThreadHandleState state)
118 {
119     PyMutex_Lock(&handle->mutex);
120     handle->state = state;
121     PyMutex_Unlock(&handle->mutex);
122 }
123 
124 static PyThread_ident_t
ThreadHandle_ident(ThreadHandle * handle)125 ThreadHandle_ident(ThreadHandle *handle)
126 {
127     PyMutex_Lock(&handle->mutex);
128     PyThread_ident_t ident = handle->ident;
129     PyMutex_Unlock(&handle->mutex);
130     return ident;
131 }
132 
133 static int
ThreadHandle_get_os_handle(ThreadHandle * handle,PyThread_handle_t * os_handle)134 ThreadHandle_get_os_handle(ThreadHandle *handle, PyThread_handle_t *os_handle)
135 {
136     PyMutex_Lock(&handle->mutex);
137     int has_os_handle = handle->has_os_handle;
138     if (has_os_handle) {
139         *os_handle = handle->os_handle;
140     }
141     PyMutex_Unlock(&handle->mutex);
142     return has_os_handle;
143 }
144 
145 static void
add_to_shutdown_handles(thread_module_state * state,ThreadHandle * handle)146 add_to_shutdown_handles(thread_module_state *state, ThreadHandle *handle)
147 {
148     HEAD_LOCK(&_PyRuntime);
149     llist_insert_tail(&state->shutdown_handles, &handle->shutdown_node);
150     HEAD_UNLOCK(&_PyRuntime);
151 }
152 
153 static void
clear_shutdown_handles(thread_module_state * state)154 clear_shutdown_handles(thread_module_state *state)
155 {
156     HEAD_LOCK(&_PyRuntime);
157     struct llist_node *node;
158     llist_for_each_safe(node, &state->shutdown_handles) {
159         llist_remove(node);
160     }
161     HEAD_UNLOCK(&_PyRuntime);
162 }
163 
164 static void
remove_from_shutdown_handles(ThreadHandle * handle)165 remove_from_shutdown_handles(ThreadHandle *handle)
166 {
167     HEAD_LOCK(&_PyRuntime);
168     if (handle->shutdown_node.next != NULL) {
169         llist_remove(&handle->shutdown_node);
170     }
171     HEAD_UNLOCK(&_PyRuntime);
172 }
173 
174 static ThreadHandle *
ThreadHandle_new(void)175 ThreadHandle_new(void)
176 {
177     ThreadHandle *self =
178         (ThreadHandle *)PyMem_RawCalloc(1, sizeof(ThreadHandle));
179     if (self == NULL) {
180         PyErr_NoMemory();
181         return NULL;
182     }
183     self->ident = 0;
184     self->os_handle = 0;
185     self->has_os_handle = 0;
186     self->thread_is_exiting = (PyEvent){0};
187     self->mutex = (PyMutex){_Py_UNLOCKED};
188     self->once = (_PyOnceFlag){0};
189     self->state = THREAD_HANDLE_NOT_STARTED;
190     self->refcount = 1;
191 
192     HEAD_LOCK(&_PyRuntime);
193     llist_insert_tail(&_PyRuntime.threads.handles, &self->node);
194     HEAD_UNLOCK(&_PyRuntime);
195 
196     return self;
197 }
198 
199 static void
ThreadHandle_incref(ThreadHandle * self)200 ThreadHandle_incref(ThreadHandle *self)
201 {
202     _Py_atomic_add_ssize(&self->refcount, 1);
203 }
204 
205 static int
detach_thread(ThreadHandle * self)206 detach_thread(ThreadHandle *self)
207 {
208     if (!self->has_os_handle) {
209         return 0;
210     }
211     // This is typically short so no need to release the GIL
212     if (PyThread_detach_thread(self->os_handle)) {
213         fprintf(stderr, "detach_thread: failed detaching thread\n");
214         return -1;
215     }
216     return 0;
217 }
218 
219 // NB: This may be called after the PyThreadState in `thread_run` has been
220 // deleted; it cannot call anything that relies on a valid PyThreadState
221 // existing.
222 static void
ThreadHandle_decref(ThreadHandle * self)223 ThreadHandle_decref(ThreadHandle *self)
224 {
225     if (_Py_atomic_add_ssize(&self->refcount, -1) > 1) {
226         return;
227     }
228 
229     // Remove ourself from the global list of handles
230     HEAD_LOCK(&_PyRuntime);
231     if (self->node.next != NULL) {
232         llist_remove(&self->node);
233     }
234     HEAD_UNLOCK(&_PyRuntime);
235 
236     assert(self->shutdown_node.next == NULL);
237 
238     // It's safe to access state non-atomically:
239     //   1. This is the destructor; nothing else holds a reference.
240     //   2. The refcount going to zero is a "synchronizes-with" event; all
241     //      changes from other threads are visible.
242     if (self->state == THREAD_HANDLE_RUNNING && !detach_thread(self)) {
243         self->state = THREAD_HANDLE_DONE;
244     }
245 
246     PyMem_RawFree(self);
247 }
248 
249 void
_PyThread_AfterFork(struct _pythread_runtime_state * state)250 _PyThread_AfterFork(struct _pythread_runtime_state *state)
251 {
252     // gh-115035: We mark ThreadHandles as not joinable early in the child's
253     // after-fork handler. We do this before calling any Python code to ensure
254     // that it happens before any ThreadHandles are deallocated, such as by a
255     // GC cycle.
256     PyThread_ident_t current = PyThread_get_thread_ident_ex();
257 
258     struct llist_node *node;
259     llist_for_each_safe(node, &state->handles) {
260         ThreadHandle *handle = llist_data(node, ThreadHandle, node);
261         if (handle->ident == current) {
262             continue;
263         }
264 
265         // Mark all threads as done. Any attempts to join or detach the
266         // underlying OS thread (if any) could crash. We are the only thread;
267         // it's safe to set this non-atomically.
268         handle->state = THREAD_HANDLE_DONE;
269         handle->once = (_PyOnceFlag){_Py_ONCE_INITIALIZED};
270         handle->mutex = (PyMutex){_Py_UNLOCKED};
271         _PyEvent_Notify(&handle->thread_is_exiting);
272         llist_remove(node);
273         remove_from_shutdown_handles(handle);
274     }
275 }
276 
277 // bootstate is used to "bootstrap" new threads. Any arguments needed by
278 // `thread_run()`, which can only take a single argument due to platform
279 // limitations, are contained in bootstate.
280 struct bootstate {
281     PyThreadState *tstate;
282     PyObject *func;
283     PyObject *args;
284     PyObject *kwargs;
285     ThreadHandle *handle;
286     PyEvent handle_ready;
287 };
288 
289 static void
thread_bootstate_free(struct bootstate * boot,int decref)290 thread_bootstate_free(struct bootstate *boot, int decref)
291 {
292     if (decref) {
293         Py_DECREF(boot->func);
294         Py_DECREF(boot->args);
295         Py_XDECREF(boot->kwargs);
296     }
297     ThreadHandle_decref(boot->handle);
298     PyMem_RawFree(boot);
299 }
300 
301 static void
thread_run(void * boot_raw)302 thread_run(void *boot_raw)
303 {
304     struct bootstate *boot = (struct bootstate *) boot_raw;
305     PyThreadState *tstate = boot->tstate;
306 
307     // Wait until the handle is marked as running
308     PyEvent_Wait(&boot->handle_ready);
309 
310     // `handle` needs to be manipulated after bootstate has been freed
311     ThreadHandle *handle = boot->handle;
312     ThreadHandle_incref(handle);
313 
314     // gh-108987: If _thread.start_new_thread() is called before or while
315     // Python is being finalized, thread_run() can called *after*.
316     // _PyRuntimeState_SetFinalizing() is called. At this point, all Python
317     // threads must exit, except of the thread calling Py_Finalize() which
318     // holds the GIL and must not exit.
319     //
320     // At this stage, tstate can be a dangling pointer (point to freed memory),
321     // it's ok to call _PyThreadState_MustExit() with a dangling pointer.
322     if (_PyThreadState_MustExit(tstate)) {
323         // Don't call PyThreadState_Clear() nor _PyThreadState_DeleteCurrent().
324         // These functions are called on tstate indirectly by Py_Finalize()
325         // which calls _PyInterpreterState_Clear().
326         //
327         // Py_DECREF() cannot be called because the GIL is not held: leak
328         // references on purpose. Python is being finalized anyway.
329         thread_bootstate_free(boot, 0);
330         goto exit;
331     }
332 
333     _PyThreadState_Bind(tstate);
334     PyEval_AcquireThread(tstate);
335     _Py_atomic_add_ssize(&tstate->interp->threads.count, 1);
336 
337     PyObject *res = PyObject_Call(boot->func, boot->args, boot->kwargs);
338     if (res == NULL) {
339         if (PyErr_ExceptionMatches(PyExc_SystemExit))
340             /* SystemExit is ignored silently */
341             PyErr_Clear();
342         else {
343             PyErr_FormatUnraisable(
344                 "Exception ignored in thread started by %R", boot->func);
345         }
346     }
347     else {
348         Py_DECREF(res);
349     }
350 
351     thread_bootstate_free(boot, 1);
352 
353     _Py_atomic_add_ssize(&tstate->interp->threads.count, -1);
354     PyThreadState_Clear(tstate);
355     _PyThreadState_DeleteCurrent(tstate);
356 
357 exit:
358     // Don't need to wait for this thread anymore
359     remove_from_shutdown_handles(handle);
360 
361     _PyEvent_Notify(&handle->thread_is_exiting);
362     ThreadHandle_decref(handle);
363 
364     // bpo-44434: Don't call explicitly PyThread_exit_thread(). On Linux with
365     // the glibc, pthread_exit() can abort the whole process if dlopen() fails
366     // to open the libgcc_s.so library (ex: EMFILE error).
367     return;
368 }
369 
370 static int
force_done(ThreadHandle * handle)371 force_done(ThreadHandle *handle)
372 {
373     assert(get_thread_handle_state(handle) == THREAD_HANDLE_STARTING);
374     _PyEvent_Notify(&handle->thread_is_exiting);
375     set_thread_handle_state(handle, THREAD_HANDLE_DONE);
376     return 0;
377 }
378 
379 static int
ThreadHandle_start(ThreadHandle * self,PyObject * func,PyObject * args,PyObject * kwargs)380 ThreadHandle_start(ThreadHandle *self, PyObject *func, PyObject *args,
381                    PyObject *kwargs)
382 {
383     // Mark the handle as starting to prevent any other threads from doing so
384     PyMutex_Lock(&self->mutex);
385     if (self->state != THREAD_HANDLE_NOT_STARTED) {
386         PyMutex_Unlock(&self->mutex);
387         PyErr_SetString(ThreadError, "thread already started");
388         return -1;
389     }
390     self->state = THREAD_HANDLE_STARTING;
391     PyMutex_Unlock(&self->mutex);
392 
393     // Do all the heavy lifting outside of the mutex. All other operations on
394     // the handle should fail since the handle is in the starting state.
395 
396     // gh-109795: Use PyMem_RawMalloc() instead of PyMem_Malloc(),
397     // because it should be possible to call thread_bootstate_free()
398     // without holding the GIL.
399     struct bootstate *boot = PyMem_RawMalloc(sizeof(struct bootstate));
400     if (boot == NULL) {
401         PyErr_NoMemory();
402         goto start_failed;
403     }
404     PyInterpreterState *interp = _PyInterpreterState_GET();
405     boot->tstate = _PyThreadState_New(interp, _PyThreadState_WHENCE_THREADING);
406     if (boot->tstate == NULL) {
407         PyMem_RawFree(boot);
408         if (!PyErr_Occurred()) {
409             PyErr_NoMemory();
410         }
411         goto start_failed;
412     }
413     boot->func = Py_NewRef(func);
414     boot->args = Py_NewRef(args);
415     boot->kwargs = Py_XNewRef(kwargs);
416     boot->handle = self;
417     ThreadHandle_incref(self);
418     boot->handle_ready = (PyEvent){0};
419 
420     PyThread_ident_t ident;
421     PyThread_handle_t os_handle;
422     if (PyThread_start_joinable_thread(thread_run, boot, &ident, &os_handle)) {
423         PyThreadState_Clear(boot->tstate);
424         PyThreadState_Delete(boot->tstate);
425         thread_bootstate_free(boot, 1);
426         PyErr_SetString(ThreadError, "can't start new thread");
427         goto start_failed;
428     }
429 
430     // Mark the handle running
431     PyMutex_Lock(&self->mutex);
432     assert(self->state == THREAD_HANDLE_STARTING);
433     self->ident = ident;
434     self->has_os_handle = 1;
435     self->os_handle = os_handle;
436     self->state = THREAD_HANDLE_RUNNING;
437     PyMutex_Unlock(&self->mutex);
438 
439     // Unblock the thread
440     _PyEvent_Notify(&boot->handle_ready);
441 
442     return 0;
443 
444 start_failed:
445     _PyOnceFlag_CallOnce(&self->once, (_Py_once_fn_t *)force_done, self);
446     return -1;
447 }
448 
449 static int
join_thread(ThreadHandle * handle)450 join_thread(ThreadHandle *handle)
451 {
452     assert(get_thread_handle_state(handle) == THREAD_HANDLE_RUNNING);
453     PyThread_handle_t os_handle;
454     if (ThreadHandle_get_os_handle(handle, &os_handle)) {
455         int err = 0;
456         Py_BEGIN_ALLOW_THREADS
457         err = PyThread_join_thread(os_handle);
458         Py_END_ALLOW_THREADS
459         if (err) {
460             PyErr_SetString(ThreadError, "Failed joining thread");
461             return -1;
462         }
463     }
464     set_thread_handle_state(handle, THREAD_HANDLE_DONE);
465     return 0;
466 }
467 
468 static int
check_started(ThreadHandle * self)469 check_started(ThreadHandle *self)
470 {
471     ThreadHandleState state = get_thread_handle_state(self);
472     if (state < THREAD_HANDLE_RUNNING) {
473         PyErr_SetString(ThreadError, "thread not started");
474         return -1;
475     }
476     return 0;
477 }
478 
479 static int
ThreadHandle_join(ThreadHandle * self,PyTime_t timeout_ns)480 ThreadHandle_join(ThreadHandle *self, PyTime_t timeout_ns)
481 {
482     if (check_started(self) < 0) {
483         return -1;
484     }
485 
486     // We want to perform this check outside of the `_PyOnceFlag` to prevent
487     // deadlock in the scenario where another thread joins us and we then
488     // attempt to join ourselves. However, it's not safe to check thread
489     // identity once the handle's os thread has finished. We may end up reusing
490     // the identity stored in the handle and erroneously think we are
491     // attempting to join ourselves.
492     //
493     // To work around this, we set `thread_is_exiting` immediately before
494     // `thread_run` returns.  We can be sure that we are not attempting to join
495     // ourselves if the handle's thread is about to exit.
496     if (!_PyEvent_IsSet(&self->thread_is_exiting) &&
497         ThreadHandle_ident(self) == PyThread_get_thread_ident_ex()) {
498         // PyThread_join_thread() would deadlock or error out.
499         PyErr_SetString(ThreadError, "Cannot join current thread");
500         return -1;
501     }
502 
503     // Wait until the deadline for the thread to exit.
504     PyTime_t deadline = timeout_ns != -1 ? _PyDeadline_Init(timeout_ns) : 0;
505     int detach = 1;
506     while (!PyEvent_WaitTimed(&self->thread_is_exiting, timeout_ns, detach)) {
507         if (deadline) {
508             // _PyDeadline_Get will return a negative value if the deadline has
509             // been exceeded.
510             timeout_ns = Py_MAX(_PyDeadline_Get(deadline), 0);
511         }
512 
513         if (timeout_ns) {
514             // Interrupted
515             if (Py_MakePendingCalls() < 0) {
516                 return -1;
517             }
518         }
519         else {
520             // Timed out
521             return 0;
522         }
523     }
524 
525     if (_PyOnceFlag_CallOnce(&self->once, (_Py_once_fn_t *)join_thread,
526                              self) == -1) {
527         return -1;
528     }
529     assert(get_thread_handle_state(self) == THREAD_HANDLE_DONE);
530     return 0;
531 }
532 
533 static int
set_done(ThreadHandle * handle)534 set_done(ThreadHandle *handle)
535 {
536     assert(get_thread_handle_state(handle) == THREAD_HANDLE_RUNNING);
537     if (detach_thread(handle) < 0) {
538         PyErr_SetString(ThreadError, "failed detaching handle");
539         return -1;
540     }
541     _PyEvent_Notify(&handle->thread_is_exiting);
542     set_thread_handle_state(handle, THREAD_HANDLE_DONE);
543     return 0;
544 }
545 
546 static int
ThreadHandle_set_done(ThreadHandle * self)547 ThreadHandle_set_done(ThreadHandle *self)
548 {
549     if (check_started(self) < 0) {
550         return -1;
551     }
552 
553     if (_PyOnceFlag_CallOnce(&self->once, (_Py_once_fn_t *)set_done, self) ==
554         -1) {
555         return -1;
556     }
557     assert(get_thread_handle_state(self) == THREAD_HANDLE_DONE);
558     return 0;
559 }
560 
561 // A wrapper around a ThreadHandle.
562 typedef struct {
563     PyObject_HEAD
564 
565     ThreadHandle *handle;
566 } PyThreadHandleObject;
567 
568 static PyThreadHandleObject *
PyThreadHandleObject_new(PyTypeObject * type)569 PyThreadHandleObject_new(PyTypeObject *type)
570 {
571     ThreadHandle *handle = ThreadHandle_new();
572     if (handle == NULL) {
573         return NULL;
574     }
575 
576     PyThreadHandleObject *self =
577         (PyThreadHandleObject *)type->tp_alloc(type, 0);
578     if (self == NULL) {
579         ThreadHandle_decref(handle);
580         return NULL;
581     }
582 
583     self->handle = handle;
584 
585     return self;
586 }
587 
588 static PyObject *
PyThreadHandleObject_tp_new(PyTypeObject * type,PyObject * args,PyObject * kwds)589 PyThreadHandleObject_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
590 {
591     return (PyObject *)PyThreadHandleObject_new(type);
592 }
593 
594 static int
PyThreadHandleObject_traverse(PyThreadHandleObject * self,visitproc visit,void * arg)595 PyThreadHandleObject_traverse(PyThreadHandleObject *self, visitproc visit,
596                               void *arg)
597 {
598     Py_VISIT(Py_TYPE(self));
599     return 0;
600 }
601 
602 static void
PyThreadHandleObject_dealloc(PyThreadHandleObject * self)603 PyThreadHandleObject_dealloc(PyThreadHandleObject *self)
604 {
605     PyObject_GC_UnTrack(self);
606     PyTypeObject *tp = Py_TYPE(self);
607     ThreadHandle_decref(self->handle);
608     tp->tp_free(self);
609     Py_DECREF(tp);
610 }
611 
612 static PyObject *
PyThreadHandleObject_repr(PyThreadHandleObject * self)613 PyThreadHandleObject_repr(PyThreadHandleObject *self)
614 {
615     PyThread_ident_t ident = ThreadHandle_ident(self->handle);
616     return PyUnicode_FromFormat("<%s object: ident=%" PY_FORMAT_THREAD_IDENT_T ">",
617                                 Py_TYPE(self)->tp_name, ident);
618 }
619 
620 static PyObject *
PyThreadHandleObject_get_ident(PyThreadHandleObject * self,PyObject * Py_UNUSED (ignored))621 PyThreadHandleObject_get_ident(PyThreadHandleObject *self,
622                                PyObject *Py_UNUSED(ignored))
623 {
624     return PyLong_FromUnsignedLongLong(ThreadHandle_ident(self->handle));
625 }
626 
627 static PyObject *
PyThreadHandleObject_join(PyThreadHandleObject * self,PyObject * args)628 PyThreadHandleObject_join(PyThreadHandleObject *self, PyObject *args)
629 {
630     PyObject *timeout_obj = NULL;
631     if (!PyArg_ParseTuple(args, "|O:join", &timeout_obj)) {
632         return NULL;
633     }
634 
635     PyTime_t timeout_ns = -1;
636     if (timeout_obj != NULL && timeout_obj != Py_None) {
637         if (_PyTime_FromSecondsObject(&timeout_ns, timeout_obj,
638                                       _PyTime_ROUND_TIMEOUT) < 0) {
639             return NULL;
640         }
641     }
642 
643     if (ThreadHandle_join(self->handle, timeout_ns) < 0) {
644         return NULL;
645     }
646     Py_RETURN_NONE;
647 }
648 
649 static PyObject *
PyThreadHandleObject_is_done(PyThreadHandleObject * self,PyObject * Py_UNUSED (ignored))650 PyThreadHandleObject_is_done(PyThreadHandleObject *self,
651                              PyObject *Py_UNUSED(ignored))
652 {
653     if (_PyEvent_IsSet(&self->handle->thread_is_exiting)) {
654         Py_RETURN_TRUE;
655     }
656     else {
657         Py_RETURN_FALSE;
658     }
659 }
660 
661 static PyObject *
PyThreadHandleObject_set_done(PyThreadHandleObject * self,PyObject * Py_UNUSED (ignored))662 PyThreadHandleObject_set_done(PyThreadHandleObject *self,
663                               PyObject *Py_UNUSED(ignored))
664 {
665     if (ThreadHandle_set_done(self->handle) < 0) {
666         return NULL;
667     }
668     Py_RETURN_NONE;
669 }
670 
671 static PyGetSetDef ThreadHandle_getsetlist[] = {
672     {"ident", (getter)PyThreadHandleObject_get_ident, NULL, NULL},
673     {0},
674 };
675 
676 static PyMethodDef ThreadHandle_methods[] = {
677     {"join", (PyCFunction)PyThreadHandleObject_join, METH_VARARGS, NULL},
678     {"_set_done", (PyCFunction)PyThreadHandleObject_set_done, METH_NOARGS, NULL},
679     {"is_done", (PyCFunction)PyThreadHandleObject_is_done, METH_NOARGS, NULL},
680     {0, 0}
681 };
682 
683 static PyType_Slot ThreadHandle_Type_slots[] = {
684     {Py_tp_dealloc, (destructor)PyThreadHandleObject_dealloc},
685     {Py_tp_repr, (reprfunc)PyThreadHandleObject_repr},
686     {Py_tp_getset, ThreadHandle_getsetlist},
687     {Py_tp_traverse, PyThreadHandleObject_traverse},
688     {Py_tp_methods, ThreadHandle_methods},
689     {Py_tp_new, PyThreadHandleObject_tp_new},
690     {0, 0}
691 };
692 
693 static PyType_Spec ThreadHandle_Type_spec = {
694     "_thread._ThreadHandle",
695     sizeof(PyThreadHandleObject),
696     0,
697     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC,
698     ThreadHandle_Type_slots,
699 };
700 
701 /* Lock objects */
702 
703 typedef struct {
704     PyObject_HEAD
705     PyMutex lock;
706 } lockobject;
707 
708 static int
lock_traverse(lockobject * self,visitproc visit,void * arg)709 lock_traverse(lockobject *self, visitproc visit, void *arg)
710 {
711     Py_VISIT(Py_TYPE(self));
712     return 0;
713 }
714 
715 static void
lock_dealloc(lockobject * self)716 lock_dealloc(lockobject *self)
717 {
718     PyObject_GC_UnTrack(self);
719     PyObject_ClearWeakRefs((PyObject *) self);
720     PyTypeObject *tp = Py_TYPE(self);
721     tp->tp_free((PyObject*)self);
722     Py_DECREF(tp);
723 }
724 
725 static inline PyLockStatus
acquire_timed(PyThread_type_lock lock,PyTime_t timeout)726 acquire_timed(PyThread_type_lock lock, PyTime_t timeout)
727 {
728     return PyThread_acquire_lock_timed_with_retries(lock, timeout);
729 }
730 
731 static int
lock_acquire_parse_args(PyObject * args,PyObject * kwds,PyTime_t * timeout)732 lock_acquire_parse_args(PyObject *args, PyObject *kwds,
733                         PyTime_t *timeout)
734 {
735     char *kwlist[] = {"blocking", "timeout", NULL};
736     int blocking = 1;
737     PyObject *timeout_obj = NULL;
738     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|pO:acquire", kwlist,
739                                      &blocking, &timeout_obj))
740         return -1;
741 
742     // XXX Use PyThread_ParseTimeoutArg().
743 
744     const PyTime_t unset_timeout = _PyTime_FromSeconds(-1);
745     *timeout = unset_timeout;
746 
747     if (timeout_obj
748         && _PyTime_FromSecondsObject(timeout,
749                                      timeout_obj, _PyTime_ROUND_TIMEOUT) < 0)
750         return -1;
751 
752     if (!blocking && *timeout != unset_timeout ) {
753         PyErr_SetString(PyExc_ValueError,
754                         "can't specify a timeout for a non-blocking call");
755         return -1;
756     }
757     if (*timeout < 0 && *timeout != unset_timeout) {
758         PyErr_SetString(PyExc_ValueError,
759                         "timeout value must be a non-negative number");
760         return -1;
761     }
762     if (!blocking)
763         *timeout = 0;
764     else if (*timeout != unset_timeout) {
765         PyTime_t microseconds;
766 
767         microseconds = _PyTime_AsMicroseconds(*timeout, _PyTime_ROUND_TIMEOUT);
768         if (microseconds > PY_TIMEOUT_MAX) {
769             PyErr_SetString(PyExc_OverflowError,
770                             "timeout value is too large");
771             return -1;
772         }
773     }
774     return 0;
775 }
776 
777 static PyObject *
lock_PyThread_acquire_lock(lockobject * self,PyObject * args,PyObject * kwds)778 lock_PyThread_acquire_lock(lockobject *self, PyObject *args, PyObject *kwds)
779 {
780     PyTime_t timeout;
781     if (lock_acquire_parse_args(args, kwds, &timeout) < 0)
782         return NULL;
783 
784     PyLockStatus r = _PyMutex_LockTimed(&self->lock, timeout,
785                                         _PY_LOCK_HANDLE_SIGNALS | _PY_LOCK_DETACH);
786     if (r == PY_LOCK_INTR) {
787         return NULL;
788     }
789 
790     return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
791 }
792 
793 PyDoc_STRVAR(acquire_doc,
794 "acquire($self, /, blocking=True, timeout=-1)\n\
795 --\n\
796 \n\
797 Lock the lock.  Without argument, this blocks if the lock is already\n\
798 locked (even by the same thread), waiting for another thread to release\n\
799 the lock, and return True once the lock is acquired.\n\
800 With an argument, this will only block if the argument is true,\n\
801 and the return value reflects whether the lock is acquired.\n\
802 The blocking operation is interruptible.");
803 
804 PyDoc_STRVAR(acquire_lock_doc,
805 "acquire_lock($self, /, blocking=True, timeout=-1)\n\
806 --\n\
807 \n\
808 An obsolete synonym of acquire().");
809 
810 PyDoc_STRVAR(enter_doc,
811 "__enter__($self, /)\n\
812 --\n\
813 \n\
814 Lock the lock.");
815 
816 static PyObject *
lock_PyThread_release_lock(lockobject * self,PyObject * Py_UNUSED (ignored))817 lock_PyThread_release_lock(lockobject *self, PyObject *Py_UNUSED(ignored))
818 {
819     /* Sanity check: the lock must be locked */
820     if (_PyMutex_TryUnlock(&self->lock) < 0) {
821         PyErr_SetString(ThreadError, "release unlocked lock");
822         return NULL;
823     }
824 
825     Py_RETURN_NONE;
826 }
827 
828 PyDoc_STRVAR(release_doc,
829 "release($self, /)\n\
830 --\n\
831 \n\
832 Release the lock, allowing another thread that is blocked waiting for\n\
833 the lock to acquire the lock.  The lock must be in the locked state,\n\
834 but it needn't be locked by the same thread that unlocks it.");
835 
836 PyDoc_STRVAR(release_lock_doc,
837 "release_lock($self, /)\n\
838 --\n\
839 \n\
840 An obsolete synonym of release().");
841 
842 PyDoc_STRVAR(lock_exit_doc,
843 "__exit__($self, /, *exc_info)\n\
844 --\n\
845 \n\
846 Release the lock.");
847 
848 static PyObject *
lock_locked_lock(lockobject * self,PyObject * Py_UNUSED (ignored))849 lock_locked_lock(lockobject *self, PyObject *Py_UNUSED(ignored))
850 {
851     return PyBool_FromLong(PyMutex_IsLocked(&self->lock));
852 }
853 
854 PyDoc_STRVAR(locked_doc,
855 "locked($self, /)\n\
856 --\n\
857 \n\
858 Return whether the lock is in the locked state.");
859 
860 PyDoc_STRVAR(locked_lock_doc,
861 "locked_lock($self, /)\n\
862 --\n\
863 \n\
864 An obsolete synonym of locked().");
865 
866 static PyObject *
lock_repr(lockobject * self)867 lock_repr(lockobject *self)
868 {
869     return PyUnicode_FromFormat("<%s %s object at %p>",
870         PyMutex_IsLocked(&self->lock) ? "locked" : "unlocked", Py_TYPE(self)->tp_name, self);
871 }
872 
873 #ifdef HAVE_FORK
874 static PyObject *
lock__at_fork_reinit(lockobject * self,PyObject * Py_UNUSED (args))875 lock__at_fork_reinit(lockobject *self, PyObject *Py_UNUSED(args))
876 {
877     _PyMutex_at_fork_reinit(&self->lock);
878     Py_RETURN_NONE;
879 }
880 #endif  /* HAVE_FORK */
881 
882 static lockobject *newlockobject(PyObject *module);
883 
884 static PyObject *
lock_new(PyTypeObject * type,PyObject * args,PyObject * kwargs)885 lock_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
886 {
887     // convert to AC?
888     if (!_PyArg_NoKeywords("lock", kwargs)) {
889         goto error;
890     }
891     if (!_PyArg_CheckPositional("lock", PyTuple_GET_SIZE(args), 0, 0)) {
892         goto error;
893     }
894 
895     PyObject *module = PyType_GetModuleByDef(type, &thread_module);
896     assert(module != NULL);
897     return (PyObject *)newlockobject(module);
898 
899 error:
900     return NULL;
901 }
902 
903 
904 static PyMethodDef lock_methods[] = {
905     {"acquire_lock", _PyCFunction_CAST(lock_PyThread_acquire_lock),
906      METH_VARARGS | METH_KEYWORDS, acquire_lock_doc},
907     {"acquire",      _PyCFunction_CAST(lock_PyThread_acquire_lock),
908      METH_VARARGS | METH_KEYWORDS, acquire_doc},
909     {"release_lock", (PyCFunction)lock_PyThread_release_lock,
910      METH_NOARGS, release_lock_doc},
911     {"release",      (PyCFunction)lock_PyThread_release_lock,
912      METH_NOARGS, release_doc},
913     {"locked_lock",  (PyCFunction)lock_locked_lock,
914      METH_NOARGS, locked_lock_doc},
915     {"locked",       (PyCFunction)lock_locked_lock,
916      METH_NOARGS, locked_doc},
917     {"__enter__",    _PyCFunction_CAST(lock_PyThread_acquire_lock),
918      METH_VARARGS | METH_KEYWORDS, enter_doc},
919     {"__exit__",    (PyCFunction)lock_PyThread_release_lock,
920      METH_VARARGS, lock_exit_doc},
921 #ifdef HAVE_FORK
922     {"_at_fork_reinit",    (PyCFunction)lock__at_fork_reinit,
923      METH_NOARGS, NULL},
924 #endif
925     {NULL,           NULL}              /* sentinel */
926 };
927 
928 PyDoc_STRVAR(lock_doc,
929 "lock()\n\
930 --\n\
931 \n\
932 A lock object is a synchronization primitive.  To create a lock,\n\
933 call threading.Lock().  Methods are:\n\
934 \n\
935 acquire() -- lock the lock, possibly blocking until it can be obtained\n\
936 release() -- unlock of the lock\n\
937 locked() -- test whether the lock is currently locked\n\
938 \n\
939 A lock is not owned by the thread that locked it; another thread may\n\
940 unlock it.  A thread attempting to lock a lock that it has already locked\n\
941 will block until another thread unlocks it.  Deadlocks may ensue.");
942 
943 static PyType_Slot lock_type_slots[] = {
944     {Py_tp_dealloc, (destructor)lock_dealloc},
945     {Py_tp_repr, (reprfunc)lock_repr},
946     {Py_tp_doc, (void *)lock_doc},
947     {Py_tp_methods, lock_methods},
948     {Py_tp_traverse, lock_traverse},
949     {Py_tp_new, lock_new},
950     {0, 0}
951 };
952 
953 static PyType_Spec lock_type_spec = {
954     .name = "_thread.lock",
955     .basicsize = sizeof(lockobject),
956     .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
957               Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_MANAGED_WEAKREF),
958     .slots = lock_type_slots,
959 };
960 
961 /* Recursive lock objects */
962 
963 typedef struct {
964     PyObject_HEAD
965     PyThread_type_lock rlock_lock;
966     PyThread_ident_t rlock_owner;
967     unsigned long rlock_count;
968     PyObject *in_weakreflist;
969 } rlockobject;
970 
971 static int
rlock_traverse(rlockobject * self,visitproc visit,void * arg)972 rlock_traverse(rlockobject *self, visitproc visit, void *arg)
973 {
974     Py_VISIT(Py_TYPE(self));
975     return 0;
976 }
977 
978 
979 static void
rlock_dealloc(rlockobject * self)980 rlock_dealloc(rlockobject *self)
981 {
982     PyObject_GC_UnTrack(self);
983     if (self->in_weakreflist != NULL)
984         PyObject_ClearWeakRefs((PyObject *) self);
985     /* self->rlock_lock can be NULL if PyThread_allocate_lock() failed
986        in rlock_new() */
987     if (self->rlock_lock != NULL) {
988         /* Unlock the lock so it's safe to free it */
989         if (self->rlock_count > 0)
990             PyThread_release_lock(self->rlock_lock);
991 
992         PyThread_free_lock(self->rlock_lock);
993     }
994     PyTypeObject *tp = Py_TYPE(self);
995     tp->tp_free(self);
996     Py_DECREF(tp);
997 }
998 
999 static bool
rlock_is_owned_by(rlockobject * self,PyThread_ident_t tid)1000 rlock_is_owned_by(rlockobject *self, PyThread_ident_t tid)
1001 {
1002     PyThread_ident_t owner_tid =
1003         _Py_atomic_load_ullong_relaxed(&self->rlock_owner);
1004     return owner_tid == tid && self->rlock_count > 0;
1005 }
1006 
1007 static PyObject *
rlock_acquire(rlockobject * self,PyObject * args,PyObject * kwds)1008 rlock_acquire(rlockobject *self, PyObject *args, PyObject *kwds)
1009 {
1010     PyTime_t timeout;
1011     PyThread_ident_t tid;
1012     PyLockStatus r = PY_LOCK_ACQUIRED;
1013 
1014     if (lock_acquire_parse_args(args, kwds, &timeout) < 0)
1015         return NULL;
1016 
1017     tid = PyThread_get_thread_ident_ex();
1018     if (rlock_is_owned_by(self, tid)) {
1019         unsigned long count = self->rlock_count + 1;
1020         if (count <= self->rlock_count) {
1021             PyErr_SetString(PyExc_OverflowError,
1022                             "Internal lock count overflowed");
1023             return NULL;
1024         }
1025         self->rlock_count = count;
1026         Py_RETURN_TRUE;
1027     }
1028     r = acquire_timed(self->rlock_lock, timeout);
1029     if (r == PY_LOCK_ACQUIRED) {
1030         assert(self->rlock_count == 0);
1031         _Py_atomic_store_ullong_relaxed(&self->rlock_owner, tid);
1032         self->rlock_count = 1;
1033     }
1034     else if (r == PY_LOCK_INTR) {
1035         return NULL;
1036     }
1037 
1038     return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
1039 }
1040 
1041 PyDoc_STRVAR(rlock_acquire_doc,
1042 "acquire($self, /, blocking=True, timeout=-1)\n\
1043 --\n\
1044 \n\
1045 Lock the lock.  `blocking` indicates whether we should wait\n\
1046 for the lock to be available or not.  If `blocking` is False\n\
1047 and another thread holds the lock, the method will return False\n\
1048 immediately.  If `blocking` is True and another thread holds\n\
1049 the lock, the method will wait for the lock to be released,\n\
1050 take it and then return True.\n\
1051 (note: the blocking operation is interruptible.)\n\
1052 \n\
1053 In all other cases, the method will return True immediately.\n\
1054 Precisely, if the current thread already holds the lock, its\n\
1055 internal counter is simply incremented. If nobody holds the lock,\n\
1056 the lock is taken and its internal counter initialized to 1.");
1057 
1058 PyDoc_STRVAR(rlock_enter_doc,
1059 "__enter__($self, /)\n\
1060 --\n\
1061 \n\
1062 Lock the lock.");
1063 
1064 static PyObject *
rlock_release(rlockobject * self,PyObject * Py_UNUSED (ignored))1065 rlock_release(rlockobject *self, PyObject *Py_UNUSED(ignored))
1066 {
1067     PyThread_ident_t tid = PyThread_get_thread_ident_ex();
1068 
1069     if (!rlock_is_owned_by(self, tid)) {
1070         PyErr_SetString(PyExc_RuntimeError,
1071                         "cannot release un-acquired lock");
1072         return NULL;
1073     }
1074     if (--self->rlock_count == 0) {
1075         _Py_atomic_store_ullong_relaxed(&self->rlock_owner, 0);
1076         PyThread_release_lock(self->rlock_lock);
1077     }
1078     Py_RETURN_NONE;
1079 }
1080 
1081 PyDoc_STRVAR(rlock_release_doc,
1082 "release($self, /)\n\
1083 --\n\
1084 \n\
1085 Release the lock, allowing another thread that is blocked waiting for\n\
1086 the lock to acquire the lock.  The lock must be in the locked state,\n\
1087 and must be locked by the same thread that unlocks it; otherwise a\n\
1088 `RuntimeError` is raised.\n\
1089 \n\
1090 Do note that if the lock was acquire()d several times in a row by the\n\
1091 current thread, release() needs to be called as many times for the lock\n\
1092 to be available for other threads.");
1093 
1094 PyDoc_STRVAR(rlock_exit_doc,
1095 "__exit__($self, /, *exc_info)\n\
1096 --\n\
1097 \n\
1098 Release the lock.");
1099 
1100 static PyObject *
rlock_acquire_restore(rlockobject * self,PyObject * args)1101 rlock_acquire_restore(rlockobject *self, PyObject *args)
1102 {
1103     PyThread_ident_t owner;
1104     unsigned long count;
1105     int r = 1;
1106 
1107     if (!PyArg_ParseTuple(args, "(k" Py_PARSE_THREAD_IDENT_T "):_acquire_restore",
1108             &count, &owner))
1109         return NULL;
1110 
1111     if (!PyThread_acquire_lock(self->rlock_lock, 0)) {
1112         Py_BEGIN_ALLOW_THREADS
1113         r = PyThread_acquire_lock(self->rlock_lock, 1);
1114         Py_END_ALLOW_THREADS
1115     }
1116     if (!r) {
1117         PyErr_SetString(ThreadError, "couldn't acquire lock");
1118         return NULL;
1119     }
1120     assert(self->rlock_count == 0);
1121     _Py_atomic_store_ullong_relaxed(&self->rlock_owner, owner);
1122     self->rlock_count = count;
1123     Py_RETURN_NONE;
1124 }
1125 
1126 PyDoc_STRVAR(rlock_acquire_restore_doc,
1127 "_acquire_restore($self, state, /)\n\
1128 --\n\
1129 \n\
1130 For internal use by `threading.Condition`.");
1131 
1132 static PyObject *
rlock_release_save(rlockobject * self,PyObject * Py_UNUSED (ignored))1133 rlock_release_save(rlockobject *self, PyObject *Py_UNUSED(ignored))
1134 {
1135     PyThread_ident_t owner;
1136     unsigned long count;
1137 
1138     if (self->rlock_count == 0) {
1139         PyErr_SetString(PyExc_RuntimeError,
1140                         "cannot release un-acquired lock");
1141         return NULL;
1142     }
1143 
1144     owner = self->rlock_owner;
1145     count = self->rlock_count;
1146     self->rlock_count = 0;
1147     _Py_atomic_store_ullong_relaxed(&self->rlock_owner, 0);
1148     PyThread_release_lock(self->rlock_lock);
1149     return Py_BuildValue("k" Py_PARSE_THREAD_IDENT_T, count, owner);
1150 }
1151 
1152 PyDoc_STRVAR(rlock_release_save_doc,
1153 "_release_save($self, /)\n\
1154 --\n\
1155 \n\
1156 For internal use by `threading.Condition`.");
1157 
1158 static PyObject *
rlock_recursion_count(rlockobject * self,PyObject * Py_UNUSED (ignored))1159 rlock_recursion_count(rlockobject *self, PyObject *Py_UNUSED(ignored))
1160 {
1161     PyThread_ident_t tid = PyThread_get_thread_ident_ex();
1162     PyThread_ident_t owner =
1163         _Py_atomic_load_ullong_relaxed(&self->rlock_owner);
1164     return PyLong_FromUnsignedLong(owner == tid ? self->rlock_count : 0UL);
1165 }
1166 
1167 PyDoc_STRVAR(rlock_recursion_count_doc,
1168 "_recursion_count($self, /)\n\
1169 --\n\
1170 \n\
1171 For internal use by reentrancy checks.");
1172 
1173 static PyObject *
rlock_is_owned(rlockobject * self,PyObject * Py_UNUSED (ignored))1174 rlock_is_owned(rlockobject *self, PyObject *Py_UNUSED(ignored))
1175 {
1176     PyThread_ident_t tid = PyThread_get_thread_ident_ex();
1177 
1178     if (rlock_is_owned_by(self, tid)) {
1179         Py_RETURN_TRUE;
1180     }
1181     Py_RETURN_FALSE;
1182 }
1183 
1184 PyDoc_STRVAR(rlock_is_owned_doc,
1185 "_is_owned($self, /)\n\
1186 --\n\
1187 \n\
1188 For internal use by `threading.Condition`.");
1189 
1190 static PyObject *
rlock_new(PyTypeObject * type,PyObject * args,PyObject * kwds)1191 rlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1192 {
1193     rlockobject *self = (rlockobject *) type->tp_alloc(type, 0);
1194     if (self == NULL) {
1195         return NULL;
1196     }
1197     self->in_weakreflist = NULL;
1198     self->rlock_owner = 0;
1199     self->rlock_count = 0;
1200 
1201     self->rlock_lock = PyThread_allocate_lock();
1202     if (self->rlock_lock == NULL) {
1203         Py_DECREF(self);
1204         PyErr_SetString(ThreadError, "can't allocate lock");
1205         return NULL;
1206     }
1207     return (PyObject *) self;
1208 }
1209 
1210 static PyObject *
rlock_repr(rlockobject * self)1211 rlock_repr(rlockobject *self)
1212 {
1213     PyThread_ident_t owner =
1214             _Py_atomic_load_ullong_relaxed(&self->rlock_owner);
1215     return PyUnicode_FromFormat(
1216         "<%s %s object owner=%" PY_FORMAT_THREAD_IDENT_T " count=%lu at %p>",
1217         self->rlock_count ? "locked" : "unlocked",
1218         Py_TYPE(self)->tp_name, owner,
1219         self->rlock_count, self);
1220 }
1221 
1222 
1223 #ifdef HAVE_FORK
1224 static PyObject *
rlock__at_fork_reinit(rlockobject * self,PyObject * Py_UNUSED (args))1225 rlock__at_fork_reinit(rlockobject *self, PyObject *Py_UNUSED(args))
1226 {
1227     if (_PyThread_at_fork_reinit(&self->rlock_lock) < 0) {
1228         PyErr_SetString(ThreadError, "failed to reinitialize lock at fork");
1229         return NULL;
1230     }
1231 
1232     self->rlock_owner = 0;
1233     self->rlock_count = 0;
1234 
1235     Py_RETURN_NONE;
1236 }
1237 #endif  /* HAVE_FORK */
1238 
1239 
1240 static PyMethodDef rlock_methods[] = {
1241     {"acquire",      _PyCFunction_CAST(rlock_acquire),
1242      METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
1243     {"release",      (PyCFunction)rlock_release,
1244      METH_NOARGS, rlock_release_doc},
1245     {"_is_owned",     (PyCFunction)rlock_is_owned,
1246      METH_NOARGS, rlock_is_owned_doc},
1247     {"_acquire_restore", (PyCFunction)rlock_acquire_restore,
1248      METH_VARARGS, rlock_acquire_restore_doc},
1249     {"_release_save", (PyCFunction)rlock_release_save,
1250      METH_NOARGS, rlock_release_save_doc},
1251     {"_recursion_count", (PyCFunction)rlock_recursion_count,
1252      METH_NOARGS, rlock_recursion_count_doc},
1253     {"__enter__",    _PyCFunction_CAST(rlock_acquire),
1254      METH_VARARGS | METH_KEYWORDS, rlock_enter_doc},
1255     {"__exit__",    (PyCFunction)rlock_release,
1256      METH_VARARGS, rlock_exit_doc},
1257 #ifdef HAVE_FORK
1258     {"_at_fork_reinit",    (PyCFunction)rlock__at_fork_reinit,
1259      METH_NOARGS, NULL},
1260 #endif
1261     {NULL,           NULL}              /* sentinel */
1262 };
1263 
1264 
1265 static PyMemberDef rlock_type_members[] = {
1266     {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(rlockobject, in_weakreflist), Py_READONLY},
1267     {NULL},
1268 };
1269 
1270 static PyType_Slot rlock_type_slots[] = {
1271     {Py_tp_dealloc, (destructor)rlock_dealloc},
1272     {Py_tp_repr, (reprfunc)rlock_repr},
1273     {Py_tp_methods, rlock_methods},
1274     {Py_tp_alloc, PyType_GenericAlloc},
1275     {Py_tp_new, rlock_new},
1276     {Py_tp_members, rlock_type_members},
1277     {Py_tp_traverse, rlock_traverse},
1278     {0, 0},
1279 };
1280 
1281 static PyType_Spec rlock_type_spec = {
1282     .name = "_thread.RLock",
1283     .basicsize = sizeof(rlockobject),
1284     .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
1285               Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE),
1286     .slots = rlock_type_slots,
1287 };
1288 
1289 static lockobject *
newlockobject(PyObject * module)1290 newlockobject(PyObject *module)
1291 {
1292     thread_module_state *state = get_thread_state(module);
1293 
1294     PyTypeObject *type = state->lock_type;
1295     lockobject *self = (lockobject *)type->tp_alloc(type, 0);
1296     if (self == NULL) {
1297         return NULL;
1298     }
1299     self->lock = (PyMutex){0};
1300     return self;
1301 }
1302 
1303 /* Thread-local objects */
1304 
1305 /* Quick overview:
1306 
1307    We need to be able to reclaim reference cycles as soon as possible
1308    (both when a thread is being terminated, or a thread-local object
1309     becomes unreachable from user data).  Constraints:
1310    - it must not be possible for thread-state dicts to be involved in
1311      reference cycles (otherwise the cyclic GC will refuse to consider
1312      objects referenced from a reachable thread-state dict, even though
1313      local_dealloc would clear them)
1314    - the death of a thread-state dict must still imply destruction of the
1315      corresponding local dicts in all thread-local objects.
1316 
1317    Our implementation uses small "localdummy" objects in order to break
1318    the reference chain. These trivial objects are hashable (using the
1319    default scheme of identity hashing) and weakrefable.
1320 
1321    Each thread-state holds two separate localdummy objects:
1322 
1323    - `threading_local_key` is used as a key to retrieve the locals dictionary
1324      for the thread in any `threading.local` object.
1325    - `threading_local_sentinel` is used to signal when a thread is being
1326      destroyed. Consequently, the associated thread-state must hold the only
1327      reference.
1328 
1329    Each `threading.local` object contains a dict mapping localdummy keys to
1330    locals dicts and a set containing weak references to localdummy
1331    sentinels. Each sentinel weak reference has a callback that removes itself
1332    and the locals dict for the key from the `threading.local` object when
1333    called.
1334 
1335    Therefore:
1336    - The thread-state only holds strong references to localdummy objects, which
1337      cannot participate in cycles.
1338    - Only outside objects (application- or library-level) hold strong
1339      references to the thread-local objects.
1340    - As soon as thread-state's sentinel dummy is destroyed the callbacks for
1341      all weakrefs attached to the sentinel are called, and destroy the
1342      corresponding local dicts from thread-local objects.
1343    - As soon as a thread-local object is destroyed, its local dicts are
1344      destroyed.
1345    - The GC can do its work correctly when a thread-local object is dangling,
1346      without any interference from the thread-state dicts.
1347 
1348    This dual key arrangement is necessary to ensure that `threading.local`
1349    values can be retrieved from finalizers. If we were to only keep a mapping
1350    of localdummy weakrefs to locals dicts it's possible that the weakrefs would
1351    be cleared before finalizers were called (GC currently clears weakrefs that
1352    are garbage before invoking finalizers), causing lookups in finalizers to
1353    fail.
1354 */
1355 
1356 typedef struct {
1357     PyObject_HEAD
1358     PyObject *weakreflist;      /* List of weak references to self */
1359 } localdummyobject;
1360 
1361 static void
localdummy_dealloc(localdummyobject * self)1362 localdummy_dealloc(localdummyobject *self)
1363 {
1364     if (self->weakreflist != NULL)
1365         PyObject_ClearWeakRefs((PyObject *) self);
1366     PyTypeObject *tp = Py_TYPE(self);
1367     tp->tp_free((PyObject*)self);
1368     Py_DECREF(tp);
1369 }
1370 
1371 static PyMemberDef local_dummy_type_members[] = {
1372     {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(localdummyobject, weakreflist), Py_READONLY},
1373     {NULL},
1374 };
1375 
1376 static PyType_Slot local_dummy_type_slots[] = {
1377     {Py_tp_dealloc, (destructor)localdummy_dealloc},
1378     {Py_tp_doc, "Thread-local dummy"},
1379     {Py_tp_members, local_dummy_type_members},
1380     {0, 0}
1381 };
1382 
1383 static PyType_Spec local_dummy_type_spec = {
1384     .name = "_thread._localdummy",
1385     .basicsize = sizeof(localdummyobject),
1386     .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION |
1387               Py_TPFLAGS_IMMUTABLETYPE),
1388     .slots = local_dummy_type_slots,
1389 };
1390 
1391 
1392 typedef struct {
1393     PyObject_HEAD
1394     PyObject *args;
1395     PyObject *kw;
1396     PyObject *weakreflist;      /* List of weak references to self */
1397     /* A {localdummy -> localdict} dict */
1398     PyObject *localdicts;
1399     /* A set of weakrefs to thread sentinels localdummies*/
1400     PyObject *thread_watchdogs;
1401 } localobject;
1402 
1403 /* Forward declaration */
1404 static int create_localsdict(localobject *self, thread_module_state *state,
1405                              PyObject **localsdict, PyObject **sentinel_wr);
1406 static PyObject *clear_locals(PyObject *meth_self, PyObject *dummyweakref);
1407 
1408 /* Create a weakref to the sentinel localdummy for the current thread */
1409 static PyObject *
create_sentinel_wr(localobject * self)1410 create_sentinel_wr(localobject *self)
1411 {
1412     static PyMethodDef wr_callback_def = {
1413         "clear_locals", (PyCFunction) clear_locals, METH_O
1414     };
1415 
1416     PyThreadState *tstate = PyThreadState_Get();
1417 
1418     /* We use a weak reference to self in the callback closure
1419        in order to avoid spurious reference cycles */
1420     PyObject *self_wr = PyWeakref_NewRef((PyObject *) self, NULL);
1421     if (self_wr == NULL) {
1422         return NULL;
1423     }
1424 
1425     PyObject *args = PyTuple_New(2);
1426     if (args == NULL) {
1427         Py_DECREF(self_wr);
1428         return NULL;
1429     }
1430     PyTuple_SET_ITEM(args, 0, self_wr);
1431     PyTuple_SET_ITEM(args, 1, Py_NewRef(tstate->threading_local_key));
1432 
1433     PyObject *cb = PyCFunction_New(&wr_callback_def, args);
1434     Py_DECREF(args);
1435     if (cb == NULL) {
1436         return NULL;
1437     }
1438 
1439     PyObject *wr = PyWeakref_NewRef(tstate->threading_local_sentinel, cb);
1440     Py_DECREF(cb);
1441 
1442     return wr;
1443 }
1444 
1445 static PyObject *
local_new(PyTypeObject * type,PyObject * args,PyObject * kw)1446 local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
1447 {
1448     if (type->tp_init == PyBaseObject_Type.tp_init) {
1449         int rc = 0;
1450         if (args != NULL)
1451             rc = PyObject_IsTrue(args);
1452         if (rc == 0 && kw != NULL)
1453             rc = PyObject_IsTrue(kw);
1454         if (rc != 0) {
1455             if (rc > 0) {
1456                 PyErr_SetString(PyExc_TypeError,
1457                           "Initialization arguments are not supported");
1458             }
1459             return NULL;
1460         }
1461     }
1462 
1463     PyObject *module = PyType_GetModuleByDef(type, &thread_module);
1464     assert(module != NULL);
1465     thread_module_state *state = get_thread_state(module);
1466 
1467     localobject *self = (localobject *)type->tp_alloc(type, 0);
1468     if (self == NULL) {
1469         return NULL;
1470     }
1471 
1472     self->args = Py_XNewRef(args);
1473     self->kw = Py_XNewRef(kw);
1474 
1475     self->localdicts = PyDict_New();
1476     if (self->localdicts == NULL) {
1477         goto err;
1478     }
1479 
1480     self->thread_watchdogs = PySet_New(NULL);
1481     if (self->thread_watchdogs == NULL) {
1482         goto err;
1483     }
1484 
1485     PyObject *localsdict = NULL;
1486     PyObject *sentinel_wr = NULL;
1487     if (create_localsdict(self, state, &localsdict, &sentinel_wr) < 0) {
1488         goto err;
1489     }
1490     Py_DECREF(localsdict);
1491     Py_DECREF(sentinel_wr);
1492 
1493     return (PyObject *)self;
1494 
1495   err:
1496     Py_DECREF(self);
1497     return NULL;
1498 }
1499 
1500 static int
local_traverse(localobject * self,visitproc visit,void * arg)1501 local_traverse(localobject *self, visitproc visit, void *arg)
1502 {
1503     Py_VISIT(Py_TYPE(self));
1504     Py_VISIT(self->args);
1505     Py_VISIT(self->kw);
1506     Py_VISIT(self->localdicts);
1507     Py_VISIT(self->thread_watchdogs);
1508     return 0;
1509 }
1510 
1511 static int
local_clear(localobject * self)1512 local_clear(localobject *self)
1513 {
1514     Py_CLEAR(self->args);
1515     Py_CLEAR(self->kw);
1516     Py_CLEAR(self->localdicts);
1517     Py_CLEAR(self->thread_watchdogs);
1518     return 0;
1519 }
1520 
1521 static void
local_dealloc(localobject * self)1522 local_dealloc(localobject *self)
1523 {
1524     /* Weakrefs must be invalidated right now, otherwise they can be used
1525        from code called below, which is very dangerous since Py_REFCNT(self) == 0 */
1526     if (self->weakreflist != NULL) {
1527         PyObject_ClearWeakRefs((PyObject *) self);
1528     }
1529 
1530     PyObject_GC_UnTrack(self);
1531 
1532     local_clear(self);
1533 
1534     PyTypeObject *tp = Py_TYPE(self);
1535     tp->tp_free((PyObject*)self);
1536     Py_DECREF(tp);
1537 }
1538 
1539 /* Create the TLS key and sentinel if they don't exist */
1540 static int
create_localdummies(thread_module_state * state)1541 create_localdummies(thread_module_state *state)
1542 {
1543     PyThreadState *tstate = _PyThreadState_GET();
1544 
1545     if (tstate->threading_local_key != NULL) {
1546         return 0;
1547     }
1548 
1549     PyTypeObject *ld_type = state->local_dummy_type;
1550     tstate->threading_local_key = ld_type->tp_alloc(ld_type, 0);
1551     if (tstate->threading_local_key == NULL) {
1552         return -1;
1553     }
1554 
1555     tstate->threading_local_sentinel = ld_type->tp_alloc(ld_type, 0);
1556     if (tstate->threading_local_sentinel == NULL) {
1557         Py_CLEAR(tstate->threading_local_key);
1558         return -1;
1559     }
1560 
1561     return 0;
1562 }
1563 
1564 /* Insert a localsdict and sentinel weakref for the current thread, placing
1565    strong references in localsdict and sentinel_wr, respectively.
1566 */
1567 static int
create_localsdict(localobject * self,thread_module_state * state,PyObject ** localsdict,PyObject ** sentinel_wr)1568 create_localsdict(localobject *self, thread_module_state *state,
1569                   PyObject **localsdict, PyObject **sentinel_wr)
1570 {
1571     PyThreadState *tstate = _PyThreadState_GET();
1572     PyObject *ldict = NULL;
1573     PyObject *wr = NULL;
1574 
1575     if (create_localdummies(state) < 0) {
1576         goto err;
1577     }
1578 
1579     /* Create and insert the locals dict and sentinel weakref */
1580     ldict = PyDict_New();
1581     if (ldict == NULL) {
1582         goto err;
1583     }
1584 
1585     if (PyDict_SetItem(self->localdicts, tstate->threading_local_key, ldict) <
1586         0) {
1587         goto err;
1588     }
1589 
1590     wr = create_sentinel_wr(self);
1591     if (wr == NULL) {
1592         PyObject *exc = PyErr_GetRaisedException();
1593         if (PyDict_DelItem(self->localdicts, tstate->threading_local_key) <
1594             0) {
1595             PyErr_WriteUnraisable((PyObject *)self);
1596         }
1597         PyErr_SetRaisedException(exc);
1598         goto err;
1599     }
1600 
1601     if (PySet_Add(self->thread_watchdogs, wr) < 0) {
1602         PyObject *exc = PyErr_GetRaisedException();
1603         if (PyDict_DelItem(self->localdicts, tstate->threading_local_key) <
1604             0) {
1605             PyErr_WriteUnraisable((PyObject *)self);
1606         }
1607         PyErr_SetRaisedException(exc);
1608         goto err;
1609     }
1610 
1611     *localsdict = ldict;
1612     *sentinel_wr = wr;
1613     return 0;
1614 
1615 err:
1616     Py_XDECREF(ldict);
1617     Py_XDECREF(wr);
1618     return -1;
1619 }
1620 
1621 /* Return a strong reference to the locals dict for the current thread,
1622    creating it if necessary.
1623 */
1624 static PyObject *
_ldict(localobject * self,thread_module_state * state)1625 _ldict(localobject *self, thread_module_state *state)
1626 {
1627     if (create_localdummies(state) < 0) {
1628         return NULL;
1629     }
1630 
1631     /* Check if a localsdict already exists */
1632     PyObject *ldict;
1633     PyThreadState *tstate = _PyThreadState_GET();
1634     if (PyDict_GetItemRef(self->localdicts, tstate->threading_local_key,
1635                           &ldict) < 0) {
1636         return NULL;
1637     }
1638     if (ldict != NULL) {
1639         return ldict;
1640     }
1641 
1642     /* threading.local hasn't been instantiated for this thread */
1643     PyObject *wr;
1644     if (create_localsdict(self, state, &ldict, &wr) < 0) {
1645         return NULL;
1646     }
1647 
1648     /* run __init__ if we're a subtype of `threading.local` */
1649     if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init &&
1650         Py_TYPE(self)->tp_init((PyObject *)self, self->args, self->kw) < 0) {
1651         /* we need to get rid of ldict from thread so
1652            we create a new one the next time we do an attr
1653            access */
1654         PyObject *exc = PyErr_GetRaisedException();
1655         if (PyDict_DelItem(self->localdicts, tstate->threading_local_key) <
1656             0) {
1657             PyErr_WriteUnraisable((PyObject *)self);
1658             PyErr_Clear();
1659         }
1660         if (PySet_Discard(self->thread_watchdogs, wr) < 0) {
1661             PyErr_WriteUnraisable((PyObject *)self);
1662         }
1663         PyErr_SetRaisedException(exc);
1664         Py_DECREF(ldict);
1665         Py_DECREF(wr);
1666         return NULL;
1667     }
1668     Py_DECREF(wr);
1669 
1670     return ldict;
1671 }
1672 
1673 static int
local_setattro(localobject * self,PyObject * name,PyObject * v)1674 local_setattro(localobject *self, PyObject *name, PyObject *v)
1675 {
1676     PyObject *module = PyType_GetModuleByDef(Py_TYPE(self), &thread_module);
1677     assert(module != NULL);
1678     thread_module_state *state = get_thread_state(module);
1679 
1680     PyObject *ldict = _ldict(self, state);
1681     if (ldict == NULL) {
1682         goto err;
1683     }
1684 
1685     int r = PyObject_RichCompareBool(name, &_Py_ID(__dict__), Py_EQ);
1686     if (r == -1) {
1687         goto err;
1688     }
1689     if (r == 1) {
1690         PyErr_Format(PyExc_AttributeError,
1691                      "'%.100s' object attribute %R is read-only",
1692                      Py_TYPE(self)->tp_name, name);
1693         goto err;
1694     }
1695 
1696     int st =
1697         _PyObject_GenericSetAttrWithDict((PyObject *)self, name, v, ldict);
1698     Py_DECREF(ldict);
1699     return st;
1700 
1701 err:
1702     Py_XDECREF(ldict);
1703     return -1;
1704 }
1705 
1706 static PyObject *local_getattro(localobject *, PyObject *);
1707 
1708 static PyMemberDef local_type_members[] = {
1709     {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(localobject, weakreflist), Py_READONLY},
1710     {NULL},
1711 };
1712 
1713 static PyType_Slot local_type_slots[] = {
1714     {Py_tp_dealloc, (destructor)local_dealloc},
1715     {Py_tp_getattro, (getattrofunc)local_getattro},
1716     {Py_tp_setattro, (setattrofunc)local_setattro},
1717     {Py_tp_doc, "_local()\n--\n\nThread-local data"},
1718     {Py_tp_traverse, (traverseproc)local_traverse},
1719     {Py_tp_clear, (inquiry)local_clear},
1720     {Py_tp_new, local_new},
1721     {Py_tp_members, local_type_members},
1722     {0, 0}
1723 };
1724 
1725 static PyType_Spec local_type_spec = {
1726     .name = "_thread._local",
1727     .basicsize = sizeof(localobject),
1728     .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
1729               Py_TPFLAGS_IMMUTABLETYPE),
1730     .slots = local_type_slots,
1731 };
1732 
1733 static PyObject *
local_getattro(localobject * self,PyObject * name)1734 local_getattro(localobject *self, PyObject *name)
1735 {
1736     PyObject *module = PyType_GetModuleByDef(Py_TYPE(self), &thread_module);
1737     assert(module != NULL);
1738     thread_module_state *state = get_thread_state(module);
1739 
1740     PyObject *ldict = _ldict(self, state);
1741     if (ldict == NULL)
1742         return NULL;
1743 
1744     int r = PyObject_RichCompareBool(name, &_Py_ID(__dict__), Py_EQ);
1745     if (r == 1) {
1746         return ldict;
1747     }
1748     if (r == -1) {
1749         Py_DECREF(ldict);
1750         return NULL;
1751     }
1752 
1753     if (!Py_IS_TYPE(self, state->local_type)) {
1754         /* use generic lookup for subtypes */
1755         PyObject *res =
1756             _PyObject_GenericGetAttrWithDict((PyObject *)self, name, ldict, 0);
1757         Py_DECREF(ldict);
1758         return res;
1759     }
1760 
1761     /* Optimization: just look in dict ourselves */
1762     PyObject *value;
1763     if (PyDict_GetItemRef(ldict, name, &value) != 0) {
1764         // found or error
1765         Py_DECREF(ldict);
1766         return value;
1767     }
1768 
1769     /* Fall back on generic to get __class__ and __dict__ */
1770     PyObject *res =
1771         _PyObject_GenericGetAttrWithDict((PyObject *)self, name, ldict, 0);
1772     Py_DECREF(ldict);
1773     return res;
1774 }
1775 
1776 /* Called when a dummy is destroyed, indicating that the owning thread is being
1777  * cleared. */
1778 static PyObject *
clear_locals(PyObject * locals_and_key,PyObject * dummyweakref)1779 clear_locals(PyObject *locals_and_key, PyObject *dummyweakref)
1780 {
1781     PyObject *localweakref = PyTuple_GetItem(locals_and_key, 0);
1782     localobject *self = (localobject *)_PyWeakref_GET_REF(localweakref);
1783     if (self == NULL) {
1784         Py_RETURN_NONE;
1785     }
1786 
1787     /* If the thread-local object is still alive and not being cleared,
1788        remove the corresponding local dict */
1789     if (self->localdicts != NULL) {
1790         PyObject *key = PyTuple_GetItem(locals_and_key, 1);
1791         if (PyDict_Pop(self->localdicts, key, NULL) < 0) {
1792             PyErr_WriteUnraisable((PyObject*)self);
1793         }
1794     }
1795     if (self->thread_watchdogs != NULL) {
1796         if (PySet_Discard(self->thread_watchdogs, dummyweakref) < 0) {
1797             PyErr_WriteUnraisable((PyObject *)self);
1798         }
1799     }
1800 
1801     Py_DECREF(self);
1802     Py_RETURN_NONE;
1803 }
1804 
1805 /* Module functions */
1806 
1807 static PyObject *
thread_daemon_threads_allowed(PyObject * module,PyObject * Py_UNUSED (ignored))1808 thread_daemon_threads_allowed(PyObject *module, PyObject *Py_UNUSED(ignored))
1809 {
1810     PyInterpreterState *interp = _PyInterpreterState_GET();
1811     if (interp->feature_flags & Py_RTFLAGS_DAEMON_THREADS) {
1812         Py_RETURN_TRUE;
1813     }
1814     else {
1815         Py_RETURN_FALSE;
1816     }
1817 }
1818 
1819 PyDoc_STRVAR(daemon_threads_allowed_doc,
1820 "daemon_threads_allowed($module, /)\n\
1821 --\n\
1822 \n\
1823 Return True if daemon threads are allowed in the current interpreter,\n\
1824 and False otherwise.\n");
1825 
1826 static int
do_start_new_thread(thread_module_state * state,PyObject * func,PyObject * args,PyObject * kwargs,ThreadHandle * handle,int daemon)1827 do_start_new_thread(thread_module_state *state, PyObject *func, PyObject *args,
1828                     PyObject *kwargs, ThreadHandle *handle, int daemon)
1829 {
1830     PyInterpreterState *interp = _PyInterpreterState_GET();
1831     if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_THREADS)) {
1832         PyErr_SetString(PyExc_RuntimeError,
1833                         "thread is not supported for isolated subinterpreters");
1834         return -1;
1835     }
1836     if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
1837         PyErr_SetString(PyExc_PythonFinalizationError,
1838                         "can't create new thread at interpreter shutdown");
1839         return -1;
1840     }
1841 
1842     if (!daemon) {
1843         // Add the handle before starting the thread to avoid adding a handle
1844         // to a thread that has already finished (i.e. if the thread finishes
1845         // before the call to `ThreadHandle_start()` below returns).
1846         add_to_shutdown_handles(state, handle);
1847     }
1848 
1849     if (ThreadHandle_start(handle, func, args, kwargs) < 0) {
1850         if (!daemon) {
1851             remove_from_shutdown_handles(handle);
1852         }
1853         return -1;
1854     }
1855 
1856     return 0;
1857 }
1858 
1859 static PyObject *
thread_PyThread_start_new_thread(PyObject * module,PyObject * fargs)1860 thread_PyThread_start_new_thread(PyObject *module, PyObject *fargs)
1861 {
1862     PyObject *func, *args, *kwargs = NULL;
1863     thread_module_state *state = get_thread_state(module);
1864 
1865     if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3,
1866                            &func, &args, &kwargs))
1867         return NULL;
1868     if (!PyCallable_Check(func)) {
1869         PyErr_SetString(PyExc_TypeError,
1870                         "first arg must be callable");
1871         return NULL;
1872     }
1873     if (!PyTuple_Check(args)) {
1874         PyErr_SetString(PyExc_TypeError,
1875                         "2nd arg must be a tuple");
1876         return NULL;
1877     }
1878     if (kwargs != NULL && !PyDict_Check(kwargs)) {
1879         PyErr_SetString(PyExc_TypeError,
1880                         "optional 3rd arg must be a dictionary");
1881         return NULL;
1882     }
1883 
1884     if (PySys_Audit("_thread.start_new_thread", "OOO",
1885                     func, args, kwargs ? kwargs : Py_None) < 0) {
1886         return NULL;
1887     }
1888 
1889     ThreadHandle *handle = ThreadHandle_new();
1890     if (handle == NULL) {
1891         return NULL;
1892     }
1893 
1894     int st =
1895         do_start_new_thread(state, func, args, kwargs, handle, /*daemon=*/1);
1896     if (st < 0) {
1897         ThreadHandle_decref(handle);
1898         return NULL;
1899     }
1900     PyThread_ident_t ident = ThreadHandle_ident(handle);
1901     ThreadHandle_decref(handle);
1902     return PyLong_FromUnsignedLongLong(ident);
1903 }
1904 
1905 PyDoc_STRVAR(start_new_thread_doc,
1906 "start_new_thread($module, function, args, kwargs={}, /)\n\
1907 --\n\
1908 \n\
1909 Start a new thread and return its identifier.\n\
1910 \n\
1911 The thread will call the function with positional arguments from the\n\
1912 tuple args and keyword arguments taken from the optional dictionary\n\
1913 kwargs.  The thread exits when the function returns; the return value\n\
1914 is ignored.  The thread will also exit when the function raises an\n\
1915 unhandled exception; a stack trace will be printed unless the exception\n\
1916 is SystemExit.");
1917 
1918 PyDoc_STRVAR(start_new_doc,
1919 "start_new($module, function, args, kwargs={}, /)\n\
1920 --\n\
1921 \n\
1922 An obsolete synonym of start_new_thread().");
1923 
1924 static PyObject *
thread_PyThread_start_joinable_thread(PyObject * module,PyObject * fargs,PyObject * fkwargs)1925 thread_PyThread_start_joinable_thread(PyObject *module, PyObject *fargs,
1926                                       PyObject *fkwargs)
1927 {
1928     static char *keywords[] = {"function", "handle", "daemon", NULL};
1929     PyObject *func = NULL;
1930     int daemon = 1;
1931     thread_module_state *state = get_thread_state(module);
1932     PyObject *hobj = NULL;
1933     if (!PyArg_ParseTupleAndKeywords(fargs, fkwargs,
1934                                      "O|Op:start_joinable_thread", keywords,
1935                                      &func, &hobj, &daemon)) {
1936         return NULL;
1937     }
1938 
1939     if (!PyCallable_Check(func)) {
1940         PyErr_SetString(PyExc_TypeError,
1941                         "thread function must be callable");
1942         return NULL;
1943     }
1944 
1945     if (hobj == NULL) {
1946         hobj = Py_None;
1947     }
1948     else if (hobj != Py_None && !Py_IS_TYPE(hobj, state->thread_handle_type)) {
1949         PyErr_SetString(PyExc_TypeError, "'handle' must be a _ThreadHandle");
1950         return NULL;
1951     }
1952 
1953     if (PySys_Audit("_thread.start_joinable_thread", "OiO", func, daemon,
1954                     hobj) < 0) {
1955         return NULL;
1956     }
1957 
1958     if (hobj == Py_None) {
1959         hobj = (PyObject *)PyThreadHandleObject_new(state->thread_handle_type);
1960         if (hobj == NULL) {
1961             return NULL;
1962         }
1963     }
1964     else {
1965         Py_INCREF(hobj);
1966     }
1967 
1968     PyObject* args = PyTuple_New(0);
1969     if (args == NULL) {
1970         return NULL;
1971     }
1972     int st = do_start_new_thread(state, func, args,
1973                                  /*kwargs=*/ NULL, ((PyThreadHandleObject*)hobj)->handle, daemon);
1974     Py_DECREF(args);
1975     if (st < 0) {
1976         Py_DECREF(hobj);
1977         return NULL;
1978     }
1979     return (PyObject *) hobj;
1980 }
1981 
1982 PyDoc_STRVAR(start_joinable_doc,
1983 "start_joinable_thread($module, /, function, handle=None, daemon=True)\n\
1984 --\n\
1985 \n\
1986 *For internal use only*: start a new thread.\n\
1987 \n\
1988 Like start_new_thread(), this starts a new thread calling the given function.\n\
1989 Unlike start_new_thread(), this returns a handle object with methods to join\n\
1990 or detach the given thread.\n\
1991 This function is not for third-party code, please use the\n\
1992 `threading` module instead. During finalization the runtime will not wait for\n\
1993 the thread to exit if daemon is True. If handle is provided it must be a\n\
1994 newly created thread._ThreadHandle instance.");
1995 
1996 static PyObject *
thread_PyThread_exit_thread(PyObject * self,PyObject * Py_UNUSED (ignored))1997 thread_PyThread_exit_thread(PyObject *self, PyObject *Py_UNUSED(ignored))
1998 {
1999     PyErr_SetNone(PyExc_SystemExit);
2000     return NULL;
2001 }
2002 
2003 PyDoc_STRVAR(exit_doc,
2004 "exit($module, /)\n\
2005 --\n\
2006 \n\
2007 This is synonymous to ``raise SystemExit''.  It will cause the current\n\
2008 thread to exit silently unless the exception is caught.");
2009 
2010 PyDoc_STRVAR(exit_thread_doc,
2011 "exit_thread($module, /)\n\
2012 --\n\
2013 \n\
2014 An obsolete synonym of exit().");
2015 
2016 static PyObject *
thread_PyThread_interrupt_main(PyObject * self,PyObject * args)2017 thread_PyThread_interrupt_main(PyObject *self, PyObject *args)
2018 {
2019     int signum = SIGINT;
2020     if (!PyArg_ParseTuple(args, "|i:signum", &signum)) {
2021         return NULL;
2022     }
2023 
2024     if (PyErr_SetInterruptEx(signum)) {
2025         PyErr_SetString(PyExc_ValueError, "signal number out of range");
2026         return NULL;
2027     }
2028     Py_RETURN_NONE;
2029 }
2030 
2031 PyDoc_STRVAR(interrupt_doc,
2032 "interrupt_main($module, signum=signal.SIGINT, /)\n\
2033 --\n\
2034 \n\
2035 Simulate the arrival of the given signal in the main thread,\n\
2036 where the corresponding signal handler will be executed.\n\
2037 If *signum* is omitted, SIGINT is assumed.\n\
2038 A subthread can use this function to interrupt the main thread.\n\
2039 \n\
2040 Note: the default signal handler for SIGINT raises ``KeyboardInterrupt``."
2041 );
2042 
2043 static PyObject *
thread_PyThread_allocate_lock(PyObject * module,PyObject * Py_UNUSED (ignored))2044 thread_PyThread_allocate_lock(PyObject *module, PyObject *Py_UNUSED(ignored))
2045 {
2046     return (PyObject *) newlockobject(module);
2047 }
2048 
2049 PyDoc_STRVAR(allocate_lock_doc,
2050 "allocate_lock($module, /)\n\
2051 --\n\
2052 \n\
2053 Create a new lock object. See help(type(threading.Lock())) for\n\
2054 information about locks.");
2055 
2056 PyDoc_STRVAR(allocate_doc,
2057 "allocate($module, /)\n\
2058 --\n\
2059 \n\
2060 An obsolete synonym of allocate_lock().");
2061 
2062 static PyObject *
thread_get_ident(PyObject * self,PyObject * Py_UNUSED (ignored))2063 thread_get_ident(PyObject *self, PyObject *Py_UNUSED(ignored))
2064 {
2065     PyThread_ident_t ident = PyThread_get_thread_ident_ex();
2066     if (ident == PYTHREAD_INVALID_THREAD_ID) {
2067         PyErr_SetString(ThreadError, "no current thread ident");
2068         return NULL;
2069     }
2070     return PyLong_FromUnsignedLongLong(ident);
2071 }
2072 
2073 PyDoc_STRVAR(get_ident_doc,
2074 "get_ident($module, /)\n\
2075 --\n\
2076 \n\
2077 Return a non-zero integer that uniquely identifies the current thread\n\
2078 amongst other threads that exist simultaneously.\n\
2079 This may be used to identify per-thread resources.\n\
2080 Even though on some platforms threads identities may appear to be\n\
2081 allocated consecutive numbers starting at 1, this behavior should not\n\
2082 be relied upon, and the number should be seen purely as a magic cookie.\n\
2083 A thread's identity may be reused for another thread after it exits.");
2084 
2085 #ifdef PY_HAVE_THREAD_NATIVE_ID
2086 static PyObject *
thread_get_native_id(PyObject * self,PyObject * Py_UNUSED (ignored))2087 thread_get_native_id(PyObject *self, PyObject *Py_UNUSED(ignored))
2088 {
2089     unsigned long native_id = PyThread_get_thread_native_id();
2090     return PyLong_FromUnsignedLong(native_id);
2091 }
2092 
2093 PyDoc_STRVAR(get_native_id_doc,
2094 "get_native_id($module, /)\n\
2095 --\n\
2096 \n\
2097 Return a non-negative integer identifying the thread as reported\n\
2098 by the OS (kernel). This may be used to uniquely identify a\n\
2099 particular thread within a system.");
2100 #endif
2101 
2102 static PyObject *
thread__count(PyObject * self,PyObject * Py_UNUSED (ignored))2103 thread__count(PyObject *self, PyObject *Py_UNUSED(ignored))
2104 {
2105     PyInterpreterState *interp = _PyInterpreterState_GET();
2106     return PyLong_FromSsize_t(_Py_atomic_load_ssize(&interp->threads.count));
2107 }
2108 
2109 PyDoc_STRVAR(_count_doc,
2110 "_count($module, /)\n\
2111 --\n\
2112 \n\
2113 Return the number of currently running Python threads, excluding\n\
2114 the main thread. The returned number comprises all threads created\n\
2115 through `start_new_thread()` as well as `threading.Thread`, and not\n\
2116 yet finished.\n\
2117 \n\
2118 This function is meant for internal and specialized purposes only.\n\
2119 In most applications `threading.enumerate()` should be used instead.");
2120 
2121 static PyObject *
thread_stack_size(PyObject * self,PyObject * args)2122 thread_stack_size(PyObject *self, PyObject *args)
2123 {
2124     size_t old_size;
2125     Py_ssize_t new_size = 0;
2126     int rc;
2127 
2128     if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size))
2129         return NULL;
2130 
2131     if (new_size < 0) {
2132         PyErr_SetString(PyExc_ValueError,
2133                         "size must be 0 or a positive value");
2134         return NULL;
2135     }
2136 
2137     old_size = PyThread_get_stacksize();
2138 
2139     rc = PyThread_set_stacksize((size_t) new_size);
2140     if (rc == -1) {
2141         PyErr_Format(PyExc_ValueError,
2142                      "size not valid: %zd bytes",
2143                      new_size);
2144         return NULL;
2145     }
2146     if (rc == -2) {
2147         PyErr_SetString(ThreadError,
2148                         "setting stack size not supported");
2149         return NULL;
2150     }
2151 
2152     return PyLong_FromSsize_t((Py_ssize_t) old_size);
2153 }
2154 
2155 PyDoc_STRVAR(stack_size_doc,
2156 "stack_size($module, size=0, /)\n\
2157 --\n\
2158 \n\
2159 Return the thread stack size used when creating new threads.  The\n\
2160 optional size argument specifies the stack size (in bytes) to be used\n\
2161 for subsequently created threads, and must be 0 (use platform or\n\
2162 configured default) or a positive integer value of at least 32,768 (32k).\n\
2163 If changing the thread stack size is unsupported, a ThreadError\n\
2164 exception is raised.  If the specified size is invalid, a ValueError\n\
2165 exception is raised, and the stack size is unmodified.  32k bytes\n\
2166  currently the minimum supported stack size value to guarantee\n\
2167 sufficient stack space for the interpreter itself.\n\
2168 \n\
2169 Note that some platforms may have particular restrictions on values for\n\
2170 the stack size, such as requiring a minimum stack size larger than 32 KiB or\n\
2171 requiring allocation in multiples of the system memory page size\n\
2172 - platform documentation should be referred to for more information\n\
2173 (4 KiB pages are common; using multiples of 4096 for the stack size is\n\
2174 the suggested approach in the absence of more specific information).");
2175 
2176 static int
thread_excepthook_file(PyObject * file,PyObject * exc_type,PyObject * exc_value,PyObject * exc_traceback,PyObject * thread)2177 thread_excepthook_file(PyObject *file, PyObject *exc_type, PyObject *exc_value,
2178                        PyObject *exc_traceback, PyObject *thread)
2179 {
2180     /* print(f"Exception in thread {thread.name}:", file=file) */
2181     if (PyFile_WriteString("Exception in thread ", file) < 0) {
2182         return -1;
2183     }
2184 
2185     PyObject *name = NULL;
2186     if (thread != Py_None) {
2187         if (PyObject_GetOptionalAttr(thread, &_Py_ID(name), &name) < 0) {
2188             return -1;
2189         }
2190     }
2191     if (name != NULL) {
2192         if (PyFile_WriteObject(name, file, Py_PRINT_RAW) < 0) {
2193             Py_DECREF(name);
2194             return -1;
2195         }
2196         Py_DECREF(name);
2197     }
2198     else {
2199         PyThread_ident_t ident = PyThread_get_thread_ident_ex();
2200         PyObject *str = PyUnicode_FromFormat("%" PY_FORMAT_THREAD_IDENT_T, ident);
2201         if (str != NULL) {
2202             if (PyFile_WriteObject(str, file, Py_PRINT_RAW) < 0) {
2203                 Py_DECREF(str);
2204                 return -1;
2205             }
2206             Py_DECREF(str);
2207         }
2208         else {
2209             PyErr_Clear();
2210 
2211             if (PyFile_WriteString("<failed to get thread name>", file) < 0) {
2212                 return -1;
2213             }
2214         }
2215     }
2216 
2217     if (PyFile_WriteString(":\n", file) < 0) {
2218         return -1;
2219     }
2220 
2221     /* Display the traceback */
2222     _PyErr_Display(file, exc_type, exc_value, exc_traceback);
2223 
2224     /* Call file.flush() */
2225     if (_PyFile_Flush(file) < 0) {
2226         return -1;
2227     }
2228 
2229     return 0;
2230 }
2231 
2232 
2233 PyDoc_STRVAR(ExceptHookArgs__doc__,
2234 "ExceptHookArgs\n\
2235 \n\
2236 Type used to pass arguments to threading.excepthook.");
2237 
2238 static PyStructSequence_Field ExceptHookArgs_fields[] = {
2239     {"exc_type", "Exception type"},
2240     {"exc_value", "Exception value"},
2241     {"exc_traceback", "Exception traceback"},
2242     {"thread", "Thread"},
2243     {0}
2244 };
2245 
2246 static PyStructSequence_Desc ExceptHookArgs_desc = {
2247     .name = "_thread._ExceptHookArgs",
2248     .doc = ExceptHookArgs__doc__,
2249     .fields = ExceptHookArgs_fields,
2250     .n_in_sequence = 4
2251 };
2252 
2253 
2254 static PyObject *
thread_excepthook(PyObject * module,PyObject * args)2255 thread_excepthook(PyObject *module, PyObject *args)
2256 {
2257     thread_module_state *state = get_thread_state(module);
2258 
2259     if (!Py_IS_TYPE(args, state->excepthook_type)) {
2260         PyErr_SetString(PyExc_TypeError,
2261                         "_thread.excepthook argument type "
2262                         "must be ExceptHookArgs");
2263         return NULL;
2264     }
2265 
2266     /* Borrowed reference */
2267     PyObject *exc_type = PyStructSequence_GET_ITEM(args, 0);
2268     if (exc_type == PyExc_SystemExit) {
2269         /* silently ignore SystemExit */
2270         Py_RETURN_NONE;
2271     }
2272 
2273     /* Borrowed references */
2274     PyObject *exc_value = PyStructSequence_GET_ITEM(args, 1);
2275     PyObject *exc_tb = PyStructSequence_GET_ITEM(args, 2);
2276     PyObject *thread = PyStructSequence_GET_ITEM(args, 3);
2277 
2278     PyThreadState *tstate = _PyThreadState_GET();
2279     PyObject *file = _PySys_GetAttr(tstate, &_Py_ID(stderr));
2280     if (file == NULL || file == Py_None) {
2281         if (thread == Py_None) {
2282             /* do nothing if sys.stderr is None and thread is None */
2283             Py_RETURN_NONE;
2284         }
2285 
2286         file = PyObject_GetAttrString(thread, "_stderr");
2287         if (file == NULL) {
2288             return NULL;
2289         }
2290         if (file == Py_None) {
2291             Py_DECREF(file);
2292             /* do nothing if sys.stderr is None and sys.stderr was None
2293                when the thread was created */
2294             Py_RETURN_NONE;
2295         }
2296     }
2297     else {
2298         Py_INCREF(file);
2299     }
2300 
2301     int res = thread_excepthook_file(file, exc_type, exc_value, exc_tb,
2302                                      thread);
2303     Py_DECREF(file);
2304     if (res < 0) {
2305         return NULL;
2306     }
2307 
2308     Py_RETURN_NONE;
2309 }
2310 
2311 PyDoc_STRVAR(excepthook_doc,
2312 "_excepthook($module, (exc_type, exc_value, exc_traceback, thread), /)\n\
2313 --\n\
2314 \n\
2315 Handle uncaught Thread.run() exception.");
2316 
2317 static PyObject *
thread__is_main_interpreter(PyObject * module,PyObject * Py_UNUSED (ignored))2318 thread__is_main_interpreter(PyObject *module, PyObject *Py_UNUSED(ignored))
2319 {
2320     PyInterpreterState *interp = _PyInterpreterState_GET();
2321     return PyBool_FromLong(_Py_IsMainInterpreter(interp));
2322 }
2323 
2324 PyDoc_STRVAR(thread__is_main_interpreter_doc,
2325 "_is_main_interpreter($module, /)\n\
2326 --\n\
2327 \n\
2328 Return True if the current interpreter is the main Python interpreter.");
2329 
2330 static PyObject *
thread_shutdown(PyObject * self,PyObject * args)2331 thread_shutdown(PyObject *self, PyObject *args)
2332 {
2333     PyThread_ident_t ident = PyThread_get_thread_ident_ex();
2334     thread_module_state *state = get_thread_state(self);
2335 
2336     for (;;) {
2337         ThreadHandle *handle = NULL;
2338 
2339         // Find a thread that's not yet finished.
2340         HEAD_LOCK(&_PyRuntime);
2341         struct llist_node *node;
2342         llist_for_each_safe(node, &state->shutdown_handles) {
2343             ThreadHandle *cur = llist_data(node, ThreadHandle, shutdown_node);
2344             if (cur->ident != ident) {
2345                 ThreadHandle_incref(cur);
2346                 handle = cur;
2347                 break;
2348             }
2349         }
2350         HEAD_UNLOCK(&_PyRuntime);
2351 
2352         if (!handle) {
2353             // No more threads to wait on!
2354             break;
2355         }
2356 
2357         // Wait for the thread to finish. If we're interrupted, such
2358         // as by a ctrl-c we print the error and exit early.
2359         if (ThreadHandle_join(handle, -1) < 0) {
2360             PyErr_WriteUnraisable(NULL);
2361             ThreadHandle_decref(handle);
2362             Py_RETURN_NONE;
2363         }
2364 
2365         ThreadHandle_decref(handle);
2366     }
2367 
2368     Py_RETURN_NONE;
2369 }
2370 
2371 PyDoc_STRVAR(shutdown_doc,
2372 "_shutdown($module, /)\n\
2373 --\n\
2374 \n\
2375 Wait for all non-daemon threads (other than the calling thread) to stop.");
2376 
2377 static PyObject *
thread__make_thread_handle(PyObject * module,PyObject * identobj)2378 thread__make_thread_handle(PyObject *module, PyObject *identobj)
2379 {
2380     thread_module_state *state = get_thread_state(module);
2381     if (!PyLong_Check(identobj)) {
2382         PyErr_SetString(PyExc_TypeError, "ident must be an integer");
2383         return NULL;
2384     }
2385     PyThread_ident_t ident = PyLong_AsUnsignedLongLong(identobj);
2386     if (PyErr_Occurred()) {
2387         return NULL;
2388     }
2389     PyThreadHandleObject *hobj =
2390         PyThreadHandleObject_new(state->thread_handle_type);
2391     if (hobj == NULL) {
2392         return NULL;
2393     }
2394     PyMutex_Lock(&hobj->handle->mutex);
2395     hobj->handle->ident = ident;
2396     hobj->handle->state = THREAD_HANDLE_RUNNING;
2397     PyMutex_Unlock(&hobj->handle->mutex);
2398     return (PyObject*) hobj;
2399 }
2400 
2401 PyDoc_STRVAR(thread__make_thread_handle_doc,
2402 "_make_thread_handle($module, ident, /)\n\
2403 --\n\
2404 \n\
2405 Internal only. Make a thread handle for threads not spawned\n\
2406 by the _thread or threading module.");
2407 
2408 static PyObject *
thread__get_main_thread_ident(PyObject * module,PyObject * Py_UNUSED (ignored))2409 thread__get_main_thread_ident(PyObject *module, PyObject *Py_UNUSED(ignored))
2410 {
2411     return PyLong_FromUnsignedLongLong(_PyRuntime.main_thread);
2412 }
2413 
2414 PyDoc_STRVAR(thread__get_main_thread_ident_doc,
2415 "_get_main_thread_ident($module, /)\n\
2416 --\n\
2417 \n\
2418 Internal only. Return a non-zero integer that uniquely identifies the main thread\n\
2419 of the main interpreter.");
2420 
2421 static PyMethodDef thread_methods[] = {
2422     {"start_new_thread",        (PyCFunction)thread_PyThread_start_new_thread,
2423      METH_VARARGS, start_new_thread_doc},
2424     {"start_new",               (PyCFunction)thread_PyThread_start_new_thread,
2425      METH_VARARGS, start_new_doc},
2426     {"start_joinable_thread",   _PyCFunction_CAST(thread_PyThread_start_joinable_thread),
2427      METH_VARARGS | METH_KEYWORDS, start_joinable_doc},
2428     {"daemon_threads_allowed",  (PyCFunction)thread_daemon_threads_allowed,
2429      METH_NOARGS, daemon_threads_allowed_doc},
2430     {"allocate_lock",           thread_PyThread_allocate_lock,
2431      METH_NOARGS, allocate_lock_doc},
2432     {"allocate",                thread_PyThread_allocate_lock,
2433      METH_NOARGS, allocate_doc},
2434     {"exit_thread",             thread_PyThread_exit_thread,
2435      METH_NOARGS, exit_thread_doc},
2436     {"exit",                    thread_PyThread_exit_thread,
2437      METH_NOARGS, exit_doc},
2438     {"interrupt_main",          (PyCFunction)thread_PyThread_interrupt_main,
2439      METH_VARARGS, interrupt_doc},
2440     {"get_ident",               thread_get_ident,
2441      METH_NOARGS, get_ident_doc},
2442 #ifdef PY_HAVE_THREAD_NATIVE_ID
2443     {"get_native_id",           thread_get_native_id,
2444      METH_NOARGS, get_native_id_doc},
2445 #endif
2446     {"_count",                  thread__count,
2447      METH_NOARGS, _count_doc},
2448     {"stack_size",              (PyCFunction)thread_stack_size,
2449      METH_VARARGS, stack_size_doc},
2450     {"_excepthook",             thread_excepthook,
2451      METH_O, excepthook_doc},
2452     {"_is_main_interpreter",    thread__is_main_interpreter,
2453      METH_NOARGS, thread__is_main_interpreter_doc},
2454     {"_shutdown",               thread_shutdown,
2455      METH_NOARGS, shutdown_doc},
2456     {"_make_thread_handle", thread__make_thread_handle,
2457      METH_O, thread__make_thread_handle_doc},
2458     {"_get_main_thread_ident", thread__get_main_thread_ident,
2459      METH_NOARGS, thread__get_main_thread_ident_doc},
2460     {NULL,                      NULL}           /* sentinel */
2461 };
2462 
2463 
2464 /* Initialization function */
2465 
2466 static int
thread_module_exec(PyObject * module)2467 thread_module_exec(PyObject *module)
2468 {
2469     thread_module_state *state = get_thread_state(module);
2470     PyObject *d = PyModule_GetDict(module);
2471 
2472     // Initialize the C thread library
2473     PyThread_init_thread();
2474 
2475     // _ThreadHandle
2476     state->thread_handle_type = (PyTypeObject *)PyType_FromSpec(&ThreadHandle_Type_spec);
2477     if (state->thread_handle_type == NULL) {
2478         return -1;
2479     }
2480     if (PyDict_SetItemString(d, "_ThreadHandle", (PyObject *)state->thread_handle_type) < 0) {
2481         return -1;
2482     }
2483 
2484     // Lock
2485     state->lock_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, &lock_type_spec, NULL);
2486     if (state->lock_type == NULL) {
2487         return -1;
2488     }
2489     if (PyModule_AddType(module, state->lock_type) < 0) {
2490         return -1;
2491     }
2492     // Old alias: lock -> LockType
2493     if (PyDict_SetItemString(d, "LockType", (PyObject *)state->lock_type) < 0) {
2494         return -1;
2495     }
2496 
2497     // RLock
2498     PyTypeObject *rlock_type = (PyTypeObject *)PyType_FromSpec(&rlock_type_spec);
2499     if (rlock_type == NULL) {
2500         return -1;
2501     }
2502     if (PyModule_AddType(module, rlock_type) < 0) {
2503         Py_DECREF(rlock_type);
2504         return -1;
2505     }
2506     Py_DECREF(rlock_type);
2507 
2508     // Local dummy
2509     state->local_dummy_type = (PyTypeObject *)PyType_FromSpec(&local_dummy_type_spec);
2510     if (state->local_dummy_type == NULL) {
2511         return -1;
2512     }
2513 
2514     // Local
2515     state->local_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, &local_type_spec, NULL);
2516     if (state->local_type == NULL) {
2517         return -1;
2518     }
2519     if (PyModule_AddType(module, state->local_type) < 0) {
2520         return -1;
2521     }
2522 
2523     // Add module attributes
2524     if (PyDict_SetItemString(d, "error", ThreadError) < 0) {
2525         return -1;
2526     }
2527 
2528     // _ExceptHookArgs type
2529     state->excepthook_type = PyStructSequence_NewType(&ExceptHookArgs_desc);
2530     if (state->excepthook_type == NULL) {
2531         return -1;
2532     }
2533     if (PyModule_AddType(module, state->excepthook_type) < 0) {
2534         return -1;
2535     }
2536 
2537     // TIMEOUT_MAX
2538     double timeout_max = (double)PY_TIMEOUT_MAX * 1e-6;
2539     double time_max = PyTime_AsSecondsDouble(PyTime_MAX);
2540     timeout_max = Py_MIN(timeout_max, time_max);
2541     // Round towards minus infinity
2542     timeout_max = floor(timeout_max);
2543 
2544     if (PyModule_Add(module, "TIMEOUT_MAX",
2545                         PyFloat_FromDouble(timeout_max)) < 0) {
2546         return -1;
2547     }
2548 
2549     llist_init(&state->shutdown_handles);
2550 
2551     return 0;
2552 }
2553 
2554 
2555 static int
thread_module_traverse(PyObject * module,visitproc visit,void * arg)2556 thread_module_traverse(PyObject *module, visitproc visit, void *arg)
2557 {
2558     thread_module_state *state = get_thread_state(module);
2559     Py_VISIT(state->excepthook_type);
2560     Py_VISIT(state->lock_type);
2561     Py_VISIT(state->local_type);
2562     Py_VISIT(state->local_dummy_type);
2563     Py_VISIT(state->thread_handle_type);
2564     return 0;
2565 }
2566 
2567 static int
thread_module_clear(PyObject * module)2568 thread_module_clear(PyObject *module)
2569 {
2570     thread_module_state *state = get_thread_state(module);
2571     Py_CLEAR(state->excepthook_type);
2572     Py_CLEAR(state->lock_type);
2573     Py_CLEAR(state->local_type);
2574     Py_CLEAR(state->local_dummy_type);
2575     Py_CLEAR(state->thread_handle_type);
2576     // Remove any remaining handles (e.g. if shutdown exited early due to
2577     // interrupt) so that attempts to unlink the handle after our module state
2578     // is destroyed do not crash.
2579     clear_shutdown_handles(state);
2580     return 0;
2581 }
2582 
2583 static void
thread_module_free(void * module)2584 thread_module_free(void *module)
2585 {
2586     thread_module_clear((PyObject *)module);
2587 }
2588 
2589 
2590 
2591 PyDoc_STRVAR(thread_doc,
2592 "This module provides primitive operations to write multi-threaded programs.\n\
2593 The 'threading' module provides a more convenient interface.");
2594 
2595 static PyModuleDef_Slot thread_module_slots[] = {
2596     {Py_mod_exec, thread_module_exec},
2597     {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
2598     {Py_mod_gil, Py_MOD_GIL_NOT_USED},
2599     {0, NULL}
2600 };
2601 
2602 static struct PyModuleDef thread_module = {
2603     PyModuleDef_HEAD_INIT,
2604     .m_name = "_thread",
2605     .m_doc = thread_doc,
2606     .m_size = sizeof(thread_module_state),
2607     .m_methods = thread_methods,
2608     .m_traverse = thread_module_traverse,
2609     .m_clear = thread_module_clear,
2610     .m_free = thread_module_free,
2611     .m_slots = thread_module_slots,
2612 };
2613 
2614 PyMODINIT_FUNC
PyInit__thread(void)2615 PyInit__thread(void)
2616 {
2617     return PyModuleDef_Init(&thread_module);
2618 }
2619