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