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*
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
51 lock_traverse(lockobject *self, visitproc visit, void *arg)
52 {
53 Py_VISIT(Py_TYPE(self));
54 return 0;
55 }
56
57 static void
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
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
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 *
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 *
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 *
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 *
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 *
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
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
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 *
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 *
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 *
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 *
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 static PyObject *
489 rlock_recursion_count(rlockobject *self, PyObject *Py_UNUSED(ignored))
490 {
491 unsigned long tid = PyThread_get_thread_ident();
492 return PyLong_FromUnsignedLong(
493 self->rlock_owner == tid ? self->rlock_count : 0UL);
494 }
495
496 PyDoc_STRVAR(rlock_recursion_count_doc,
497 "_recursion_count() -> int\n\
498 \n\
499 For internal use by reentrancy checks.");
500
501 static PyObject *
502 rlock_is_owned(rlockobject *self, PyObject *Py_UNUSED(ignored))
503 {
504 unsigned long tid = PyThread_get_thread_ident();
505
506 if (self->rlock_count > 0 && self->rlock_owner == tid) {
507 Py_RETURN_TRUE;
508 }
509 Py_RETURN_FALSE;
510 }
511
512 PyDoc_STRVAR(rlock_is_owned_doc,
513 "_is_owned() -> bool\n\
514 \n\
515 For internal use by `threading.Condition`.");
516
517 static PyObject *
518 rlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
519 {
520 rlockobject *self = (rlockobject *) type->tp_alloc(type, 0);
521 if (self == NULL) {
522 return NULL;
523 }
524 self->in_weakreflist = NULL;
525 self->rlock_owner = 0;
526 self->rlock_count = 0;
527
528 self->rlock_lock = PyThread_allocate_lock();
529 if (self->rlock_lock == NULL) {
530 Py_DECREF(self);
531 PyErr_SetString(ThreadError, "can't allocate lock");
532 return NULL;
533 }
534 return (PyObject *) self;
535 }
536
537 static PyObject *
538 rlock_repr(rlockobject *self)
539 {
540 return PyUnicode_FromFormat("<%s %s object owner=%ld count=%lu at %p>",
541 self->rlock_count ? "locked" : "unlocked",
542 Py_TYPE(self)->tp_name, self->rlock_owner,
543 self->rlock_count, self);
544 }
545
546
547 #ifdef HAVE_FORK
548 static PyObject *
549 rlock__at_fork_reinit(rlockobject *self, PyObject *Py_UNUSED(args))
550 {
551 if (_PyThread_at_fork_reinit(&self->rlock_lock) < 0) {
552 PyErr_SetString(ThreadError, "failed to reinitialize lock at fork");
553 return NULL;
554 }
555
556 self->rlock_owner = 0;
557 self->rlock_count = 0;
558
559 Py_RETURN_NONE;
560 }
561 #endif /* HAVE_FORK */
562
563
564 static PyMethodDef rlock_methods[] = {
565 {"acquire", _PyCFunction_CAST(rlock_acquire),
566 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
567 {"release", (PyCFunction)rlock_release,
568 METH_NOARGS, rlock_release_doc},
569 {"_is_owned", (PyCFunction)rlock_is_owned,
570 METH_NOARGS, rlock_is_owned_doc},
571 {"_acquire_restore", (PyCFunction)rlock_acquire_restore,
572 METH_VARARGS, rlock_acquire_restore_doc},
573 {"_release_save", (PyCFunction)rlock_release_save,
574 METH_NOARGS, rlock_release_save_doc},
575 {"_recursion_count", (PyCFunction)rlock_recursion_count,
576 METH_NOARGS, rlock_recursion_count_doc},
577 {"__enter__", _PyCFunction_CAST(rlock_acquire),
578 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
579 {"__exit__", (PyCFunction)rlock_release,
580 METH_VARARGS, rlock_release_doc},
581 #ifdef HAVE_FORK
582 {"_at_fork_reinit", (PyCFunction)rlock__at_fork_reinit,
583 METH_NOARGS, NULL},
584 #endif
585 {NULL, NULL} /* sentinel */
586 };
587
588
589 static PyMemberDef rlock_type_members[] = {
590 {"__weaklistoffset__", T_PYSSIZET, offsetof(rlockobject, in_weakreflist), READONLY},
591 {NULL},
592 };
593
594 static PyType_Slot rlock_type_slots[] = {
595 {Py_tp_dealloc, (destructor)rlock_dealloc},
596 {Py_tp_repr, (reprfunc)rlock_repr},
597 {Py_tp_methods, rlock_methods},
598 {Py_tp_alloc, PyType_GenericAlloc},
599 {Py_tp_new, rlock_new},
600 {Py_tp_members, rlock_type_members},
601 {Py_tp_traverse, rlock_traverse},
602 {0, 0},
603 };
604
605 static PyType_Spec rlock_type_spec = {
606 .name = "_thread.RLock",
607 .basicsize = sizeof(rlockobject),
608 .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
609 Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE),
610 .slots = rlock_type_slots,
611 };
612
613 static lockobject *
614 newlockobject(PyObject *module)
615 {
616 thread_module_state *state = get_thread_state(module);
617
618 PyTypeObject *type = state->lock_type;
619 lockobject *self = (lockobject *)type->tp_alloc(type, 0);
620 if (self == NULL) {
621 return NULL;
622 }
623
624 self->lock_lock = PyThread_allocate_lock();
625 self->locked = 0;
626 self->in_weakreflist = NULL;
627
628 if (self->lock_lock == NULL) {
629 Py_DECREF(self);
630 PyErr_SetString(ThreadError, "can't allocate lock");
631 return NULL;
632 }
633 return self;
634 }
635
636 /* Thread-local objects */
637
638 /* Quick overview:
639
640 We need to be able to reclaim reference cycles as soon as possible
641 (both when a thread is being terminated, or a thread-local object
642 becomes unreachable from user data). Constraints:
643 - it must not be possible for thread-state dicts to be involved in
644 reference cycles (otherwise the cyclic GC will refuse to consider
645 objects referenced from a reachable thread-state dict, even though
646 local_dealloc would clear them)
647 - the death of a thread-state dict must still imply destruction of the
648 corresponding local dicts in all thread-local objects.
649
650 Our implementation uses small "localdummy" objects in order to break
651 the reference chain. These trivial objects are hashable (using the
652 default scheme of identity hashing) and weakrefable.
653 Each thread-state holds a separate localdummy for each local object
654 (as a /strong reference/),
655 and each thread-local object holds a dict mapping /weak references/
656 of localdummies to local dicts.
657
658 Therefore:
659 - only the thread-state dict holds a strong reference to the dummies
660 - only the thread-local object holds a strong reference to the local dicts
661 - only outside objects (application- or library-level) hold strong
662 references to the thread-local objects
663 - as soon as a thread-state dict is destroyed, the weakref callbacks of all
664 dummies attached to that thread are called, and destroy the corresponding
665 local dicts from thread-local objects
666 - as soon as a thread-local object is destroyed, its local dicts are
667 destroyed and its dummies are manually removed from all thread states
668 - the GC can do its work correctly when a thread-local object is dangling,
669 without any interference from the thread-state dicts
670
671 As an additional optimization, each localdummy holds a borrowed reference
672 to the corresponding localdict. This borrowed reference is only used
673 by the thread-local object which has created the localdummy, which should
674 guarantee that the localdict still exists when accessed.
675 */
676
677 typedef struct {
678 PyObject_HEAD
679 PyObject *localdict; /* Borrowed reference! */
680 PyObject *weakreflist; /* List of weak references to self */
681 } localdummyobject;
682
683 static void
684 localdummy_dealloc(localdummyobject *self)
685 {
686 if (self->weakreflist != NULL)
687 PyObject_ClearWeakRefs((PyObject *) self);
688 PyTypeObject *tp = Py_TYPE(self);
689 tp->tp_free((PyObject*)self);
690 Py_DECREF(tp);
691 }
692
693 static PyMemberDef local_dummy_type_members[] = {
694 {"__weaklistoffset__", T_PYSSIZET, offsetof(localdummyobject, weakreflist), READONLY},
695 {NULL},
696 };
697
698 static PyType_Slot local_dummy_type_slots[] = {
699 {Py_tp_dealloc, (destructor)localdummy_dealloc},
700 {Py_tp_doc, "Thread-local dummy"},
701 {Py_tp_members, local_dummy_type_members},
702 {0, 0}
703 };
704
705 static PyType_Spec local_dummy_type_spec = {
706 .name = "_thread._localdummy",
707 .basicsize = sizeof(localdummyobject),
708 .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION |
709 Py_TPFLAGS_IMMUTABLETYPE),
710 .slots = local_dummy_type_slots,
711 };
712
713
714 typedef struct {
715 PyObject_HEAD
716 PyObject *key;
717 PyObject *args;
718 PyObject *kw;
719 PyObject *weakreflist; /* List of weak references to self */
720 /* A {localdummy weakref -> localdict} dict */
721 PyObject *dummies;
722 /* The callback for weakrefs to localdummies */
723 PyObject *wr_callback;
724 } localobject;
725
726 /* Forward declaration */
727 static PyObject *_ldict(localobject *self, thread_module_state *state);
728 static PyObject *_localdummy_destroyed(PyObject *meth_self, PyObject *dummyweakref);
729
730 /* Create and register the dummy for the current thread.
731 Returns a borrowed reference of the corresponding local dict */
732 static PyObject *
733 _local_create_dummy(localobject *self, thread_module_state *state)
734 {
735 PyObject *ldict = NULL, *wr = NULL;
736 localdummyobject *dummy = NULL;
737 PyTypeObject *type = state->local_dummy_type;
738
739 PyObject *tdict = PyThreadState_GetDict();
740 if (tdict == NULL) {
741 PyErr_SetString(PyExc_SystemError,
742 "Couldn't get thread-state dictionary");
743 goto err;
744 }
745
746 ldict = PyDict_New();
747 if (ldict == NULL) {
748 goto err;
749 }
750 dummy = (localdummyobject *) type->tp_alloc(type, 0);
751 if (dummy == NULL) {
752 goto err;
753 }
754 dummy->localdict = ldict;
755 wr = PyWeakref_NewRef((PyObject *) dummy, self->wr_callback);
756 if (wr == NULL) {
757 goto err;
758 }
759
760 /* As a side-effect, this will cache the weakref's hash before the
761 dummy gets deleted */
762 int r = PyDict_SetItem(self->dummies, wr, ldict);
763 if (r < 0) {
764 goto err;
765 }
766 Py_CLEAR(wr);
767 r = PyDict_SetItem(tdict, self->key, (PyObject *) dummy);
768 if (r < 0) {
769 goto err;
770 }
771 Py_CLEAR(dummy);
772
773 Py_DECREF(ldict);
774 return ldict;
775
776 err:
777 Py_XDECREF(ldict);
778 Py_XDECREF(wr);
779 Py_XDECREF(dummy);
780 return NULL;
781 }
782
783 static PyObject *
784 local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
785 {
786 static PyMethodDef wr_callback_def = {
787 "_localdummy_destroyed", (PyCFunction) _localdummy_destroyed, METH_O
788 };
789
790 if (type->tp_init == PyBaseObject_Type.tp_init) {
791 int rc = 0;
792 if (args != NULL)
793 rc = PyObject_IsTrue(args);
794 if (rc == 0 && kw != NULL)
795 rc = PyObject_IsTrue(kw);
796 if (rc != 0) {
797 if (rc > 0) {
798 PyErr_SetString(PyExc_TypeError,
799 "Initialization arguments are not supported");
800 }
801 return NULL;
802 }
803 }
804
805 PyObject *module = PyType_GetModuleByDef(type, &thread_module);
806 thread_module_state *state = get_thread_state(module);
807
808 localobject *self = (localobject *)type->tp_alloc(type, 0);
809 if (self == NULL) {
810 return NULL;
811 }
812
813 self->args = Py_XNewRef(args);
814 self->kw = Py_XNewRef(kw);
815 self->key = PyUnicode_FromFormat("thread.local.%p", self);
816 if (self->key == NULL) {
817 goto err;
818 }
819
820 self->dummies = PyDict_New();
821 if (self->dummies == NULL) {
822 goto err;
823 }
824
825 /* We use a weak reference to self in the callback closure
826 in order to avoid spurious reference cycles */
827 PyObject *wr = PyWeakref_NewRef((PyObject *) self, NULL);
828 if (wr == NULL) {
829 goto err;
830 }
831 self->wr_callback = PyCFunction_NewEx(&wr_callback_def, wr, NULL);
832 Py_DECREF(wr);
833 if (self->wr_callback == NULL) {
834 goto err;
835 }
836 if (_local_create_dummy(self, state) == NULL) {
837 goto err;
838 }
839 return (PyObject *)self;
840
841 err:
842 Py_DECREF(self);
843 return NULL;
844 }
845
846 static int
847 local_traverse(localobject *self, visitproc visit, void *arg)
848 {
849 Py_VISIT(Py_TYPE(self));
850 Py_VISIT(self->args);
851 Py_VISIT(self->kw);
852 Py_VISIT(self->dummies);
853 return 0;
854 }
855
856 #define HEAD_LOCK(runtime) \
857 PyThread_acquire_lock((runtime)->interpreters.mutex, WAIT_LOCK)
858 #define HEAD_UNLOCK(runtime) \
859 PyThread_release_lock((runtime)->interpreters.mutex)
860
861 static int
862 local_clear(localobject *self)
863 {
864 Py_CLEAR(self->args);
865 Py_CLEAR(self->kw);
866 Py_CLEAR(self->dummies);
867 Py_CLEAR(self->wr_callback);
868 /* Remove all strong references to dummies from the thread states */
869 if (self->key) {
870 PyInterpreterState *interp = _PyInterpreterState_GET();
871 _PyRuntimeState *runtime = &_PyRuntime;
872 HEAD_LOCK(runtime);
873 PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
874 HEAD_UNLOCK(runtime);
875 while (tstate) {
876 if (tstate->dict) {
877 PyObject *v = _PyDict_Pop(tstate->dict, self->key, Py_None);
878 if (v != NULL) {
879 Py_DECREF(v);
880 }
881 else {
882 PyErr_Clear();
883 }
884 }
885 HEAD_LOCK(runtime);
886 tstate = PyThreadState_Next(tstate);
887 HEAD_UNLOCK(runtime);
888 }
889 }
890 return 0;
891 }
892
893 static void
894 local_dealloc(localobject *self)
895 {
896 /* Weakrefs must be invalidated right now, otherwise they can be used
897 from code called below, which is very dangerous since Py_REFCNT(self) == 0 */
898 if (self->weakreflist != NULL) {
899 PyObject_ClearWeakRefs((PyObject *) self);
900 }
901
902 PyObject_GC_UnTrack(self);
903
904 local_clear(self);
905 Py_XDECREF(self->key);
906
907 PyTypeObject *tp = Py_TYPE(self);
908 tp->tp_free((PyObject*)self);
909 Py_DECREF(tp);
910 }
911
912 /* Returns a borrowed reference to the local dict, creating it if necessary */
913 static PyObject *
914 _ldict(localobject *self, thread_module_state *state)
915 {
916 PyObject *tdict = PyThreadState_GetDict();
917 if (tdict == NULL) {
918 PyErr_SetString(PyExc_SystemError,
919 "Couldn't get thread-state dictionary");
920 return NULL;
921 }
922
923 PyObject *ldict;
924 PyObject *dummy = PyDict_GetItemWithError(tdict, self->key);
925 if (dummy == NULL) {
926 if (PyErr_Occurred()) {
927 return NULL;
928 }
929 ldict = _local_create_dummy(self, state);
930 if (ldict == NULL)
931 return NULL;
932
933 if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init &&
934 Py_TYPE(self)->tp_init((PyObject*)self,
935 self->args, self->kw) < 0) {
936 /* we need to get rid of ldict from thread so
937 we create a new one the next time we do an attr
938 access */
939 PyDict_DelItem(tdict, self->key);
940 return NULL;
941 }
942 }
943 else {
944 assert(Py_IS_TYPE(dummy, state->local_dummy_type));
945 ldict = ((localdummyobject *) dummy)->localdict;
946 }
947
948 return ldict;
949 }
950
951 static int
952 local_setattro(localobject *self, PyObject *name, PyObject *v)
953 {
954 PyObject *module = PyType_GetModuleByDef(Py_TYPE(self), &thread_module);
955 thread_module_state *state = get_thread_state(module);
956
957 PyObject *ldict = _ldict(self, state);
958 if (ldict == NULL) {
959 return -1;
960 }
961
962 int r = PyObject_RichCompareBool(name, &_Py_ID(__dict__), Py_EQ);
963 if (r == -1) {
964 return -1;
965 }
966 if (r == 1) {
967 PyErr_Format(PyExc_AttributeError,
968 "'%.50s' object attribute '%U' is read-only",
969 Py_TYPE(self)->tp_name, name);
970 return -1;
971 }
972
973 return _PyObject_GenericSetAttrWithDict((PyObject *)self, name, v, ldict);
974 }
975
976 static PyObject *local_getattro(localobject *, PyObject *);
977
978 static PyMemberDef local_type_members[] = {
979 {"__weaklistoffset__", T_PYSSIZET, offsetof(localobject, weakreflist), READONLY},
980 {NULL},
981 };
982
983 static PyType_Slot local_type_slots[] = {
984 {Py_tp_dealloc, (destructor)local_dealloc},
985 {Py_tp_getattro, (getattrofunc)local_getattro},
986 {Py_tp_setattro, (setattrofunc)local_setattro},
987 {Py_tp_doc, "Thread-local data"},
988 {Py_tp_traverse, (traverseproc)local_traverse},
989 {Py_tp_clear, (inquiry)local_clear},
990 {Py_tp_new, local_new},
991 {Py_tp_members, local_type_members},
992 {0, 0}
993 };
994
995 static PyType_Spec local_type_spec = {
996 .name = "_thread._local",
997 .basicsize = sizeof(localobject),
998 .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
999 Py_TPFLAGS_IMMUTABLETYPE),
1000 .slots = local_type_slots,
1001 };
1002
1003 static PyObject *
1004 local_getattro(localobject *self, PyObject *name)
1005 {
1006 PyObject *module = PyType_GetModuleByDef(Py_TYPE(self), &thread_module);
1007 thread_module_state *state = get_thread_state(module);
1008
1009 PyObject *ldict = _ldict(self, state);
1010 if (ldict == NULL)
1011 return NULL;
1012
1013 int r = PyObject_RichCompareBool(name, &_Py_ID(__dict__), Py_EQ);
1014 if (r == 1) {
1015 return Py_NewRef(ldict);
1016 }
1017 if (r == -1) {
1018 return NULL;
1019 }
1020
1021 if (!Py_IS_TYPE(self, state->local_type)) {
1022 /* use generic lookup for subtypes */
1023 return _PyObject_GenericGetAttrWithDict((PyObject *)self, name,
1024 ldict, 0);
1025 }
1026
1027 /* Optimization: just look in dict ourselves */
1028 PyObject *value = PyDict_GetItemWithError(ldict, name);
1029 if (value != NULL) {
1030 return Py_NewRef(value);
1031 }
1032 if (PyErr_Occurred()) {
1033 return NULL;
1034 }
1035
1036 /* Fall back on generic to get __class__ and __dict__ */
1037 return _PyObject_GenericGetAttrWithDict(
1038 (PyObject *)self, name, ldict, 0);
1039 }
1040
1041 /* Called when a dummy is destroyed. */
1042 static PyObject *
1043 _localdummy_destroyed(PyObject *localweakref, PyObject *dummyweakref)
1044 {
1045 assert(PyWeakref_CheckRef(localweakref));
1046 PyObject *obj = PyWeakref_GET_OBJECT(localweakref);
1047 if (obj == Py_None) {
1048 Py_RETURN_NONE;
1049 }
1050
1051 /* If the thread-local object is still alive and not being cleared,
1052 remove the corresponding local dict */
1053 localobject *self = (localobject *)Py_NewRef(obj);
1054 if (self->dummies != NULL) {
1055 PyObject *ldict;
1056 ldict = PyDict_GetItemWithError(self->dummies, dummyweakref);
1057 if (ldict != NULL) {
1058 PyDict_DelItem(self->dummies, dummyweakref);
1059 }
1060 if (PyErr_Occurred())
1061 PyErr_WriteUnraisable(obj);
1062 }
1063 Py_DECREF(obj);
1064 Py_RETURN_NONE;
1065 }
1066
1067 /* Module functions */
1068
1069 struct bootstate {
1070 PyThreadState *tstate;
1071 PyObject *func;
1072 PyObject *args;
1073 PyObject *kwargs;
1074 };
1075
1076
1077 static void
1078 thread_bootstate_free(struct bootstate *boot, int decref)
1079 {
1080 if (decref) {
1081 Py_DECREF(boot->func);
1082 Py_DECREF(boot->args);
1083 Py_XDECREF(boot->kwargs);
1084 }
1085 PyMem_RawFree(boot);
1086 }
1087
1088
1089 static void
1090 thread_run(void *boot_raw)
1091 {
1092 struct bootstate *boot = (struct bootstate *) boot_raw;
1093 PyThreadState *tstate = boot->tstate;
1094
1095 // gh-108987: If _thread.start_new_thread() is called before or while
1096 // Python is being finalized, thread_run() can called *after*.
1097 // _PyRuntimeState_SetFinalizing() is called. At this point, all Python
1098 // threads must exit, except of the thread calling Py_Finalize() whch holds
1099 // the GIL and must not exit.
1100 //
1101 // At this stage, tstate can be a dangling pointer (point to freed memory),
1102 // it's ok to call _PyThreadState_MustExit() with a dangling pointer.
1103 if (_PyThreadState_MustExit(tstate)) {
1104 // Don't call PyThreadState_Clear() nor _PyThreadState_DeleteCurrent().
1105 // These functions are called on tstate indirectly by Py_Finalize()
1106 // which calls _PyInterpreterState_Clear().
1107 //
1108 // Py_DECREF() cannot be called because the GIL is not held: leak
1109 // references on purpose. Python is being finalized anyway.
1110 thread_bootstate_free(boot, 0);
1111 goto exit;
1112 }
1113
1114 tstate->thread_id = PyThread_get_thread_ident();
1115 #ifdef PY_HAVE_THREAD_NATIVE_ID
1116 tstate->native_thread_id = PyThread_get_thread_native_id();
1117 #else
1118 tstate->native_thread_id = 0;
1119 #endif
1120 _PyThreadState_SetCurrent(tstate);
1121 PyEval_AcquireThread(tstate);
1122 tstate->interp->threads.count++;
1123
1124 PyObject *res = PyObject_Call(boot->func, boot->args, boot->kwargs);
1125 if (res == NULL) {
1126 if (PyErr_ExceptionMatches(PyExc_SystemExit))
1127 /* SystemExit is ignored silently */
1128 PyErr_Clear();
1129 else {
1130 _PyErr_WriteUnraisableMsg("in thread started by", boot->func);
1131 }
1132 }
1133 else {
1134 Py_DECREF(res);
1135 }
1136
1137 thread_bootstate_free(boot, 1);
1138
1139 tstate->interp->threads.count--;
1140 PyThreadState_Clear(tstate);
1141 _PyThreadState_DeleteCurrent(tstate);
1142
1143 exit:
1144 // bpo-44434: Don't call explicitly PyThread_exit_thread(). On Linux with
1145 // the glibc, pthread_exit() can abort the whole process if dlopen() fails
1146 // to open the libgcc_s.so library (ex: EMFILE error).
1147 return;
1148 }
1149
1150 static PyObject *
1151 thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
1152 {
1153 PyObject *func, *args, *kwargs = NULL;
1154
1155 if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3,
1156 &func, &args, &kwargs))
1157 return NULL;
1158 if (!PyCallable_Check(func)) {
1159 PyErr_SetString(PyExc_TypeError,
1160 "first arg must be callable");
1161 return NULL;
1162 }
1163 if (!PyTuple_Check(args)) {
1164 PyErr_SetString(PyExc_TypeError,
1165 "2nd arg must be a tuple");
1166 return NULL;
1167 }
1168 if (kwargs != NULL && !PyDict_Check(kwargs)) {
1169 PyErr_SetString(PyExc_TypeError,
1170 "optional 3rd arg must be a dictionary");
1171 return NULL;
1172 }
1173
1174 PyInterpreterState *interp = _PyInterpreterState_GET();
1175 if (interp->config._isolated_interpreter) {
1176 PyErr_SetString(PyExc_RuntimeError,
1177 "thread is not supported for isolated subinterpreters");
1178 return NULL;
1179 }
1180
1181 // gh-109795: Use PyMem_RawMalloc() instead of PyMem_Malloc(),
1182 // because it should be possible to call thread_bootstate_free()
1183 // without holding the GIL.
1184 struct bootstate *boot = PyMem_RawMalloc(sizeof(struct bootstate));
1185 if (boot == NULL) {
1186 return PyErr_NoMemory();
1187 }
1188 boot->tstate = _PyThreadState_Prealloc(interp);
1189 if (boot->tstate == NULL) {
1190 PyMem_RawFree(boot);
1191 return PyErr_NoMemory();
1192 }
1193 boot->func = Py_NewRef(func);
1194 boot->args = Py_NewRef(args);
1195 boot->kwargs = Py_XNewRef(kwargs);
1196
1197 unsigned long ident = PyThread_start_new_thread(thread_run, (void*) boot);
1198 if (ident == PYTHREAD_INVALID_THREAD_ID) {
1199 PyErr_SetString(ThreadError, "can't start new thread");
1200 PyThreadState_Clear(boot->tstate);
1201 thread_bootstate_free(boot, 1);
1202 return NULL;
1203 }
1204 return PyLong_FromUnsignedLong(ident);
1205 }
1206
1207 PyDoc_STRVAR(start_new_doc,
1208 "start_new_thread(function, args[, kwargs])\n\
1209 (start_new() is an obsolete synonym)\n\
1210 \n\
1211 Start a new thread and return its identifier. The thread will call the\n\
1212 function with positional arguments from the tuple args and keyword arguments\n\
1213 taken from the optional dictionary kwargs. The thread exits when the\n\
1214 function returns; the return value is ignored. The thread will also exit\n\
1215 when the function raises an unhandled exception; a stack trace will be\n\
1216 printed unless the exception is SystemExit.\n");
1217
1218 static PyObject *
1219 thread_PyThread_exit_thread(PyObject *self, PyObject *Py_UNUSED(ignored))
1220 {
1221 PyErr_SetNone(PyExc_SystemExit);
1222 return NULL;
1223 }
1224
1225 PyDoc_STRVAR(exit_doc,
1226 "exit()\n\
1227 (exit_thread() is an obsolete synonym)\n\
1228 \n\
1229 This is synonymous to ``raise SystemExit''. It will cause the current\n\
1230 thread to exit silently unless the exception is caught.");
1231
1232 static PyObject *
1233 thread_PyThread_interrupt_main(PyObject *self, PyObject *args)
1234 {
1235 int signum = SIGINT;
1236 if (!PyArg_ParseTuple(args, "|i:signum", &signum)) {
1237 return NULL;
1238 }
1239
1240 if (PyErr_SetInterruptEx(signum)) {
1241 PyErr_SetString(PyExc_ValueError, "signal number out of range");
1242 return NULL;
1243 }
1244 Py_RETURN_NONE;
1245 }
1246
1247 PyDoc_STRVAR(interrupt_doc,
1248 "interrupt_main(signum=signal.SIGINT, /)\n\
1249 \n\
1250 Simulate the arrival of the given signal in the main thread,\n\
1251 where the corresponding signal handler will be executed.\n\
1252 If *signum* is omitted, SIGINT is assumed.\n\
1253 A subthread can use this function to interrupt the main thread.\n\
1254 \n\
1255 Note: the default signal handler for SIGINT raises ``KeyboardInterrupt``."
1256 );
1257
1258 static lockobject *newlockobject(PyObject *module);
1259
1260 static PyObject *
1261 thread_PyThread_allocate_lock(PyObject *module, PyObject *Py_UNUSED(ignored))
1262 {
1263 return (PyObject *) newlockobject(module);
1264 }
1265
1266 PyDoc_STRVAR(allocate_doc,
1267 "allocate_lock() -> lock object\n\
1268 (allocate() is an obsolete synonym)\n\
1269 \n\
1270 Create a new lock object. See help(type(threading.Lock())) for\n\
1271 information about locks.");
1272
1273 static PyObject *
1274 thread_get_ident(PyObject *self, PyObject *Py_UNUSED(ignored))
1275 {
1276 unsigned long ident = PyThread_get_thread_ident();
1277 if (ident == PYTHREAD_INVALID_THREAD_ID) {
1278 PyErr_SetString(ThreadError, "no current thread ident");
1279 return NULL;
1280 }
1281 return PyLong_FromUnsignedLong(ident);
1282 }
1283
1284 PyDoc_STRVAR(get_ident_doc,
1285 "get_ident() -> integer\n\
1286 \n\
1287 Return a non-zero integer that uniquely identifies the current thread\n\
1288 amongst other threads that exist simultaneously.\n\
1289 This may be used to identify per-thread resources.\n\
1290 Even though on some platforms threads identities may appear to be\n\
1291 allocated consecutive numbers starting at 1, this behavior should not\n\
1292 be relied upon, and the number should be seen purely as a magic cookie.\n\
1293 A thread's identity may be reused for another thread after it exits.");
1294
1295 #ifdef PY_HAVE_THREAD_NATIVE_ID
1296 static PyObject *
1297 thread_get_native_id(PyObject *self, PyObject *Py_UNUSED(ignored))
1298 {
1299 unsigned long native_id = PyThread_get_thread_native_id();
1300 return PyLong_FromUnsignedLong(native_id);
1301 }
1302
1303 PyDoc_STRVAR(get_native_id_doc,
1304 "get_native_id() -> integer\n\
1305 \n\
1306 Return a non-negative integer identifying the thread as reported\n\
1307 by the OS (kernel). This may be used to uniquely identify a\n\
1308 particular thread within a system.");
1309 #endif
1310
1311 static PyObject *
1312 thread__count(PyObject *self, PyObject *Py_UNUSED(ignored))
1313 {
1314 PyInterpreterState *interp = _PyInterpreterState_GET();
1315 return PyLong_FromLong(interp->threads.count);
1316 }
1317
1318 PyDoc_STRVAR(_count_doc,
1319 "_count() -> integer\n\
1320 \n\
1321 \
1322 Return the number of currently running Python threads, excluding\n\
1323 the main thread. The returned number comprises all threads created\n\
1324 through `start_new_thread()` as well as `threading.Thread`, and not\n\
1325 yet finished.\n\
1326 \n\
1327 This function is meant for internal and specialized purposes only.\n\
1328 In most applications `threading.enumerate()` should be used instead.");
1329
1330 static void
1331 release_sentinel(void *wr_raw)
1332 {
1333 PyObject *wr = _PyObject_CAST(wr_raw);
1334 /* Tricky: this function is called when the current thread state
1335 is being deleted. Therefore, only simple C code can safely
1336 execute here. */
1337 PyObject *obj = PyWeakref_GET_OBJECT(wr);
1338 lockobject *lock;
1339 if (obj != Py_None) {
1340 lock = (lockobject *) obj;
1341 if (lock->locked) {
1342 PyThread_release_lock(lock->lock_lock);
1343 lock->locked = 0;
1344 }
1345 }
1346 /* Deallocating a weakref with a NULL callback only calls
1347 PyObject_GC_Del(), which can't call any Python code. */
1348 Py_DECREF(wr);
1349 }
1350
1351 static PyObject *
1352 thread__set_sentinel(PyObject *module, PyObject *Py_UNUSED(ignored))
1353 {
1354 PyObject *wr;
1355 PyThreadState *tstate = _PyThreadState_GET();
1356 lockobject *lock;
1357
1358 if (tstate->on_delete_data != NULL) {
1359 /* We must support the re-creation of the lock from a
1360 fork()ed child. */
1361 assert(tstate->on_delete == &release_sentinel);
1362 wr = (PyObject *) tstate->on_delete_data;
1363 tstate->on_delete = NULL;
1364 tstate->on_delete_data = NULL;
1365 Py_DECREF(wr);
1366 }
1367 lock = newlockobject(module);
1368 if (lock == NULL)
1369 return NULL;
1370 /* The lock is owned by whoever called _set_sentinel(), but the weakref
1371 hangs to the thread state. */
1372 wr = PyWeakref_NewRef((PyObject *) lock, NULL);
1373 if (wr == NULL) {
1374 Py_DECREF(lock);
1375 return NULL;
1376 }
1377 tstate->on_delete_data = (void *) wr;
1378 tstate->on_delete = &release_sentinel;
1379 return (PyObject *) lock;
1380 }
1381
1382 PyDoc_STRVAR(_set_sentinel_doc,
1383 "_set_sentinel() -> lock\n\
1384 \n\
1385 Set a sentinel lock that will be released when the current thread\n\
1386 state is finalized (after it is untied from the interpreter).\n\
1387 \n\
1388 This is a private API for the threading module.");
1389
1390 static PyObject *
1391 thread_stack_size(PyObject *self, PyObject *args)
1392 {
1393 size_t old_size;
1394 Py_ssize_t new_size = 0;
1395 int rc;
1396
1397 if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size))
1398 return NULL;
1399
1400 if (new_size < 0) {
1401 PyErr_SetString(PyExc_ValueError,
1402 "size must be 0 or a positive value");
1403 return NULL;
1404 }
1405
1406 old_size = PyThread_get_stacksize();
1407
1408 rc = PyThread_set_stacksize((size_t) new_size);
1409 if (rc == -1) {
1410 PyErr_Format(PyExc_ValueError,
1411 "size not valid: %zd bytes",
1412 new_size);
1413 return NULL;
1414 }
1415 if (rc == -2) {
1416 PyErr_SetString(ThreadError,
1417 "setting stack size not supported");
1418 return NULL;
1419 }
1420
1421 return PyLong_FromSsize_t((Py_ssize_t) old_size);
1422 }
1423
1424 PyDoc_STRVAR(stack_size_doc,
1425 "stack_size([size]) -> size\n\
1426 \n\
1427 Return the thread stack size used when creating new threads. The\n\
1428 optional size argument specifies the stack size (in bytes) to be used\n\
1429 for subsequently created threads, and must be 0 (use platform or\n\
1430 configured default) or a positive integer value of at least 32,768 (32k).\n\
1431 If changing the thread stack size is unsupported, a ThreadError\n\
1432 exception is raised. If the specified size is invalid, a ValueError\n\
1433 exception is raised, and the stack size is unmodified. 32k bytes\n\
1434 currently the minimum supported stack size value to guarantee\n\
1435 sufficient stack space for the interpreter itself.\n\
1436 \n\
1437 Note that some platforms may have particular restrictions on values for\n\
1438 the stack size, such as requiring a minimum stack size larger than 32 KiB or\n\
1439 requiring allocation in multiples of the system memory page size\n\
1440 - platform documentation should be referred to for more information\n\
1441 (4 KiB pages are common; using multiples of 4096 for the stack size is\n\
1442 the suggested approach in the absence of more specific information).");
1443
1444 static int
1445 thread_excepthook_file(PyObject *file, PyObject *exc_type, PyObject *exc_value,
1446 PyObject *exc_traceback, PyObject *thread)
1447 {
1448 /* print(f"Exception in thread {thread.name}:", file=file) */
1449 if (PyFile_WriteString("Exception in thread ", file) < 0) {
1450 return -1;
1451 }
1452
1453 PyObject *name = NULL;
1454 if (thread != Py_None) {
1455 if (_PyObject_LookupAttr(thread, &_Py_ID(name), &name) < 0) {
1456 return -1;
1457 }
1458 }
1459 if (name != NULL) {
1460 if (PyFile_WriteObject(name, file, Py_PRINT_RAW) < 0) {
1461 Py_DECREF(name);
1462 return -1;
1463 }
1464 Py_DECREF(name);
1465 }
1466 else {
1467 unsigned long ident = PyThread_get_thread_ident();
1468 PyObject *str = PyUnicode_FromFormat("%lu", ident);
1469 if (str != NULL) {
1470 if (PyFile_WriteObject(str, file, Py_PRINT_RAW) < 0) {
1471 Py_DECREF(str);
1472 return -1;
1473 }
1474 Py_DECREF(str);
1475 }
1476 else {
1477 PyErr_Clear();
1478
1479 if (PyFile_WriteString("<failed to get thread name>", file) < 0) {
1480 return -1;
1481 }
1482 }
1483 }
1484
1485 if (PyFile_WriteString(":\n", file) < 0) {
1486 return -1;
1487 }
1488
1489 /* Display the traceback */
1490 _PyErr_Display(file, exc_type, exc_value, exc_traceback);
1491
1492 /* Call file.flush() */
1493 PyObject *res = PyObject_CallMethodNoArgs(file, &_Py_ID(flush));
1494 if (!res) {
1495 return -1;
1496 }
1497 Py_DECREF(res);
1498
1499 return 0;
1500 }
1501
1502
1503 PyDoc_STRVAR(ExceptHookArgs__doc__,
1504 "ExceptHookArgs\n\
1505 \n\
1506 Type used to pass arguments to threading.excepthook.");
1507
1508 static PyStructSequence_Field ExceptHookArgs_fields[] = {
1509 {"exc_type", "Exception type"},
1510 {"exc_value", "Exception value"},
1511 {"exc_traceback", "Exception traceback"},
1512 {"thread", "Thread"},
1513 {0}
1514 };
1515
1516 static PyStructSequence_Desc ExceptHookArgs_desc = {
1517 .name = "_thread._ExceptHookArgs",
1518 .doc = ExceptHookArgs__doc__,
1519 .fields = ExceptHookArgs_fields,
1520 .n_in_sequence = 4
1521 };
1522
1523
1524 static PyObject *
1525 thread_excepthook(PyObject *module, PyObject *args)
1526 {
1527 thread_module_state *state = get_thread_state(module);
1528
1529 if (!Py_IS_TYPE(args, state->excepthook_type)) {
1530 PyErr_SetString(PyExc_TypeError,
1531 "_thread.excepthook argument type "
1532 "must be ExceptHookArgs");
1533 return NULL;
1534 }
1535
1536 /* Borrowed reference */
1537 PyObject *exc_type = PyStructSequence_GET_ITEM(args, 0);
1538 if (exc_type == PyExc_SystemExit) {
1539 /* silently ignore SystemExit */
1540 Py_RETURN_NONE;
1541 }
1542
1543 /* Borrowed references */
1544 PyObject *exc_value = PyStructSequence_GET_ITEM(args, 1);
1545 PyObject *exc_tb = PyStructSequence_GET_ITEM(args, 2);
1546 PyObject *thread = PyStructSequence_GET_ITEM(args, 3);
1547
1548 PyThreadState *tstate = _PyThreadState_GET();
1549 PyObject *file = _PySys_GetAttr(tstate, &_Py_ID(stderr));
1550 if (file == NULL || file == Py_None) {
1551 if (thread == Py_None) {
1552 /* do nothing if sys.stderr is None and thread is None */
1553 Py_RETURN_NONE;
1554 }
1555
1556 file = PyObject_GetAttrString(thread, "_stderr");
1557 if (file == NULL) {
1558 return NULL;
1559 }
1560 if (file == Py_None) {
1561 Py_DECREF(file);
1562 /* do nothing if sys.stderr is None and sys.stderr was None
1563 when the thread was created */
1564 Py_RETURN_NONE;
1565 }
1566 }
1567 else {
1568 Py_INCREF(file);
1569 }
1570
1571 int res = thread_excepthook_file(file, exc_type, exc_value, exc_tb,
1572 thread);
1573 Py_DECREF(file);
1574 if (res < 0) {
1575 return NULL;
1576 }
1577
1578 Py_RETURN_NONE;
1579 }
1580
1581 PyDoc_STRVAR(excepthook_doc,
1582 "excepthook(exc_type, exc_value, exc_traceback, thread)\n\
1583 \n\
1584 Handle uncaught Thread.run() exception.");
1585
1586 static PyMethodDef thread_methods[] = {
1587 {"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread,
1588 METH_VARARGS, start_new_doc},
1589 {"start_new", (PyCFunction)thread_PyThread_start_new_thread,
1590 METH_VARARGS, start_new_doc},
1591 {"allocate_lock", thread_PyThread_allocate_lock,
1592 METH_NOARGS, allocate_doc},
1593 {"allocate", thread_PyThread_allocate_lock,
1594 METH_NOARGS, allocate_doc},
1595 {"exit_thread", thread_PyThread_exit_thread,
1596 METH_NOARGS, exit_doc},
1597 {"exit", thread_PyThread_exit_thread,
1598 METH_NOARGS, exit_doc},
1599 {"interrupt_main", (PyCFunction)thread_PyThread_interrupt_main,
1600 METH_VARARGS, interrupt_doc},
1601 {"get_ident", thread_get_ident,
1602 METH_NOARGS, get_ident_doc},
1603 #ifdef PY_HAVE_THREAD_NATIVE_ID
1604 {"get_native_id", thread_get_native_id,
1605 METH_NOARGS, get_native_id_doc},
1606 #endif
1607 {"_count", thread__count,
1608 METH_NOARGS, _count_doc},
1609 {"stack_size", (PyCFunction)thread_stack_size,
1610 METH_VARARGS, stack_size_doc},
1611 {"_set_sentinel", thread__set_sentinel,
1612 METH_NOARGS, _set_sentinel_doc},
1613 {"_excepthook", thread_excepthook,
1614 METH_O, excepthook_doc},
1615 {NULL, NULL} /* sentinel */
1616 };
1617
1618
1619 /* Initialization function */
1620
1621 static int
1622 thread_module_exec(PyObject *module)
1623 {
1624 thread_module_state *state = get_thread_state(module);
1625 PyObject *d = PyModule_GetDict(module);
1626
1627 // Initialize the C thread library
1628 PyThread_init_thread();
1629
1630 // Lock
1631 state->lock_type = (PyTypeObject *)PyType_FromSpec(&lock_type_spec);
1632 if (state->lock_type == NULL) {
1633 return -1;
1634 }
1635 if (PyDict_SetItemString(d, "LockType", (PyObject *)state->lock_type) < 0) {
1636 return -1;
1637 }
1638
1639 // RLock
1640 PyTypeObject *rlock_type = (PyTypeObject *)PyType_FromSpec(&rlock_type_spec);
1641 if (rlock_type == NULL) {
1642 return -1;
1643 }
1644 if (PyModule_AddType(module, rlock_type) < 0) {
1645 Py_DECREF(rlock_type);
1646 return -1;
1647 }
1648 Py_DECREF(rlock_type);
1649
1650 // Local dummy
1651 state->local_dummy_type = (PyTypeObject *)PyType_FromSpec(&local_dummy_type_spec);
1652 if (state->local_dummy_type == NULL) {
1653 return -1;
1654 }
1655
1656 // Local
1657 state->local_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, &local_type_spec, NULL);
1658 if (state->local_type == NULL) {
1659 return -1;
1660 }
1661 if (PyModule_AddType(module, state->local_type) < 0) {
1662 return -1;
1663 }
1664
1665 // Add module attributes
1666 if (PyDict_SetItemString(d, "error", ThreadError) < 0) {
1667 return -1;
1668 }
1669
1670 // _ExceptHookArgs type
1671 state->excepthook_type = PyStructSequence_NewType(&ExceptHookArgs_desc);
1672 if (state->excepthook_type == NULL) {
1673 return -1;
1674 }
1675 if (PyModule_AddType(module, state->excepthook_type) < 0) {
1676 return -1;
1677 }
1678
1679 // TIMEOUT_MAX
1680 double timeout_max = (double)PY_TIMEOUT_MAX * 1e-6;
1681 double time_max = _PyTime_AsSecondsDouble(_PyTime_MAX);
1682 timeout_max = Py_MIN(timeout_max, time_max);
1683 // Round towards minus infinity
1684 timeout_max = floor(timeout_max);
1685
1686 if (_PyModule_Add(module, "TIMEOUT_MAX",
1687 PyFloat_FromDouble(timeout_max)) < 0) {
1688 return -1;
1689 }
1690
1691 return 0;
1692 }
1693
1694
1695 static int
1696 thread_module_traverse(PyObject *module, visitproc visit, void *arg)
1697 {
1698 thread_module_state *state = get_thread_state(module);
1699 Py_VISIT(state->excepthook_type);
1700 Py_VISIT(state->lock_type);
1701 Py_VISIT(state->local_type);
1702 Py_VISIT(state->local_dummy_type);
1703 return 0;
1704 }
1705
1706 static int
1707 thread_module_clear(PyObject *module)
1708 {
1709 thread_module_state *state = get_thread_state(module);
1710 Py_CLEAR(state->excepthook_type);
1711 Py_CLEAR(state->lock_type);
1712 Py_CLEAR(state->local_type);
1713 Py_CLEAR(state->local_dummy_type);
1714 return 0;
1715 }
1716
1717 static void
1718 thread_module_free(void *module)
1719 {
1720 thread_module_clear((PyObject *)module);
1721 }
1722
1723
1724
1725 PyDoc_STRVAR(thread_doc,
1726 "This module provides primitive operations to write multi-threaded programs.\n\
1727 The 'threading' module provides a more convenient interface.");
1728
1729 static PyModuleDef_Slot thread_module_slots[] = {
1730 {Py_mod_exec, thread_module_exec},
1731 {0, NULL}
1732 };
1733
1734 static struct PyModuleDef thread_module = {
1735 PyModuleDef_HEAD_INIT,
1736 .m_name = "_thread",
1737 .m_doc = thread_doc,
1738 .m_size = sizeof(thread_module_state),
1739 .m_methods = thread_methods,
1740 .m_traverse = thread_module_traverse,
1741 .m_clear = thread_module_clear,
1742 .m_free = thread_module_free,
1743 .m_slots = thread_module_slots,
1744 };
1745
1746 PyMODINIT_FUNC
1747 PyInit__thread(void)
1748 {
1749 return PyModuleDef_Init(&thread_module);
1750 }