1
2 /* Thread module */
3 /* Interface to Sjoerd's portable C thread library */
4
5 #include "Python.h"
6 #include "pycore_interp.h" // _PyInterpreterState.threads.count
7 #include "pycore_moduleobject.h" // _PyModule_GetState()
8 #include "pycore_pylifecycle.h"
9 #include "pycore_pystate.h" // _PyThreadState_SetCurrent()
10 #include <stddef.h> // offsetof()
11 #include "structmember.h" // PyMemberDef
12
13 #ifdef HAVE_SIGNAL_H
14 # include <signal.h> // SIGINT
15 #endif
16
17 // ThreadError is just an alias to PyExc_RuntimeError
18 #define ThreadError PyExc_RuntimeError
19
20
21 // Forward declarations
22 static struct PyModuleDef thread_module;
23
24
25 typedef struct {
26 PyTypeObject *excepthook_type;
27 PyTypeObject *lock_type;
28 PyTypeObject *local_type;
29 PyTypeObject *local_dummy_type;
30 } thread_module_state;
31
32 static inline thread_module_state*
get_thread_state(PyObject * module)33 get_thread_state(PyObject *module)
34 {
35 void *state = _PyModule_GetState(module);
36 assert(state != NULL);
37 return (thread_module_state *)state;
38 }
39
40
41 /* Lock objects */
42
43 typedef struct {
44 PyObject_HEAD
45 PyThread_type_lock lock_lock;
46 PyObject *in_weakreflist;
47 char locked; /* for sanity checking */
48 } lockobject;
49
50 static int
lock_traverse(lockobject * self,visitproc visit,void * arg)51 lock_traverse(lockobject *self, visitproc visit, void *arg)
52 {
53 Py_VISIT(Py_TYPE(self));
54 return 0;
55 }
56
57 static void
lock_dealloc(lockobject * self)58 lock_dealloc(lockobject *self)
59 {
60 PyObject_GC_UnTrack(self);
61 if (self->in_weakreflist != NULL) {
62 PyObject_ClearWeakRefs((PyObject *) self);
63 }
64 if (self->lock_lock != NULL) {
65 /* Unlock the lock so it's safe to free it */
66 if (self->locked)
67 PyThread_release_lock(self->lock_lock);
68 PyThread_free_lock(self->lock_lock);
69 }
70 PyTypeObject *tp = Py_TYPE(self);
71 tp->tp_free((PyObject*)self);
72 Py_DECREF(tp);
73 }
74
75 /* Helper to acquire an interruptible lock with a timeout. If the lock acquire
76 * is interrupted, signal handlers are run, and if they raise an exception,
77 * PY_LOCK_INTR is returned. Otherwise, PY_LOCK_ACQUIRED or PY_LOCK_FAILURE
78 * are returned, depending on whether the lock can be acquired within the
79 * timeout.
80 */
81 static PyLockStatus
acquire_timed(PyThread_type_lock lock,_PyTime_t timeout)82 acquire_timed(PyThread_type_lock lock, _PyTime_t timeout)
83 {
84 _PyTime_t endtime = 0;
85 if (timeout > 0) {
86 endtime = _PyDeadline_Init(timeout);
87 }
88
89 PyLockStatus r;
90 do {
91 _PyTime_t microseconds;
92 microseconds = _PyTime_AsMicroseconds(timeout, _PyTime_ROUND_CEILING);
93
94 /* first a simple non-blocking try without releasing the GIL */
95 r = PyThread_acquire_lock_timed(lock, 0, 0);
96 if (r == PY_LOCK_FAILURE && microseconds != 0) {
97 Py_BEGIN_ALLOW_THREADS
98 r = PyThread_acquire_lock_timed(lock, microseconds, 1);
99 Py_END_ALLOW_THREADS
100 }
101
102 if (r == PY_LOCK_INTR) {
103 /* Run signal handlers if we were interrupted. Propagate
104 * exceptions from signal handlers, such as KeyboardInterrupt, by
105 * passing up PY_LOCK_INTR. */
106 if (Py_MakePendingCalls() < 0) {
107 return PY_LOCK_INTR;
108 }
109
110 /* If we're using a timeout, recompute the timeout after processing
111 * signals, since those can take time. */
112 if (timeout > 0) {
113 timeout = _PyDeadline_Get(endtime);
114
115 /* Check for negative values, since those mean block forever.
116 */
117 if (timeout < 0) {
118 r = PY_LOCK_FAILURE;
119 }
120 }
121 }
122 } while (r == PY_LOCK_INTR); /* Retry if we were interrupted. */
123
124 return r;
125 }
126
127 static int
lock_acquire_parse_args(PyObject * args,PyObject * kwds,_PyTime_t * timeout)128 lock_acquire_parse_args(PyObject *args, PyObject *kwds,
129 _PyTime_t *timeout)
130 {
131 char *kwlist[] = {"blocking", "timeout", NULL};
132 int blocking = 1;
133 PyObject *timeout_obj = NULL;
134 const _PyTime_t unset_timeout = _PyTime_FromSeconds(-1);
135
136 *timeout = unset_timeout ;
137
138 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iO:acquire", kwlist,
139 &blocking, &timeout_obj))
140 return -1;
141
142 if (timeout_obj
143 && _PyTime_FromSecondsObject(timeout,
144 timeout_obj, _PyTime_ROUND_TIMEOUT) < 0)
145 return -1;
146
147 if (!blocking && *timeout != unset_timeout ) {
148 PyErr_SetString(PyExc_ValueError,
149 "can't specify a timeout for a non-blocking call");
150 return -1;
151 }
152 if (*timeout < 0 && *timeout != unset_timeout) {
153 PyErr_SetString(PyExc_ValueError,
154 "timeout value must be positive");
155 return -1;
156 }
157 if (!blocking)
158 *timeout = 0;
159 else if (*timeout != unset_timeout) {
160 _PyTime_t microseconds;
161
162 microseconds = _PyTime_AsMicroseconds(*timeout, _PyTime_ROUND_TIMEOUT);
163 if (microseconds > PY_TIMEOUT_MAX) {
164 PyErr_SetString(PyExc_OverflowError,
165 "timeout value is too large");
166 return -1;
167 }
168 }
169 return 0;
170 }
171
172 static PyObject *
lock_PyThread_acquire_lock(lockobject * self,PyObject * args,PyObject * kwds)173 lock_PyThread_acquire_lock(lockobject *self, PyObject *args, PyObject *kwds)
174 {
175 _PyTime_t timeout;
176 if (lock_acquire_parse_args(args, kwds, &timeout) < 0)
177 return NULL;
178
179 PyLockStatus r = acquire_timed(self->lock_lock, timeout);
180 if (r == PY_LOCK_INTR) {
181 return NULL;
182 }
183
184 if (r == PY_LOCK_ACQUIRED)
185 self->locked = 1;
186 return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
187 }
188
189 PyDoc_STRVAR(acquire_doc,
190 "acquire(blocking=True, timeout=-1) -> bool\n\
191 (acquire_lock() is an obsolete synonym)\n\
192 \n\
193 Lock the lock. Without argument, this blocks if the lock is already\n\
194 locked (even by the same thread), waiting for another thread to release\n\
195 the lock, and return True once the lock is acquired.\n\
196 With an argument, this will only block if the argument is true,\n\
197 and the return value reflects whether the lock is acquired.\n\
198 The blocking operation is interruptible.");
199
200 static PyObject *
lock_PyThread_release_lock(lockobject * self,PyObject * Py_UNUSED (ignored))201 lock_PyThread_release_lock(lockobject *self, PyObject *Py_UNUSED(ignored))
202 {
203 /* Sanity check: the lock must be locked */
204 if (!self->locked) {
205 PyErr_SetString(ThreadError, "release unlocked lock");
206 return NULL;
207 }
208
209 PyThread_release_lock(self->lock_lock);
210 self->locked = 0;
211 Py_RETURN_NONE;
212 }
213
214 PyDoc_STRVAR(release_doc,
215 "release()\n\
216 (release_lock() is an obsolete synonym)\n\
217 \n\
218 Release the lock, allowing another thread that is blocked waiting for\n\
219 the lock to acquire the lock. The lock must be in the locked state,\n\
220 but it needn't be locked by the same thread that unlocks it.");
221
222 static PyObject *
lock_locked_lock(lockobject * self,PyObject * Py_UNUSED (ignored))223 lock_locked_lock(lockobject *self, PyObject *Py_UNUSED(ignored))
224 {
225 return PyBool_FromLong((long)self->locked);
226 }
227
228 PyDoc_STRVAR(locked_doc,
229 "locked() -> bool\n\
230 (locked_lock() is an obsolete synonym)\n\
231 \n\
232 Return whether the lock is in the locked state.");
233
234 static PyObject *
lock_repr(lockobject * self)235 lock_repr(lockobject *self)
236 {
237 return PyUnicode_FromFormat("<%s %s object at %p>",
238 self->locked ? "locked" : "unlocked", Py_TYPE(self)->tp_name, self);
239 }
240
241 #ifdef HAVE_FORK
242 static PyObject *
lock__at_fork_reinit(lockobject * self,PyObject * Py_UNUSED (args))243 lock__at_fork_reinit(lockobject *self, PyObject *Py_UNUSED(args))
244 {
245 if (_PyThread_at_fork_reinit(&self->lock_lock) < 0) {
246 PyErr_SetString(ThreadError, "failed to reinitialize lock at fork");
247 return NULL;
248 }
249
250 self->locked = 0;
251
252 Py_RETURN_NONE;
253 }
254 #endif /* HAVE_FORK */
255
256
257 static PyMethodDef lock_methods[] = {
258 {"acquire_lock", _PyCFunction_CAST(lock_PyThread_acquire_lock),
259 METH_VARARGS | METH_KEYWORDS, acquire_doc},
260 {"acquire", _PyCFunction_CAST(lock_PyThread_acquire_lock),
261 METH_VARARGS | METH_KEYWORDS, acquire_doc},
262 {"release_lock", (PyCFunction)lock_PyThread_release_lock,
263 METH_NOARGS, release_doc},
264 {"release", (PyCFunction)lock_PyThread_release_lock,
265 METH_NOARGS, release_doc},
266 {"locked_lock", (PyCFunction)lock_locked_lock,
267 METH_NOARGS, locked_doc},
268 {"locked", (PyCFunction)lock_locked_lock,
269 METH_NOARGS, locked_doc},
270 {"__enter__", _PyCFunction_CAST(lock_PyThread_acquire_lock),
271 METH_VARARGS | METH_KEYWORDS, acquire_doc},
272 {"__exit__", (PyCFunction)lock_PyThread_release_lock,
273 METH_VARARGS, release_doc},
274 #ifdef HAVE_FORK
275 {"_at_fork_reinit", (PyCFunction)lock__at_fork_reinit,
276 METH_NOARGS, NULL},
277 #endif
278 {NULL, NULL} /* sentinel */
279 };
280
281 PyDoc_STRVAR(lock_doc,
282 "A lock object is a synchronization primitive. To create a lock,\n\
283 call threading.Lock(). Methods are:\n\
284 \n\
285 acquire() -- lock the lock, possibly blocking until it can be obtained\n\
286 release() -- unlock of the lock\n\
287 locked() -- test whether the lock is currently locked\n\
288 \n\
289 A lock is not owned by the thread that locked it; another thread may\n\
290 unlock it. A thread attempting to lock a lock that it has already locked\n\
291 will block until another thread unlocks it. Deadlocks may ensue.");
292
293 static PyMemberDef lock_type_members[] = {
294 {"__weaklistoffset__", T_PYSSIZET, offsetof(lockobject, in_weakreflist), READONLY},
295 {NULL},
296 };
297
298 static PyType_Slot lock_type_slots[] = {
299 {Py_tp_dealloc, (destructor)lock_dealloc},
300 {Py_tp_repr, (reprfunc)lock_repr},
301 {Py_tp_doc, (void *)lock_doc},
302 {Py_tp_methods, lock_methods},
303 {Py_tp_traverse, lock_traverse},
304 {Py_tp_members, lock_type_members},
305 {0, 0}
306 };
307
308 static PyType_Spec lock_type_spec = {
309 .name = "_thread.lock",
310 .basicsize = sizeof(lockobject),
311 .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
312 Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE),
313 .slots = lock_type_slots,
314 };
315
316 /* Recursive lock objects */
317
318 typedef struct {
319 PyObject_HEAD
320 PyThread_type_lock rlock_lock;
321 unsigned long rlock_owner;
322 unsigned long rlock_count;
323 PyObject *in_weakreflist;
324 } rlockobject;
325
326 static int
rlock_traverse(rlockobject * self,visitproc visit,void * arg)327 rlock_traverse(rlockobject *self, visitproc visit, void *arg)
328 {
329 Py_VISIT(Py_TYPE(self));
330 return 0;
331 }
332
333
334 static void
rlock_dealloc(rlockobject * self)335 rlock_dealloc(rlockobject *self)
336 {
337 PyObject_GC_UnTrack(self);
338 if (self->in_weakreflist != NULL)
339 PyObject_ClearWeakRefs((PyObject *) self);
340 /* self->rlock_lock can be NULL if PyThread_allocate_lock() failed
341 in rlock_new() */
342 if (self->rlock_lock != NULL) {
343 /* Unlock the lock so it's safe to free it */
344 if (self->rlock_count > 0)
345 PyThread_release_lock(self->rlock_lock);
346
347 PyThread_free_lock(self->rlock_lock);
348 }
349 PyTypeObject *tp = Py_TYPE(self);
350 tp->tp_free(self);
351 Py_DECREF(tp);
352 }
353
354 static PyObject *
rlock_acquire(rlockobject * self,PyObject * args,PyObject * kwds)355 rlock_acquire(rlockobject *self, PyObject *args, PyObject *kwds)
356 {
357 _PyTime_t timeout;
358 unsigned long tid;
359 PyLockStatus r = PY_LOCK_ACQUIRED;
360
361 if (lock_acquire_parse_args(args, kwds, &timeout) < 0)
362 return NULL;
363
364 tid = PyThread_get_thread_ident();
365 if (self->rlock_count > 0 && tid == self->rlock_owner) {
366 unsigned long count = self->rlock_count + 1;
367 if (count <= self->rlock_count) {
368 PyErr_SetString(PyExc_OverflowError,
369 "Internal lock count overflowed");
370 return NULL;
371 }
372 self->rlock_count = count;
373 Py_RETURN_TRUE;
374 }
375 r = acquire_timed(self->rlock_lock, timeout);
376 if (r == PY_LOCK_ACQUIRED) {
377 assert(self->rlock_count == 0);
378 self->rlock_owner = tid;
379 self->rlock_count = 1;
380 }
381 else if (r == PY_LOCK_INTR) {
382 return NULL;
383 }
384
385 return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
386 }
387
388 PyDoc_STRVAR(rlock_acquire_doc,
389 "acquire(blocking=True) -> bool\n\
390 \n\
391 Lock the lock. `blocking` indicates whether we should wait\n\
392 for the lock to be available or not. If `blocking` is False\n\
393 and another thread holds the lock, the method will return False\n\
394 immediately. If `blocking` is True and another thread holds\n\
395 the lock, the method will wait for the lock to be released,\n\
396 take it and then return True.\n\
397 (note: the blocking operation is interruptible.)\n\
398 \n\
399 In all other cases, the method will return True immediately.\n\
400 Precisely, if the current thread already holds the lock, its\n\
401 internal counter is simply incremented. If nobody holds the lock,\n\
402 the lock is taken and its internal counter initialized to 1.");
403
404 static PyObject *
rlock_release(rlockobject * self,PyObject * Py_UNUSED (ignored))405 rlock_release(rlockobject *self, PyObject *Py_UNUSED(ignored))
406 {
407 unsigned long tid = PyThread_get_thread_ident();
408
409 if (self->rlock_count == 0 || self->rlock_owner != tid) {
410 PyErr_SetString(PyExc_RuntimeError,
411 "cannot release un-acquired lock");
412 return NULL;
413 }
414 if (--self->rlock_count == 0) {
415 self->rlock_owner = 0;
416 PyThread_release_lock(self->rlock_lock);
417 }
418 Py_RETURN_NONE;
419 }
420
421 PyDoc_STRVAR(rlock_release_doc,
422 "release()\n\
423 \n\
424 Release the lock, allowing another thread that is blocked waiting for\n\
425 the lock to acquire the lock. The lock must be in the locked state,\n\
426 and must be locked by the same thread that unlocks it; otherwise a\n\
427 `RuntimeError` is raised.\n\
428 \n\
429 Do note that if the lock was acquire()d several times in a row by the\n\
430 current thread, release() needs to be called as many times for the lock\n\
431 to be available for other threads.");
432
433 static PyObject *
rlock_acquire_restore(rlockobject * self,PyObject * args)434 rlock_acquire_restore(rlockobject *self, PyObject *args)
435 {
436 unsigned long owner;
437 unsigned long count;
438 int r = 1;
439
440 if (!PyArg_ParseTuple(args, "(kk):_acquire_restore", &count, &owner))
441 return NULL;
442
443 if (!PyThread_acquire_lock(self->rlock_lock, 0)) {
444 Py_BEGIN_ALLOW_THREADS
445 r = PyThread_acquire_lock(self->rlock_lock, 1);
446 Py_END_ALLOW_THREADS
447 }
448 if (!r) {
449 PyErr_SetString(ThreadError, "couldn't acquire lock");
450 return NULL;
451 }
452 assert(self->rlock_count == 0);
453 self->rlock_owner = owner;
454 self->rlock_count = count;
455 Py_RETURN_NONE;
456 }
457
458 PyDoc_STRVAR(rlock_acquire_restore_doc,
459 "_acquire_restore(state) -> None\n\
460 \n\
461 For internal use by `threading.Condition`.");
462
463 static PyObject *
rlock_release_save(rlockobject * self,PyObject * Py_UNUSED (ignored))464 rlock_release_save(rlockobject *self, PyObject *Py_UNUSED(ignored))
465 {
466 unsigned long owner;
467 unsigned long count;
468
469 if (self->rlock_count == 0) {
470 PyErr_SetString(PyExc_RuntimeError,
471 "cannot release un-acquired lock");
472 return NULL;
473 }
474
475 owner = self->rlock_owner;
476 count = self->rlock_count;
477 self->rlock_count = 0;
478 self->rlock_owner = 0;
479 PyThread_release_lock(self->rlock_lock);
480 return Py_BuildValue("kk", count, owner);
481 }
482
483 PyDoc_STRVAR(rlock_release_save_doc,
484 "_release_save() -> tuple\n\
485 \n\
486 For internal use by `threading.Condition`.");
487
488
489 static PyObject *
rlock_is_owned(rlockobject * self,PyObject * Py_UNUSED (ignored))490 rlock_is_owned(rlockobject *self, PyObject *Py_UNUSED(ignored))
491 {
492 unsigned long tid = PyThread_get_thread_ident();
493
494 if (self->rlock_count > 0 && self->rlock_owner == tid) {
495 Py_RETURN_TRUE;
496 }
497 Py_RETURN_FALSE;
498 }
499
500 PyDoc_STRVAR(rlock_is_owned_doc,
501 "_is_owned() -> bool\n\
502 \n\
503 For internal use by `threading.Condition`.");
504
505 static PyObject *
rlock_new(PyTypeObject * type,PyObject * args,PyObject * kwds)506 rlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
507 {
508 rlockobject *self = (rlockobject *) type->tp_alloc(type, 0);
509 if (self == NULL) {
510 return NULL;
511 }
512 self->in_weakreflist = NULL;
513 self->rlock_owner = 0;
514 self->rlock_count = 0;
515
516 self->rlock_lock = PyThread_allocate_lock();
517 if (self->rlock_lock == NULL) {
518 Py_DECREF(self);
519 PyErr_SetString(ThreadError, "can't allocate lock");
520 return NULL;
521 }
522 return (PyObject *) self;
523 }
524
525 static PyObject *
rlock_repr(rlockobject * self)526 rlock_repr(rlockobject *self)
527 {
528 return PyUnicode_FromFormat("<%s %s object owner=%ld count=%lu at %p>",
529 self->rlock_count ? "locked" : "unlocked",
530 Py_TYPE(self)->tp_name, self->rlock_owner,
531 self->rlock_count, self);
532 }
533
534
535 #ifdef HAVE_FORK
536 static PyObject *
rlock__at_fork_reinit(rlockobject * self,PyObject * Py_UNUSED (args))537 rlock__at_fork_reinit(rlockobject *self, PyObject *Py_UNUSED(args))
538 {
539 if (_PyThread_at_fork_reinit(&self->rlock_lock) < 0) {
540 PyErr_SetString(ThreadError, "failed to reinitialize lock at fork");
541 return NULL;
542 }
543
544 self->rlock_owner = 0;
545 self->rlock_count = 0;
546
547 Py_RETURN_NONE;
548 }
549 #endif /* HAVE_FORK */
550
551
552 static PyMethodDef rlock_methods[] = {
553 {"acquire", _PyCFunction_CAST(rlock_acquire),
554 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
555 {"release", (PyCFunction)rlock_release,
556 METH_NOARGS, rlock_release_doc},
557 {"_is_owned", (PyCFunction)rlock_is_owned,
558 METH_NOARGS, rlock_is_owned_doc},
559 {"_acquire_restore", (PyCFunction)rlock_acquire_restore,
560 METH_VARARGS, rlock_acquire_restore_doc},
561 {"_release_save", (PyCFunction)rlock_release_save,
562 METH_NOARGS, rlock_release_save_doc},
563 {"__enter__", _PyCFunction_CAST(rlock_acquire),
564 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
565 {"__exit__", (PyCFunction)rlock_release,
566 METH_VARARGS, rlock_release_doc},
567 #ifdef HAVE_FORK
568 {"_at_fork_reinit", (PyCFunction)rlock__at_fork_reinit,
569 METH_NOARGS, NULL},
570 #endif
571 {NULL, NULL} /* sentinel */
572 };
573
574
575 static PyMemberDef rlock_type_members[] = {
576 {"__weaklistoffset__", T_PYSSIZET, offsetof(rlockobject, in_weakreflist), READONLY},
577 {NULL},
578 };
579
580 static PyType_Slot rlock_type_slots[] = {
581 {Py_tp_dealloc, (destructor)rlock_dealloc},
582 {Py_tp_repr, (reprfunc)rlock_repr},
583 {Py_tp_methods, rlock_methods},
584 {Py_tp_alloc, PyType_GenericAlloc},
585 {Py_tp_new, rlock_new},
586 {Py_tp_members, rlock_type_members},
587 {Py_tp_traverse, rlock_traverse},
588 {0, 0},
589 };
590
591 static PyType_Spec rlock_type_spec = {
592 .name = "_thread.RLock",
593 .basicsize = sizeof(rlockobject),
594 .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
595 Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE),
596 .slots = rlock_type_slots,
597 };
598
599 static lockobject *
newlockobject(PyObject * module)600 newlockobject(PyObject *module)
601 {
602 thread_module_state *state = get_thread_state(module);
603
604 PyTypeObject *type = state->lock_type;
605 lockobject *self = (lockobject *)type->tp_alloc(type, 0);
606 if (self == NULL) {
607 return NULL;
608 }
609
610 self->lock_lock = PyThread_allocate_lock();
611 self->locked = 0;
612 self->in_weakreflist = NULL;
613
614 if (self->lock_lock == NULL) {
615 Py_DECREF(self);
616 PyErr_SetString(ThreadError, "can't allocate lock");
617 return NULL;
618 }
619 return self;
620 }
621
622 /* Thread-local objects */
623
624 /* Quick overview:
625
626 We need to be able to reclaim reference cycles as soon as possible
627 (both when a thread is being terminated, or a thread-local object
628 becomes unreachable from user data). Constraints:
629 - it must not be possible for thread-state dicts to be involved in
630 reference cycles (otherwise the cyclic GC will refuse to consider
631 objects referenced from a reachable thread-state dict, even though
632 local_dealloc would clear them)
633 - the death of a thread-state dict must still imply destruction of the
634 corresponding local dicts in all thread-local objects.
635
636 Our implementation uses small "localdummy" objects in order to break
637 the reference chain. These trivial objects are hashable (using the
638 default scheme of identity hashing) and weakrefable.
639 Each thread-state holds a separate localdummy for each local object
640 (as a /strong reference/),
641 and each thread-local object holds a dict mapping /weak references/
642 of localdummies to local dicts.
643
644 Therefore:
645 - only the thread-state dict holds a strong reference to the dummies
646 - only the thread-local object holds a strong reference to the local dicts
647 - only outside objects (application- or library-level) hold strong
648 references to the thread-local objects
649 - as soon as a thread-state dict is destroyed, the weakref callbacks of all
650 dummies attached to that thread are called, and destroy the corresponding
651 local dicts from thread-local objects
652 - as soon as a thread-local object is destroyed, its local dicts are
653 destroyed and its dummies are manually removed from all thread states
654 - the GC can do its work correctly when a thread-local object is dangling,
655 without any interference from the thread-state dicts
656
657 As an additional optimization, each localdummy holds a borrowed reference
658 to the corresponding localdict. This borrowed reference is only used
659 by the thread-local object which has created the localdummy, which should
660 guarantee that the localdict still exists when accessed.
661 */
662
663 typedef struct {
664 PyObject_HEAD
665 PyObject *localdict; /* Borrowed reference! */
666 PyObject *weakreflist; /* List of weak references to self */
667 } localdummyobject;
668
669 static void
localdummy_dealloc(localdummyobject * self)670 localdummy_dealloc(localdummyobject *self)
671 {
672 if (self->weakreflist != NULL)
673 PyObject_ClearWeakRefs((PyObject *) self);
674 PyTypeObject *tp = Py_TYPE(self);
675 tp->tp_free((PyObject*)self);
676 Py_DECREF(tp);
677 }
678
679 static PyMemberDef local_dummy_type_members[] = {
680 {"__weaklistoffset__", T_PYSSIZET, offsetof(localdummyobject, weakreflist), READONLY},
681 {NULL},
682 };
683
684 static PyType_Slot local_dummy_type_slots[] = {
685 {Py_tp_dealloc, (destructor)localdummy_dealloc},
686 {Py_tp_doc, "Thread-local dummy"},
687 {Py_tp_members, local_dummy_type_members},
688 {0, 0}
689 };
690
691 static PyType_Spec local_dummy_type_spec = {
692 .name = "_thread._localdummy",
693 .basicsize = sizeof(localdummyobject),
694 .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION |
695 Py_TPFLAGS_IMMUTABLETYPE),
696 .slots = local_dummy_type_slots,
697 };
698
699
700 typedef struct {
701 PyObject_HEAD
702 PyObject *key;
703 PyObject *args;
704 PyObject *kw;
705 PyObject *weakreflist; /* List of weak references to self */
706 /* A {localdummy weakref -> localdict} dict */
707 PyObject *dummies;
708 /* The callback for weakrefs to localdummies */
709 PyObject *wr_callback;
710 } localobject;
711
712 /* Forward declaration */
713 static PyObject *_ldict(localobject *self, thread_module_state *state);
714 static PyObject *_localdummy_destroyed(PyObject *meth_self, PyObject *dummyweakref);
715
716 /* Create and register the dummy for the current thread.
717 Returns a borrowed reference of the corresponding local dict */
718 static PyObject *
_local_create_dummy(localobject * self,thread_module_state * state)719 _local_create_dummy(localobject *self, thread_module_state *state)
720 {
721 PyObject *ldict = NULL, *wr = NULL;
722 localdummyobject *dummy = NULL;
723 PyTypeObject *type = state->local_dummy_type;
724
725 PyObject *tdict = PyThreadState_GetDict();
726 if (tdict == NULL) {
727 PyErr_SetString(PyExc_SystemError,
728 "Couldn't get thread-state dictionary");
729 goto err;
730 }
731
732 ldict = PyDict_New();
733 if (ldict == NULL) {
734 goto err;
735 }
736 dummy = (localdummyobject *) type->tp_alloc(type, 0);
737 if (dummy == NULL) {
738 goto err;
739 }
740 dummy->localdict = ldict;
741 wr = PyWeakref_NewRef((PyObject *) dummy, self->wr_callback);
742 if (wr == NULL) {
743 goto err;
744 }
745
746 /* As a side-effect, this will cache the weakref's hash before the
747 dummy gets deleted */
748 int r = PyDict_SetItem(self->dummies, wr, ldict);
749 if (r < 0) {
750 goto err;
751 }
752 Py_CLEAR(wr);
753 r = PyDict_SetItem(tdict, self->key, (PyObject *) dummy);
754 if (r < 0) {
755 goto err;
756 }
757 Py_CLEAR(dummy);
758
759 Py_DECREF(ldict);
760 return ldict;
761
762 err:
763 Py_XDECREF(ldict);
764 Py_XDECREF(wr);
765 Py_XDECREF(dummy);
766 return NULL;
767 }
768
769 static PyObject *
local_new(PyTypeObject * type,PyObject * args,PyObject * kw)770 local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
771 {
772 static PyMethodDef wr_callback_def = {
773 "_localdummy_destroyed", (PyCFunction) _localdummy_destroyed, METH_O
774 };
775
776 if (type->tp_init == PyBaseObject_Type.tp_init) {
777 int rc = 0;
778 if (args != NULL)
779 rc = PyObject_IsTrue(args);
780 if (rc == 0 && kw != NULL)
781 rc = PyObject_IsTrue(kw);
782 if (rc != 0) {
783 if (rc > 0) {
784 PyErr_SetString(PyExc_TypeError,
785 "Initialization arguments are not supported");
786 }
787 return NULL;
788 }
789 }
790
791 PyObject *module = PyType_GetModuleByDef(type, &thread_module);
792 thread_module_state *state = get_thread_state(module);
793
794 localobject *self = (localobject *)type->tp_alloc(type, 0);
795 if (self == NULL) {
796 return NULL;
797 }
798
799 self->args = Py_XNewRef(args);
800 self->kw = Py_XNewRef(kw);
801 self->key = PyUnicode_FromFormat("thread.local.%p", self);
802 if (self->key == NULL) {
803 goto err;
804 }
805
806 self->dummies = PyDict_New();
807 if (self->dummies == NULL) {
808 goto err;
809 }
810
811 /* We use a weak reference to self in the callback closure
812 in order to avoid spurious reference cycles */
813 PyObject *wr = PyWeakref_NewRef((PyObject *) self, NULL);
814 if (wr == NULL) {
815 goto err;
816 }
817 self->wr_callback = PyCFunction_NewEx(&wr_callback_def, wr, NULL);
818 Py_DECREF(wr);
819 if (self->wr_callback == NULL) {
820 goto err;
821 }
822 if (_local_create_dummy(self, state) == NULL) {
823 goto err;
824 }
825 return (PyObject *)self;
826
827 err:
828 Py_DECREF(self);
829 return NULL;
830 }
831
832 static int
local_traverse(localobject * self,visitproc visit,void * arg)833 local_traverse(localobject *self, visitproc visit, void *arg)
834 {
835 Py_VISIT(Py_TYPE(self));
836 Py_VISIT(self->args);
837 Py_VISIT(self->kw);
838 Py_VISIT(self->dummies);
839 return 0;
840 }
841
842 #define HEAD_LOCK(runtime) \
843 PyThread_acquire_lock((runtime)->interpreters.mutex, WAIT_LOCK)
844 #define HEAD_UNLOCK(runtime) \
845 PyThread_release_lock((runtime)->interpreters.mutex)
846
847 static int
local_clear(localobject * self)848 local_clear(localobject *self)
849 {
850 Py_CLEAR(self->args);
851 Py_CLEAR(self->kw);
852 Py_CLEAR(self->dummies);
853 Py_CLEAR(self->wr_callback);
854 /* Remove all strong references to dummies from the thread states */
855 if (self->key) {
856 PyInterpreterState *interp = _PyInterpreterState_GET();
857 _PyRuntimeState *runtime = &_PyRuntime;
858 HEAD_LOCK(runtime);
859 PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
860 HEAD_UNLOCK(runtime);
861 while (tstate) {
862 if (tstate->dict) {
863 PyObject *v = _PyDict_Pop(tstate->dict, self->key, Py_None);
864 if (v != NULL) {
865 Py_DECREF(v);
866 }
867 else {
868 PyErr_Clear();
869 }
870 }
871 HEAD_LOCK(runtime);
872 tstate = PyThreadState_Next(tstate);
873 HEAD_UNLOCK(runtime);
874 }
875 }
876 return 0;
877 }
878
879 static void
local_dealloc(localobject * self)880 local_dealloc(localobject *self)
881 {
882 /* Weakrefs must be invalidated right now, otherwise they can be used
883 from code called below, which is very dangerous since Py_REFCNT(self) == 0 */
884 if (self->weakreflist != NULL) {
885 PyObject_ClearWeakRefs((PyObject *) self);
886 }
887
888 PyObject_GC_UnTrack(self);
889
890 local_clear(self);
891 Py_XDECREF(self->key);
892
893 PyTypeObject *tp = Py_TYPE(self);
894 tp->tp_free((PyObject*)self);
895 Py_DECREF(tp);
896 }
897
898 /* Returns a borrowed reference to the local dict, creating it if necessary */
899 static PyObject *
_ldict(localobject * self,thread_module_state * state)900 _ldict(localobject *self, thread_module_state *state)
901 {
902 PyObject *tdict = PyThreadState_GetDict();
903 if (tdict == NULL) {
904 PyErr_SetString(PyExc_SystemError,
905 "Couldn't get thread-state dictionary");
906 return NULL;
907 }
908
909 PyObject *ldict;
910 PyObject *dummy = PyDict_GetItemWithError(tdict, self->key);
911 if (dummy == NULL) {
912 if (PyErr_Occurred()) {
913 return NULL;
914 }
915 ldict = _local_create_dummy(self, state);
916 if (ldict == NULL)
917 return NULL;
918
919 if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init &&
920 Py_TYPE(self)->tp_init((PyObject*)self,
921 self->args, self->kw) < 0) {
922 /* we need to get rid of ldict from thread so
923 we create a new one the next time we do an attr
924 access */
925 PyDict_DelItem(tdict, self->key);
926 return NULL;
927 }
928 }
929 else {
930 assert(Py_IS_TYPE(dummy, state->local_dummy_type));
931 ldict = ((localdummyobject *) dummy)->localdict;
932 }
933
934 return ldict;
935 }
936
937 static int
local_setattro(localobject * self,PyObject * name,PyObject * v)938 local_setattro(localobject *self, PyObject *name, PyObject *v)
939 {
940 PyObject *module = PyType_GetModuleByDef(Py_TYPE(self), &thread_module);
941 thread_module_state *state = get_thread_state(module);
942
943 PyObject *ldict = _ldict(self, state);
944 if (ldict == NULL) {
945 return -1;
946 }
947
948 int r = PyObject_RichCompareBool(name, &_Py_ID(__dict__), Py_EQ);
949 if (r == -1) {
950 return -1;
951 }
952 if (r == 1) {
953 PyErr_Format(PyExc_AttributeError,
954 "'%.50s' object attribute '%U' is read-only",
955 Py_TYPE(self)->tp_name, name);
956 return -1;
957 }
958
959 return _PyObject_GenericSetAttrWithDict((PyObject *)self, name, v, ldict);
960 }
961
962 static PyObject *local_getattro(localobject *, PyObject *);
963
964 static PyMemberDef local_type_members[] = {
965 {"__weaklistoffset__", T_PYSSIZET, offsetof(localobject, weakreflist), READONLY},
966 {NULL},
967 };
968
969 static PyType_Slot local_type_slots[] = {
970 {Py_tp_dealloc, (destructor)local_dealloc},
971 {Py_tp_getattro, (getattrofunc)local_getattro},
972 {Py_tp_setattro, (setattrofunc)local_setattro},
973 {Py_tp_doc, "Thread-local data"},
974 {Py_tp_traverse, (traverseproc)local_traverse},
975 {Py_tp_clear, (inquiry)local_clear},
976 {Py_tp_new, local_new},
977 {Py_tp_members, local_type_members},
978 {0, 0}
979 };
980
981 static PyType_Spec local_type_spec = {
982 .name = "_thread._local",
983 .basicsize = sizeof(localobject),
984 .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
985 Py_TPFLAGS_IMMUTABLETYPE),
986 .slots = local_type_slots,
987 };
988
989 static PyObject *
local_getattro(localobject * self,PyObject * name)990 local_getattro(localobject *self, PyObject *name)
991 {
992 PyObject *module = PyType_GetModuleByDef(Py_TYPE(self), &thread_module);
993 thread_module_state *state = get_thread_state(module);
994
995 PyObject *ldict = _ldict(self, state);
996 if (ldict == NULL)
997 return NULL;
998
999 int r = PyObject_RichCompareBool(name, &_Py_ID(__dict__), Py_EQ);
1000 if (r == 1) {
1001 return Py_NewRef(ldict);
1002 }
1003 if (r == -1) {
1004 return NULL;
1005 }
1006
1007 if (!Py_IS_TYPE(self, state->local_type)) {
1008 /* use generic lookup for subtypes */
1009 return _PyObject_GenericGetAttrWithDict((PyObject *)self, name,
1010 ldict, 0);
1011 }
1012
1013 /* Optimization: just look in dict ourselves */
1014 PyObject *value = PyDict_GetItemWithError(ldict, name);
1015 if (value != NULL) {
1016 return Py_NewRef(value);
1017 }
1018 if (PyErr_Occurred()) {
1019 return NULL;
1020 }
1021
1022 /* Fall back on generic to get __class__ and __dict__ */
1023 return _PyObject_GenericGetAttrWithDict(
1024 (PyObject *)self, name, ldict, 0);
1025 }
1026
1027 /* Called when a dummy is destroyed. */
1028 static PyObject *
_localdummy_destroyed(PyObject * localweakref,PyObject * dummyweakref)1029 _localdummy_destroyed(PyObject *localweakref, PyObject *dummyweakref)
1030 {
1031 assert(PyWeakref_CheckRef(localweakref));
1032 PyObject *obj = PyWeakref_GET_OBJECT(localweakref);
1033 if (obj == Py_None) {
1034 Py_RETURN_NONE;
1035 }
1036
1037 /* If the thread-local object is still alive and not being cleared,
1038 remove the corresponding local dict */
1039 localobject *self = (localobject *)Py_NewRef(obj);
1040 if (self->dummies != NULL) {
1041 PyObject *ldict;
1042 ldict = PyDict_GetItemWithError(self->dummies, dummyweakref);
1043 if (ldict != NULL) {
1044 PyDict_DelItem(self->dummies, dummyweakref);
1045 }
1046 if (PyErr_Occurred())
1047 PyErr_WriteUnraisable(obj);
1048 }
1049 Py_DECREF(obj);
1050 Py_RETURN_NONE;
1051 }
1052
1053 /* Module functions */
1054
1055 struct bootstate {
1056 PyInterpreterState *interp;
1057 PyObject *func;
1058 PyObject *args;
1059 PyObject *kwargs;
1060 PyThreadState *tstate;
1061 _PyRuntimeState *runtime;
1062 };
1063
1064
1065 static void
thread_bootstate_free(struct bootstate * boot)1066 thread_bootstate_free(struct bootstate *boot)
1067 {
1068 Py_DECREF(boot->func);
1069 Py_DECREF(boot->args);
1070 Py_XDECREF(boot->kwargs);
1071 PyMem_Free(boot);
1072 }
1073
1074
1075 static void
thread_run(void * boot_raw)1076 thread_run(void *boot_raw)
1077 {
1078 struct bootstate *boot = (struct bootstate *) boot_raw;
1079 PyThreadState *tstate;
1080
1081 tstate = boot->tstate;
1082 tstate->thread_id = PyThread_get_thread_ident();
1083 #ifdef PY_HAVE_THREAD_NATIVE_ID
1084 tstate->native_thread_id = PyThread_get_thread_native_id();
1085 #else
1086 tstate->native_thread_id = 0;
1087 #endif
1088 _PyThreadState_SetCurrent(tstate);
1089 PyEval_AcquireThread(tstate);
1090 tstate->interp->threads.count++;
1091
1092 PyObject *res = PyObject_Call(boot->func, boot->args, boot->kwargs);
1093 if (res == NULL) {
1094 if (PyErr_ExceptionMatches(PyExc_SystemExit))
1095 /* SystemExit is ignored silently */
1096 PyErr_Clear();
1097 else {
1098 _PyErr_WriteUnraisableMsg("in thread started by", boot->func);
1099 }
1100 }
1101 else {
1102 Py_DECREF(res);
1103 }
1104
1105 thread_bootstate_free(boot);
1106 tstate->interp->threads.count--;
1107 PyThreadState_Clear(tstate);
1108 _PyThreadState_DeleteCurrent(tstate);
1109
1110 // bpo-44434: Don't call explicitly PyThread_exit_thread(). On Linux with
1111 // the glibc, pthread_exit() can abort the whole process if dlopen() fails
1112 // to open the libgcc_s.so library (ex: EMFILE error).
1113 }
1114
1115 static PyObject *
thread_PyThread_start_new_thread(PyObject * self,PyObject * fargs)1116 thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
1117 {
1118 _PyRuntimeState *runtime = &_PyRuntime;
1119 PyObject *func, *args, *kwargs = NULL;
1120
1121 if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3,
1122 &func, &args, &kwargs))
1123 return NULL;
1124 if (!PyCallable_Check(func)) {
1125 PyErr_SetString(PyExc_TypeError,
1126 "first arg must be callable");
1127 return NULL;
1128 }
1129 if (!PyTuple_Check(args)) {
1130 PyErr_SetString(PyExc_TypeError,
1131 "2nd arg must be a tuple");
1132 return NULL;
1133 }
1134 if (kwargs != NULL && !PyDict_Check(kwargs)) {
1135 PyErr_SetString(PyExc_TypeError,
1136 "optional 3rd arg must be a dictionary");
1137 return NULL;
1138 }
1139
1140 PyInterpreterState *interp = _PyInterpreterState_GET();
1141 if (interp->config._isolated_interpreter) {
1142 PyErr_SetString(PyExc_RuntimeError,
1143 "thread is not supported for isolated subinterpreters");
1144 return NULL;
1145 }
1146
1147 struct bootstate *boot = PyMem_NEW(struct bootstate, 1);
1148 if (boot == NULL) {
1149 return PyErr_NoMemory();
1150 }
1151 boot->interp = _PyInterpreterState_GET();
1152 boot->tstate = _PyThreadState_Prealloc(boot->interp);
1153 if (boot->tstate == NULL) {
1154 PyMem_Free(boot);
1155 return PyErr_NoMemory();
1156 }
1157 boot->runtime = runtime;
1158 boot->func = Py_NewRef(func);
1159 boot->args = Py_NewRef(args);
1160 boot->kwargs = Py_XNewRef(kwargs);
1161
1162 unsigned long ident = PyThread_start_new_thread(thread_run, (void*) boot);
1163 if (ident == PYTHREAD_INVALID_THREAD_ID) {
1164 PyErr_SetString(ThreadError, "can't start new thread");
1165 PyThreadState_Clear(boot->tstate);
1166 thread_bootstate_free(boot);
1167 return NULL;
1168 }
1169 return PyLong_FromUnsignedLong(ident);
1170 }
1171
1172 PyDoc_STRVAR(start_new_doc,
1173 "start_new_thread(function, args[, kwargs])\n\
1174 (start_new() is an obsolete synonym)\n\
1175 \n\
1176 Start a new thread and return its identifier. The thread will call the\n\
1177 function with positional arguments from the tuple args and keyword arguments\n\
1178 taken from the optional dictionary kwargs. The thread exits when the\n\
1179 function returns; the return value is ignored. The thread will also exit\n\
1180 when the function raises an unhandled exception; a stack trace will be\n\
1181 printed unless the exception is SystemExit.\n");
1182
1183 static PyObject *
thread_PyThread_exit_thread(PyObject * self,PyObject * Py_UNUSED (ignored))1184 thread_PyThread_exit_thread(PyObject *self, PyObject *Py_UNUSED(ignored))
1185 {
1186 PyErr_SetNone(PyExc_SystemExit);
1187 return NULL;
1188 }
1189
1190 PyDoc_STRVAR(exit_doc,
1191 "exit()\n\
1192 (exit_thread() is an obsolete synonym)\n\
1193 \n\
1194 This is synonymous to ``raise SystemExit''. It will cause the current\n\
1195 thread to exit silently unless the exception is caught.");
1196
1197 static PyObject *
thread_PyThread_interrupt_main(PyObject * self,PyObject * args)1198 thread_PyThread_interrupt_main(PyObject *self, PyObject *args)
1199 {
1200 int signum = SIGINT;
1201 if (!PyArg_ParseTuple(args, "|i:signum", &signum)) {
1202 return NULL;
1203 }
1204
1205 if (PyErr_SetInterruptEx(signum)) {
1206 PyErr_SetString(PyExc_ValueError, "signal number out of range");
1207 return NULL;
1208 }
1209 Py_RETURN_NONE;
1210 }
1211
1212 PyDoc_STRVAR(interrupt_doc,
1213 "interrupt_main(signum=signal.SIGINT, /)\n\
1214 \n\
1215 Simulate the arrival of the given signal in the main thread,\n\
1216 where the corresponding signal handler will be executed.\n\
1217 If *signum* is omitted, SIGINT is assumed.\n\
1218 A subthread can use this function to interrupt the main thread.\n\
1219 \n\
1220 Note: the default signal handler for SIGINT raises ``KeyboardInterrupt``."
1221 );
1222
1223 static lockobject *newlockobject(PyObject *module);
1224
1225 static PyObject *
thread_PyThread_allocate_lock(PyObject * module,PyObject * Py_UNUSED (ignored))1226 thread_PyThread_allocate_lock(PyObject *module, PyObject *Py_UNUSED(ignored))
1227 {
1228 return (PyObject *) newlockobject(module);
1229 }
1230
1231 PyDoc_STRVAR(allocate_doc,
1232 "allocate_lock() -> lock object\n\
1233 (allocate() is an obsolete synonym)\n\
1234 \n\
1235 Create a new lock object. See help(type(threading.Lock())) for\n\
1236 information about locks.");
1237
1238 static PyObject *
thread_get_ident(PyObject * self,PyObject * Py_UNUSED (ignored))1239 thread_get_ident(PyObject *self, PyObject *Py_UNUSED(ignored))
1240 {
1241 unsigned long ident = PyThread_get_thread_ident();
1242 if (ident == PYTHREAD_INVALID_THREAD_ID) {
1243 PyErr_SetString(ThreadError, "no current thread ident");
1244 return NULL;
1245 }
1246 return PyLong_FromUnsignedLong(ident);
1247 }
1248
1249 PyDoc_STRVAR(get_ident_doc,
1250 "get_ident() -> integer\n\
1251 \n\
1252 Return a non-zero integer that uniquely identifies the current thread\n\
1253 amongst other threads that exist simultaneously.\n\
1254 This may be used to identify per-thread resources.\n\
1255 Even though on some platforms threads identities may appear to be\n\
1256 allocated consecutive numbers starting at 1, this behavior should not\n\
1257 be relied upon, and the number should be seen purely as a magic cookie.\n\
1258 A thread's identity may be reused for another thread after it exits.");
1259
1260 #ifdef PY_HAVE_THREAD_NATIVE_ID
1261 static PyObject *
thread_get_native_id(PyObject * self,PyObject * Py_UNUSED (ignored))1262 thread_get_native_id(PyObject *self, PyObject *Py_UNUSED(ignored))
1263 {
1264 unsigned long native_id = PyThread_get_thread_native_id();
1265 return PyLong_FromUnsignedLong(native_id);
1266 }
1267
1268 PyDoc_STRVAR(get_native_id_doc,
1269 "get_native_id() -> integer\n\
1270 \n\
1271 Return a non-negative integer identifying the thread as reported\n\
1272 by the OS (kernel). This may be used to uniquely identify a\n\
1273 particular thread within a system.");
1274 #endif
1275
1276 static PyObject *
thread__count(PyObject * self,PyObject * Py_UNUSED (ignored))1277 thread__count(PyObject *self, PyObject *Py_UNUSED(ignored))
1278 {
1279 PyInterpreterState *interp = _PyInterpreterState_GET();
1280 return PyLong_FromLong(interp->threads.count);
1281 }
1282
1283 PyDoc_STRVAR(_count_doc,
1284 "_count() -> integer\n\
1285 \n\
1286 \
1287 Return the number of currently running Python threads, excluding\n\
1288 the main thread. The returned number comprises all threads created\n\
1289 through `start_new_thread()` as well as `threading.Thread`, and not\n\
1290 yet finished.\n\
1291 \n\
1292 This function is meant for internal and specialized purposes only.\n\
1293 In most applications `threading.enumerate()` should be used instead.");
1294
1295 static void
release_sentinel(void * wr_raw)1296 release_sentinel(void *wr_raw)
1297 {
1298 PyObject *wr = _PyObject_CAST(wr_raw);
1299 /* Tricky: this function is called when the current thread state
1300 is being deleted. Therefore, only simple C code can safely
1301 execute here. */
1302 PyObject *obj = PyWeakref_GET_OBJECT(wr);
1303 lockobject *lock;
1304 if (obj != Py_None) {
1305 lock = (lockobject *) obj;
1306 if (lock->locked) {
1307 PyThread_release_lock(lock->lock_lock);
1308 lock->locked = 0;
1309 }
1310 }
1311 /* Deallocating a weakref with a NULL callback only calls
1312 PyObject_GC_Del(), which can't call any Python code. */
1313 Py_DECREF(wr);
1314 }
1315
1316 static PyObject *
thread__set_sentinel(PyObject * module,PyObject * Py_UNUSED (ignored))1317 thread__set_sentinel(PyObject *module, PyObject *Py_UNUSED(ignored))
1318 {
1319 PyObject *wr;
1320 PyThreadState *tstate = _PyThreadState_GET();
1321 lockobject *lock;
1322
1323 if (tstate->on_delete_data != NULL) {
1324 /* We must support the re-creation of the lock from a
1325 fork()ed child. */
1326 assert(tstate->on_delete == &release_sentinel);
1327 wr = (PyObject *) tstate->on_delete_data;
1328 tstate->on_delete = NULL;
1329 tstate->on_delete_data = NULL;
1330 Py_DECREF(wr);
1331 }
1332 lock = newlockobject(module);
1333 if (lock == NULL)
1334 return NULL;
1335 /* The lock is owned by whoever called _set_sentinel(), but the weakref
1336 hangs to the thread state. */
1337 wr = PyWeakref_NewRef((PyObject *) lock, NULL);
1338 if (wr == NULL) {
1339 Py_DECREF(lock);
1340 return NULL;
1341 }
1342 tstate->on_delete_data = (void *) wr;
1343 tstate->on_delete = &release_sentinel;
1344 return (PyObject *) lock;
1345 }
1346
1347 PyDoc_STRVAR(_set_sentinel_doc,
1348 "_set_sentinel() -> lock\n\
1349 \n\
1350 Set a sentinel lock that will be released when the current thread\n\
1351 state is finalized (after it is untied from the interpreter).\n\
1352 \n\
1353 This is a private API for the threading module.");
1354
1355 static PyObject *
thread_stack_size(PyObject * self,PyObject * args)1356 thread_stack_size(PyObject *self, PyObject *args)
1357 {
1358 size_t old_size;
1359 Py_ssize_t new_size = 0;
1360 int rc;
1361
1362 if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size))
1363 return NULL;
1364
1365 if (new_size < 0) {
1366 PyErr_SetString(PyExc_ValueError,
1367 "size must be 0 or a positive value");
1368 return NULL;
1369 }
1370
1371 old_size = PyThread_get_stacksize();
1372
1373 rc = PyThread_set_stacksize((size_t) new_size);
1374 if (rc == -1) {
1375 PyErr_Format(PyExc_ValueError,
1376 "size not valid: %zd bytes",
1377 new_size);
1378 return NULL;
1379 }
1380 if (rc == -2) {
1381 PyErr_SetString(ThreadError,
1382 "setting stack size not supported");
1383 return NULL;
1384 }
1385
1386 return PyLong_FromSsize_t((Py_ssize_t) old_size);
1387 }
1388
1389 PyDoc_STRVAR(stack_size_doc,
1390 "stack_size([size]) -> size\n\
1391 \n\
1392 Return the thread stack size used when creating new threads. The\n\
1393 optional size argument specifies the stack size (in bytes) to be used\n\
1394 for subsequently created threads, and must be 0 (use platform or\n\
1395 configured default) or a positive integer value of at least 32,768 (32k).\n\
1396 If changing the thread stack size is unsupported, a ThreadError\n\
1397 exception is raised. If the specified size is invalid, a ValueError\n\
1398 exception is raised, and the stack size is unmodified. 32k bytes\n\
1399 currently the minimum supported stack size value to guarantee\n\
1400 sufficient stack space for the interpreter itself.\n\
1401 \n\
1402 Note that some platforms may have particular restrictions on values for\n\
1403 the stack size, such as requiring a minimum stack size larger than 32 KiB or\n\
1404 requiring allocation in multiples of the system memory page size\n\
1405 - platform documentation should be referred to for more information\n\
1406 (4 KiB pages are common; using multiples of 4096 for the stack size is\n\
1407 the suggested approach in the absence of more specific information).");
1408
1409 static int
thread_excepthook_file(PyObject * file,PyObject * exc_type,PyObject * exc_value,PyObject * exc_traceback,PyObject * thread)1410 thread_excepthook_file(PyObject *file, PyObject *exc_type, PyObject *exc_value,
1411 PyObject *exc_traceback, PyObject *thread)
1412 {
1413 /* print(f"Exception in thread {thread.name}:", file=file) */
1414 if (PyFile_WriteString("Exception in thread ", file) < 0) {
1415 return -1;
1416 }
1417
1418 PyObject *name = NULL;
1419 if (thread != Py_None) {
1420 if (_PyObject_LookupAttr(thread, &_Py_ID(name), &name) < 0) {
1421 return -1;
1422 }
1423 }
1424 if (name != NULL) {
1425 if (PyFile_WriteObject(name, file, Py_PRINT_RAW) < 0) {
1426 Py_DECREF(name);
1427 return -1;
1428 }
1429 Py_DECREF(name);
1430 }
1431 else {
1432 unsigned long ident = PyThread_get_thread_ident();
1433 PyObject *str = PyUnicode_FromFormat("%lu", ident);
1434 if (str != NULL) {
1435 if (PyFile_WriteObject(str, file, Py_PRINT_RAW) < 0) {
1436 Py_DECREF(str);
1437 return -1;
1438 }
1439 Py_DECREF(str);
1440 }
1441 else {
1442 PyErr_Clear();
1443
1444 if (PyFile_WriteString("<failed to get thread name>", file) < 0) {
1445 return -1;
1446 }
1447 }
1448 }
1449
1450 if (PyFile_WriteString(":\n", file) < 0) {
1451 return -1;
1452 }
1453
1454 /* Display the traceback */
1455 _PyErr_Display(file, exc_type, exc_value, exc_traceback);
1456
1457 /* Call file.flush() */
1458 PyObject *res = PyObject_CallMethodNoArgs(file, &_Py_ID(flush));
1459 if (!res) {
1460 return -1;
1461 }
1462 Py_DECREF(res);
1463
1464 return 0;
1465 }
1466
1467
1468 PyDoc_STRVAR(ExceptHookArgs__doc__,
1469 "ExceptHookArgs\n\
1470 \n\
1471 Type used to pass arguments to threading.excepthook.");
1472
1473 static PyStructSequence_Field ExceptHookArgs_fields[] = {
1474 {"exc_type", "Exception type"},
1475 {"exc_value", "Exception value"},
1476 {"exc_traceback", "Exception traceback"},
1477 {"thread", "Thread"},
1478 {0}
1479 };
1480
1481 static PyStructSequence_Desc ExceptHookArgs_desc = {
1482 .name = "_thread._ExceptHookArgs",
1483 .doc = ExceptHookArgs__doc__,
1484 .fields = ExceptHookArgs_fields,
1485 .n_in_sequence = 4
1486 };
1487
1488
1489 static PyObject *
thread_excepthook(PyObject * module,PyObject * args)1490 thread_excepthook(PyObject *module, PyObject *args)
1491 {
1492 thread_module_state *state = get_thread_state(module);
1493
1494 if (!Py_IS_TYPE(args, state->excepthook_type)) {
1495 PyErr_SetString(PyExc_TypeError,
1496 "_thread.excepthook argument type "
1497 "must be ExceptHookArgs");
1498 return NULL;
1499 }
1500
1501 /* Borrowed reference */
1502 PyObject *exc_type = PyStructSequence_GET_ITEM(args, 0);
1503 if (exc_type == PyExc_SystemExit) {
1504 /* silently ignore SystemExit */
1505 Py_RETURN_NONE;
1506 }
1507
1508 /* Borrowed references */
1509 PyObject *exc_value = PyStructSequence_GET_ITEM(args, 1);
1510 PyObject *exc_tb = PyStructSequence_GET_ITEM(args, 2);
1511 PyObject *thread = PyStructSequence_GET_ITEM(args, 3);
1512
1513 PyThreadState *tstate = _PyThreadState_GET();
1514 PyObject *file = _PySys_GetAttr(tstate, &_Py_ID(stderr));
1515 if (file == NULL || file == Py_None) {
1516 if (thread == Py_None) {
1517 /* do nothing if sys.stderr is None and thread is None */
1518 Py_RETURN_NONE;
1519 }
1520
1521 file = PyObject_GetAttrString(thread, "_stderr");
1522 if (file == NULL) {
1523 return NULL;
1524 }
1525 if (file == Py_None) {
1526 Py_DECREF(file);
1527 /* do nothing if sys.stderr is None and sys.stderr was None
1528 when the thread was created */
1529 Py_RETURN_NONE;
1530 }
1531 }
1532 else {
1533 Py_INCREF(file);
1534 }
1535
1536 int res = thread_excepthook_file(file, exc_type, exc_value, exc_tb,
1537 thread);
1538 Py_DECREF(file);
1539 if (res < 0) {
1540 return NULL;
1541 }
1542
1543 Py_RETURN_NONE;
1544 }
1545
1546 PyDoc_STRVAR(excepthook_doc,
1547 "excepthook(exc_type, exc_value, exc_traceback, thread)\n\
1548 \n\
1549 Handle uncaught Thread.run() exception.");
1550
1551 static PyMethodDef thread_methods[] = {
1552 {"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread,
1553 METH_VARARGS, start_new_doc},
1554 {"start_new", (PyCFunction)thread_PyThread_start_new_thread,
1555 METH_VARARGS, start_new_doc},
1556 {"allocate_lock", thread_PyThread_allocate_lock,
1557 METH_NOARGS, allocate_doc},
1558 {"allocate", thread_PyThread_allocate_lock,
1559 METH_NOARGS, allocate_doc},
1560 {"exit_thread", thread_PyThread_exit_thread,
1561 METH_NOARGS, exit_doc},
1562 {"exit", thread_PyThread_exit_thread,
1563 METH_NOARGS, exit_doc},
1564 {"interrupt_main", (PyCFunction)thread_PyThread_interrupt_main,
1565 METH_VARARGS, interrupt_doc},
1566 {"get_ident", thread_get_ident,
1567 METH_NOARGS, get_ident_doc},
1568 #ifdef PY_HAVE_THREAD_NATIVE_ID
1569 {"get_native_id", thread_get_native_id,
1570 METH_NOARGS, get_native_id_doc},
1571 #endif
1572 {"_count", thread__count,
1573 METH_NOARGS, _count_doc},
1574 {"stack_size", (PyCFunction)thread_stack_size,
1575 METH_VARARGS, stack_size_doc},
1576 {"_set_sentinel", thread__set_sentinel,
1577 METH_NOARGS, _set_sentinel_doc},
1578 {"_excepthook", thread_excepthook,
1579 METH_O, excepthook_doc},
1580 {NULL, NULL} /* sentinel */
1581 };
1582
1583
1584 /* Initialization function */
1585
1586 static int
thread_module_exec(PyObject * module)1587 thread_module_exec(PyObject *module)
1588 {
1589 thread_module_state *state = get_thread_state(module);
1590 PyObject *d = PyModule_GetDict(module);
1591
1592 // Initialize the C thread library
1593 PyThread_init_thread();
1594
1595 // Lock
1596 state->lock_type = (PyTypeObject *)PyType_FromSpec(&lock_type_spec);
1597 if (state->lock_type == NULL) {
1598 return -1;
1599 }
1600 if (PyDict_SetItemString(d, "LockType", (PyObject *)state->lock_type) < 0) {
1601 return -1;
1602 }
1603
1604 // RLock
1605 PyTypeObject *rlock_type = (PyTypeObject *)PyType_FromSpec(&rlock_type_spec);
1606 if (rlock_type == NULL) {
1607 return -1;
1608 }
1609 if (PyModule_AddType(module, rlock_type) < 0) {
1610 Py_DECREF(rlock_type);
1611 return -1;
1612 }
1613 Py_DECREF(rlock_type);
1614
1615 // Local dummy
1616 state->local_dummy_type = (PyTypeObject *)PyType_FromSpec(&local_dummy_type_spec);
1617 if (state->local_dummy_type == NULL) {
1618 return -1;
1619 }
1620
1621 // Local
1622 state->local_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, &local_type_spec, NULL);
1623 if (state->local_type == NULL) {
1624 return -1;
1625 }
1626 if (PyModule_AddType(module, state->local_type) < 0) {
1627 return -1;
1628 }
1629
1630 // Add module attributes
1631 if (PyDict_SetItemString(d, "error", ThreadError) < 0) {
1632 return -1;
1633 }
1634
1635 // _ExceptHookArgs type
1636 state->excepthook_type = PyStructSequence_NewType(&ExceptHookArgs_desc);
1637 if (state->excepthook_type == NULL) {
1638 return -1;
1639 }
1640 if (PyModule_AddType(module, state->excepthook_type) < 0) {
1641 return -1;
1642 }
1643
1644 // TIMEOUT_MAX
1645 double timeout_max = (double)PY_TIMEOUT_MAX * 1e-6;
1646 double time_max = _PyTime_AsSecondsDouble(_PyTime_MAX);
1647 timeout_max = Py_MIN(timeout_max, time_max);
1648 // Round towards minus infinity
1649 timeout_max = floor(timeout_max);
1650
1651 if (PyModule_AddObject(module, "TIMEOUT_MAX",
1652 PyFloat_FromDouble(timeout_max)) < 0) {
1653 return -1;
1654 }
1655
1656 return 0;
1657 }
1658
1659
1660 static int
thread_module_traverse(PyObject * module,visitproc visit,void * arg)1661 thread_module_traverse(PyObject *module, visitproc visit, void *arg)
1662 {
1663 thread_module_state *state = get_thread_state(module);
1664 Py_VISIT(state->excepthook_type);
1665 Py_VISIT(state->lock_type);
1666 Py_VISIT(state->local_type);
1667 Py_VISIT(state->local_dummy_type);
1668 return 0;
1669 }
1670
1671 static int
thread_module_clear(PyObject * module)1672 thread_module_clear(PyObject *module)
1673 {
1674 thread_module_state *state = get_thread_state(module);
1675 Py_CLEAR(state->excepthook_type);
1676 Py_CLEAR(state->lock_type);
1677 Py_CLEAR(state->local_type);
1678 Py_CLEAR(state->local_dummy_type);
1679 return 0;
1680 }
1681
1682 static void
thread_module_free(void * module)1683 thread_module_free(void *module)
1684 {
1685 thread_module_clear((PyObject *)module);
1686 }
1687
1688
1689
1690 PyDoc_STRVAR(thread_doc,
1691 "This module provides primitive operations to write multi-threaded programs.\n\
1692 The 'threading' module provides a more convenient interface.");
1693
1694 static PyModuleDef_Slot thread_module_slots[] = {
1695 {Py_mod_exec, thread_module_exec},
1696 {0, NULL}
1697 };
1698
1699 static struct PyModuleDef thread_module = {
1700 PyModuleDef_HEAD_INIT,
1701 .m_name = "_thread",
1702 .m_doc = thread_doc,
1703 .m_size = sizeof(thread_module_state),
1704 .m_methods = thread_methods,
1705 .m_traverse = thread_module_traverse,
1706 .m_clear = thread_module_clear,
1707 .m_free = thread_module_free,
1708 .m_slots = thread_module_slots,
1709 };
1710
1711 PyMODINIT_FUNC
PyInit__thread(void)1712 PyInit__thread(void)
1713 {
1714 return PyModuleDef_Init(&thread_module);
1715 }
1716