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