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