blob: 388e26e58d42048572e95a737da7277c08a6a012 [file] [log] [blame]
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001
2/* Thread module */
3/* Interface to Sjoerd's portable C thread library */
4
Barry Warsawd0c10421996-12-17 00:05:22 +00005#include "Python.h"
Victor Stinner4a21e572020-04-15 02:35:41 +02006#include "pycore_interp.h" // _PyInterpreterState.num_threads
Victor Stinnercdad2722021-04-22 00:52:52 +02007#include "pycore_moduleobject.h" // _PyModule_GetState()
8#include "pycore_pylifecycle.h"
Victor Stinner4a21e572020-04-15 02:35:41 +02009#include "pycore_pystate.h" // _PyThreadState_Init()
10#include <stddef.h> // offsetof()
Victor Stinner61040132020-12-18 01:39:00 +010011#include "structmember.h" // PyMemberDef
Guido van Rossum1984f1e1992-08-04 12:41:02 +000012
Antoine Pitrouba251c22021-03-11 23:35:45 +010013#ifdef HAVE_SIGNAL_H
14# include <signal.h> // SIGINT
15#endif
16
Victor Stinner8203c732020-12-16 12:20:33 +010017// ThreadError is just an alias to PyExc_RuntimeError
18#define ThreadError PyExc_RuntimeError
19
20_Py_IDENTIFIER(__dict__);
Guido van Rossum1984f1e1992-08-04 12:41:02 +000021
Victor Stinnerbd303c12013-11-07 23:07:29 +010022_Py_IDENTIFIER(stderr);
Victor Stinnercd590a72019-05-28 00:39:52 +020023_Py_IDENTIFIER(flush);
Victor Stinnerbd303c12013-11-07 23:07:29 +010024
Victor Stinner8203c732020-12-16 12:20:33 +010025
Victor Stinner61040132020-12-18 01:39:00 +010026// Forward declarations
27static struct PyModuleDef thread_module;
28
29
30typedef struct {
31 PyTypeObject *lock_type;
32 PyTypeObject *local_type;
33 PyTypeObject *local_dummy_type;
34} thread_module_state;
35
36static inline thread_module_state*
37get_thread_state(PyObject *module)
38{
Victor Stinnercdad2722021-04-22 00:52:52 +020039 void *state = _PyModule_GetState(module);
Victor Stinner61040132020-12-18 01:39:00 +010040 assert(state != NULL);
41 return (thread_module_state *)state;
42}
43
44
Guido van Rossum1984f1e1992-08-04 12:41:02 +000045/* Lock objects */
46
47typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000048 PyObject_HEAD
49 PyThread_type_lock lock_lock;
50 PyObject *in_weakreflist;
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +000051 char locked; /* for sanity checking */
Guido van Rossum1984f1e1992-08-04 12:41:02 +000052} lockobject;
53
Victor Stinner61040132020-12-18 01:39:00 +010054static int
55lock_traverse(lockobject *self, visitproc visit, void *arg)
56{
57 Py_VISIT(Py_TYPE(self));
58 return 0;
59}
60
Guido van Rossum1984f1e1992-08-04 12:41:02 +000061static void
Peter Schneider-Kamp3707efe2000-07-10 10:03:58 +000062lock_dealloc(lockobject *self)
Guido van Rossum1984f1e1992-08-04 12:41:02 +000063{
Victor Stinner8203c732020-12-16 12:20:33 +010064 if (self->in_weakreflist != NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000065 PyObject_ClearWeakRefs((PyObject *) self);
Victor Stinner8203c732020-12-16 12:20:33 +010066 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000067 if (self->lock_lock != NULL) {
68 /* Unlock the lock so it's safe to free it */
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +000069 if (self->locked)
70 PyThread_release_lock(self->lock_lock);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000071 PyThread_free_lock(self->lock_lock);
72 }
Victor Stinner61040132020-12-18 01:39:00 +010073 PyTypeObject *tp = Py_TYPE(self);
74 tp->tp_free((PyObject*)self);
75 Py_DECREF(tp);
Guido van Rossum1984f1e1992-08-04 12:41:02 +000076}
77
Antoine Pitrou810023d2010-12-15 22:59:16 +000078/* Helper to acquire an interruptible lock with a timeout. If the lock acquire
79 * is interrupted, signal handlers are run, and if they raise an exception,
80 * PY_LOCK_INTR is returned. Otherwise, PY_LOCK_ACQUIRED or PY_LOCK_FAILURE
Raymond Hettinger15f44ab2016-08-30 10:47:49 -070081 * are returned, depending on whether the lock can be acquired within the
Antoine Pitrou810023d2010-12-15 22:59:16 +000082 * timeout.
83 */
84static PyLockStatus
Victor Stinnerf5faad22015-03-28 03:52:05 +010085acquire_timed(PyThread_type_lock lock, _PyTime_t timeout)
Antoine Pitrou810023d2010-12-15 22:59:16 +000086{
87 PyLockStatus r;
Victor Stinnerf5faad22015-03-28 03:52:05 +010088 _PyTime_t endtime = 0;
Antoine Pitrou810023d2010-12-15 22:59:16 +000089
Victor Stinner8203c732020-12-16 12:20:33 +010090 if (timeout > 0) {
Victor Stinnerf5faad22015-03-28 03:52:05 +010091 endtime = _PyTime_GetMonotonicClock() + timeout;
Victor Stinner8203c732020-12-16 12:20:33 +010092 }
Antoine Pitrou810023d2010-12-15 22:59:16 +000093
94 do {
Victor Stinner8203c732020-12-16 12:20:33 +010095 _PyTime_t microseconds;
Victor Stinner869e1772015-03-30 03:49:14 +020096 microseconds = _PyTime_AsMicroseconds(timeout, _PyTime_ROUND_CEILING);
Victor Stinnerf5faad22015-03-28 03:52:05 +010097
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +000098 /* first a simple non-blocking try without releasing the GIL */
99 r = PyThread_acquire_lock_timed(lock, 0, 0);
100 if (r == PY_LOCK_FAILURE && microseconds != 0) {
101 Py_BEGIN_ALLOW_THREADS
102 r = PyThread_acquire_lock_timed(lock, microseconds, 1);
103 Py_END_ALLOW_THREADS
Victor Stinner357f5152013-11-05 15:10:19 +0100104 }
Antoine Pitrou810023d2010-12-15 22:59:16 +0000105
106 if (r == PY_LOCK_INTR) {
107 /* Run signal handlers if we were interrupted. Propagate
108 * exceptions from signal handlers, such as KeyboardInterrupt, by
109 * passing up PY_LOCK_INTR. */
110 if (Py_MakePendingCalls() < 0) {
111 return PY_LOCK_INTR;
112 }
113
114 /* If we're using a timeout, recompute the timeout after processing
115 * signals, since those can take time. */
Victor Stinnerf5faad22015-03-28 03:52:05 +0100116 if (timeout > 0) {
117 timeout = endtime - _PyTime_GetMonotonicClock();
Antoine Pitrou810023d2010-12-15 22:59:16 +0000118
119 /* Check for negative values, since those mean block forever.
120 */
Victor Stinner6aa446c2015-03-30 21:33:51 +0200121 if (timeout < 0) {
Antoine Pitrou810023d2010-12-15 22:59:16 +0000122 r = PY_LOCK_FAILURE;
123 }
124 }
125 }
126 } while (r == PY_LOCK_INTR); /* Retry if we were interrupted. */
127
128 return r;
129}
130
Victor Stinnerf5faad22015-03-28 03:52:05 +0100131static int
132lock_acquire_parse_args(PyObject *args, PyObject *kwds,
133 _PyTime_t *timeout)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000134{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000135 char *kwlist[] = {"blocking", "timeout", NULL};
136 int blocking = 1;
Victor Stinnerf5faad22015-03-28 03:52:05 +0100137 PyObject *timeout_obj = NULL;
Victor Stinner13019fd2015-04-03 13:10:54 +0200138 const _PyTime_t unset_timeout = _PyTime_FromSeconds(-1);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000139
Victor Stinnerf5faad22015-03-28 03:52:05 +0100140 *timeout = unset_timeout ;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000141
Victor Stinnerf5faad22015-03-28 03:52:05 +0100142 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iO:acquire", kwlist,
143 &blocking, &timeout_obj))
144 return -1;
145
146 if (timeout_obj
Victor Stinner869e1772015-03-30 03:49:14 +0200147 && _PyTime_FromSecondsObject(timeout,
Pablo Galindo59af94f2017-10-18 08:13:09 +0100148 timeout_obj, _PyTime_ROUND_TIMEOUT) < 0)
Victor Stinnerf5faad22015-03-28 03:52:05 +0100149 return -1;
150
151 if (!blocking && *timeout != unset_timeout ) {
152 PyErr_SetString(PyExc_ValueError,
153 "can't specify a timeout for a non-blocking call");
154 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000155 }
Victor Stinnerf5faad22015-03-28 03:52:05 +0100156 if (*timeout < 0 && *timeout != unset_timeout) {
157 PyErr_SetString(PyExc_ValueError,
158 "timeout value must be positive");
159 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000160 }
161 if (!blocking)
Victor Stinnerf5faad22015-03-28 03:52:05 +0100162 *timeout = 0;
163 else if (*timeout != unset_timeout) {
164 _PyTime_t microseconds;
165
Pablo Galindo59af94f2017-10-18 08:13:09 +0100166 microseconds = _PyTime_AsMicroseconds(*timeout, _PyTime_ROUND_TIMEOUT);
Victor Stinnerf5faad22015-03-28 03:52:05 +0100167 if (microseconds >= PY_TIMEOUT_MAX) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000168 PyErr_SetString(PyExc_OverflowError,
169 "timeout value is too large");
Victor Stinnerf5faad22015-03-28 03:52:05 +0100170 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000171 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000172 }
Victor Stinnerf5faad22015-03-28 03:52:05 +0100173 return 0;
174}
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000175
Victor Stinnerf5faad22015-03-28 03:52:05 +0100176static PyObject *
177lock_PyThread_acquire_lock(lockobject *self, PyObject *args, PyObject *kwds)
178{
179 _PyTime_t timeout;
Victor Stinnerf5faad22015-03-28 03:52:05 +0100180 if (lock_acquire_parse_args(args, kwds, &timeout) < 0)
181 return NULL;
182
Victor Stinner8203c732020-12-16 12:20:33 +0100183 PyLockStatus r = acquire_timed(self->lock_lock, timeout);
Antoine Pitrou810023d2010-12-15 22:59:16 +0000184 if (r == PY_LOCK_INTR) {
185 return NULL;
186 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000187
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +0000188 if (r == PY_LOCK_ACQUIRED)
189 self->locked = 1;
Antoine Pitrou810023d2010-12-15 22:59:16 +0000190 return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000191}
192
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000193PyDoc_STRVAR(acquire_doc,
Berker Peksag720e6552016-05-02 12:25:35 +0300194"acquire(blocking=True, timeout=-1) -> bool\n\
Guido van Rossumf6694362006-03-10 02:28:35 +0000195(acquire_lock() is an obsolete synonym)\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000196\n\
197Lock the lock. Without argument, this blocks if the lock is already\n\
198locked (even by the same thread), waiting for another thread to release\n\
R David Murray95b71102013-02-04 10:15:58 -0500199the lock, and return True once the lock is acquired.\n\
Guido van Rossum8fdc75b2002-04-07 06:32:21 +0000200With an argument, this will only block if the argument is true,\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000201and the return value reflects whether the lock is acquired.\n\
Antoine Pitrou810023d2010-12-15 22:59:16 +0000202The blocking operation is interruptible.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000203
Barry Warsawd0c10421996-12-17 00:05:22 +0000204static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530205lock_PyThread_release_lock(lockobject *self, PyObject *Py_UNUSED(ignored))
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000206{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000207 /* Sanity check: the lock must be locked */
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +0000208 if (!self->locked) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000209 PyErr_SetString(ThreadError, "release unlocked lock");
210 return NULL;
211 }
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000212
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000213 PyThread_release_lock(self->lock_lock);
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +0000214 self->locked = 0;
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200215 Py_RETURN_NONE;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000216}
217
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000218PyDoc_STRVAR(release_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000219"release()\n\
Guido van Rossumf6694362006-03-10 02:28:35 +0000220(release_lock() is an obsolete synonym)\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000221\n\
222Release the lock, allowing another thread that is blocked waiting for\n\
223the lock to acquire the lock. The lock must be in the locked state,\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000224but it needn't be locked by the same thread that unlocks it.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000225
Barry Warsawd0c10421996-12-17 00:05:22 +0000226static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530227lock_locked_lock(lockobject *self, PyObject *Py_UNUSED(ignored))
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000228{
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +0000229 return PyBool_FromLong((long)self->locked);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000230}
231
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000232PyDoc_STRVAR(locked_doc,
Guido van Rossum8fdc75b2002-04-07 06:32:21 +0000233"locked() -> bool\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000234(locked_lock() is an obsolete synonym)\n\
235\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000236Return whether the lock is in the locked state.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000237
Raymond Hettinger62f4dad2014-05-25 18:22:35 -0700238static PyObject *
239lock_repr(lockobject *self)
240{
241 return PyUnicode_FromFormat("<%s %s object at %p>",
242 self->locked ? "locked" : "unlocked", Py_TYPE(self)->tp_name, self);
243}
244
Victor Stinner87255be2020-04-07 23:11:49 +0200245#ifdef HAVE_FORK
246static PyObject *
247lock__at_fork_reinit(lockobject *self, PyObject *Py_UNUSED(args))
248{
249 if (_PyThread_at_fork_reinit(&self->lock_lock) < 0) {
250 PyErr_SetString(ThreadError, "failed to reinitialize lock at fork");
251 return NULL;
252 }
253
254 self->locked = 0;
255
256 Py_RETURN_NONE;
257}
258#endif /* HAVE_FORK */
259
260
Barry Warsawd0c10421996-12-17 00:05:22 +0000261static PyMethodDef lock_methods[] = {
Serhiy Storchaka62be7422018-11-27 13:27:31 +0200262 {"acquire_lock", (PyCFunction)(void(*)(void))lock_PyThread_acquire_lock,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000263 METH_VARARGS | METH_KEYWORDS, acquire_doc},
Serhiy Storchaka62be7422018-11-27 13:27:31 +0200264 {"acquire", (PyCFunction)(void(*)(void))lock_PyThread_acquire_lock,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000265 METH_VARARGS | METH_KEYWORDS, acquire_doc},
266 {"release_lock", (PyCFunction)lock_PyThread_release_lock,
267 METH_NOARGS, release_doc},
268 {"release", (PyCFunction)lock_PyThread_release_lock,
269 METH_NOARGS, release_doc},
270 {"locked_lock", (PyCFunction)lock_locked_lock,
271 METH_NOARGS, locked_doc},
272 {"locked", (PyCFunction)lock_locked_lock,
273 METH_NOARGS, locked_doc},
Serhiy Storchaka62be7422018-11-27 13:27:31 +0200274 {"__enter__", (PyCFunction)(void(*)(void))lock_PyThread_acquire_lock,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000275 METH_VARARGS | METH_KEYWORDS, acquire_doc},
276 {"__exit__", (PyCFunction)lock_PyThread_release_lock,
277 METH_VARARGS, release_doc},
Victor Stinner87255be2020-04-07 23:11:49 +0200278#ifdef HAVE_FORK
279 {"_at_fork_reinit", (PyCFunction)lock__at_fork_reinit,
280 METH_NOARGS, NULL},
281#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000282 {NULL, NULL} /* sentinel */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000283};
284
Victor Stinner8203c732020-12-16 12:20:33 +0100285PyDoc_STRVAR(lock_doc,
286"A lock object is a synchronization primitive. To create a lock,\n\
287call threading.Lock(). Methods are:\n\
288\n\
289acquire() -- lock the lock, possibly blocking until it can be obtained\n\
290release() -- unlock of the lock\n\
291locked() -- test whether the lock is currently locked\n\
292\n\
293A lock is not owned by the thread that locked it; another thread may\n\
294unlock it. A thread attempting to lock a lock that it has already locked\n\
295will block until another thread unlocks it. Deadlocks may ensue.");
296
Victor Stinner61040132020-12-18 01:39:00 +0100297static PyMemberDef lock_type_members[] = {
298 {"__weaklistoffset__", T_PYSSIZET, offsetof(lockobject, in_weakreflist), READONLY},
299 {NULL},
300};
301
302static PyType_Slot lock_type_slots[] = {
303 {Py_tp_dealloc, (destructor)lock_dealloc},
304 {Py_tp_repr, (reprfunc)lock_repr},
305 {Py_tp_doc, (void *)lock_doc},
306 {Py_tp_methods, lock_methods},
307 {Py_tp_traverse, lock_traverse},
308 {Py_tp_members, lock_type_members},
309 {0, 0}
310};
311
312static PyType_Spec lock_type_spec = {
313 .name = "_thread.lock",
314 .basicsize = sizeof(lockobject),
Erlend Egeberg Aasland9746cda2021-04-30 16:04:57 +0200315 .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Miss Islington (bot)7297d742021-06-17 03:19:44 -0700316 Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE),
Victor Stinner61040132020-12-18 01:39:00 +0100317 .slots = lock_type_slots,
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000318};
319
Antoine Pitrou434736a2009-11-10 18:46:01 +0000320/* Recursive lock objects */
321
322typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000323 PyObject_HEAD
324 PyThread_type_lock rlock_lock;
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200325 unsigned long rlock_owner;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000326 unsigned long rlock_count;
327 PyObject *in_weakreflist;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000328} rlockobject;
329
Miss Islington (bot)e30fe272021-06-15 06:29:44 -0700330static int
331rlock_traverse(rlockobject *self, visitproc visit, void *arg)
332{
333 Py_VISIT(Py_TYPE(self));
334 return 0;
335}
336
337
Antoine Pitrou434736a2009-11-10 18:46:01 +0000338static void
339rlock_dealloc(rlockobject *self)
340{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000341 if (self->in_weakreflist != NULL)
342 PyObject_ClearWeakRefs((PyObject *) self);
Victor Stinner357f5152013-11-05 15:10:19 +0100343 /* self->rlock_lock can be NULL if PyThread_allocate_lock() failed
344 in rlock_new() */
345 if (self->rlock_lock != NULL) {
346 /* Unlock the lock so it's safe to free it */
347 if (self->rlock_count > 0)
348 PyThread_release_lock(self->rlock_lock);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000349
Victor Stinner357f5152013-11-05 15:10:19 +0100350 PyThread_free_lock(self->rlock_lock);
351 }
Victor Stinner61040132020-12-18 01:39:00 +0100352 PyTypeObject *tp = Py_TYPE(self);
353 tp->tp_free(self);
354 Py_DECREF(tp);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000355}
356
357static PyObject *
358rlock_acquire(rlockobject *self, PyObject *args, PyObject *kwds)
359{
Victor Stinnerf5faad22015-03-28 03:52:05 +0100360 _PyTime_t timeout;
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200361 unsigned long tid;
Antoine Pitrou810023d2010-12-15 22:59:16 +0000362 PyLockStatus r = PY_LOCK_ACQUIRED;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000363
Victor Stinnerf5faad22015-03-28 03:52:05 +0100364 if (lock_acquire_parse_args(args, kwds, &timeout) < 0)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000365 return NULL;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000366
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000367 tid = PyThread_get_thread_ident();
368 if (self->rlock_count > 0 && tid == self->rlock_owner) {
369 unsigned long count = self->rlock_count + 1;
370 if (count <= self->rlock_count) {
371 PyErr_SetString(PyExc_OverflowError,
372 "Internal lock count overflowed");
373 return NULL;
374 }
375 self->rlock_count = count;
376 Py_RETURN_TRUE;
377 }
Victor Stinnerf5faad22015-03-28 03:52:05 +0100378 r = acquire_timed(self->rlock_lock, timeout);
Antoine Pitrou810023d2010-12-15 22:59:16 +0000379 if (r == PY_LOCK_ACQUIRED) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000380 assert(self->rlock_count == 0);
381 self->rlock_owner = tid;
382 self->rlock_count = 1;
383 }
Antoine Pitrou810023d2010-12-15 22:59:16 +0000384 else if (r == PY_LOCK_INTR) {
385 return NULL;
386 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000387
Antoine Pitrou810023d2010-12-15 22:59:16 +0000388 return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000389}
390
391PyDoc_STRVAR(rlock_acquire_doc,
392"acquire(blocking=True) -> bool\n\
393\n\
394Lock the lock. `blocking` indicates whether we should wait\n\
395for the lock to be available or not. If `blocking` is False\n\
396and another thread holds the lock, the method will return False\n\
397immediately. If `blocking` is True and another thread holds\n\
398the lock, the method will wait for the lock to be released,\n\
399take it and then return True.\n\
Antoine Pitrou810023d2010-12-15 22:59:16 +0000400(note: the blocking operation is interruptible.)\n\
Antoine Pitrou434736a2009-11-10 18:46:01 +0000401\n\
402In all other cases, the method will return True immediately.\n\
403Precisely, if the current thread already holds the lock, its\n\
404internal counter is simply incremented. If nobody holds the lock,\n\
405the lock is taken and its internal counter initialized to 1.");
406
407static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530408rlock_release(rlockobject *self, PyObject *Py_UNUSED(ignored))
Antoine Pitrou434736a2009-11-10 18:46:01 +0000409{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200410 unsigned long tid = PyThread_get_thread_ident();
Antoine Pitrou434736a2009-11-10 18:46:01 +0000411
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000412 if (self->rlock_count == 0 || self->rlock_owner != tid) {
413 PyErr_SetString(PyExc_RuntimeError,
414 "cannot release un-acquired lock");
415 return NULL;
416 }
417 if (--self->rlock_count == 0) {
418 self->rlock_owner = 0;
419 PyThread_release_lock(self->rlock_lock);
420 }
421 Py_RETURN_NONE;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000422}
423
424PyDoc_STRVAR(rlock_release_doc,
425"release()\n\
426\n\
427Release the lock, allowing another thread that is blocked waiting for\n\
428the lock to acquire the lock. The lock must be in the locked state,\n\
429and must be locked by the same thread that unlocks it; otherwise a\n\
430`RuntimeError` is raised.\n\
431\n\
432Do note that if the lock was acquire()d several times in a row by the\n\
433current thread, release() needs to be called as many times for the lock\n\
434to be available for other threads.");
435
436static PyObject *
Victor Stinnere8794522014-01-02 12:47:24 +0100437rlock_acquire_restore(rlockobject *self, PyObject *args)
Antoine Pitrou434736a2009-11-10 18:46:01 +0000438{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200439 unsigned long owner;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000440 unsigned long count;
441 int r = 1;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000442
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200443 if (!PyArg_ParseTuple(args, "(kk):_acquire_restore", &count, &owner))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000444 return NULL;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000445
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000446 if (!PyThread_acquire_lock(self->rlock_lock, 0)) {
447 Py_BEGIN_ALLOW_THREADS
448 r = PyThread_acquire_lock(self->rlock_lock, 1);
449 Py_END_ALLOW_THREADS
450 }
451 if (!r) {
452 PyErr_SetString(ThreadError, "couldn't acquire lock");
453 return NULL;
454 }
455 assert(self->rlock_count == 0);
456 self->rlock_owner = owner;
457 self->rlock_count = count;
458 Py_RETURN_NONE;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000459}
460
461PyDoc_STRVAR(rlock_acquire_restore_doc,
462"_acquire_restore(state) -> None\n\
463\n\
464For internal use by `threading.Condition`.");
465
466static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530467rlock_release_save(rlockobject *self, PyObject *Py_UNUSED(ignored))
Antoine Pitrou434736a2009-11-10 18:46:01 +0000468{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200469 unsigned long owner;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000470 unsigned long count;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000471
Victor Stinnerc2824d42011-04-24 23:41:33 +0200472 if (self->rlock_count == 0) {
473 PyErr_SetString(PyExc_RuntimeError,
474 "cannot release un-acquired lock");
475 return NULL;
476 }
477
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000478 owner = self->rlock_owner;
479 count = self->rlock_count;
480 self->rlock_count = 0;
481 self->rlock_owner = 0;
482 PyThread_release_lock(self->rlock_lock);
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200483 return Py_BuildValue("kk", count, owner);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000484}
485
486PyDoc_STRVAR(rlock_release_save_doc,
487"_release_save() -> tuple\n\
488\n\
489For internal use by `threading.Condition`.");
490
491
492static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530493rlock_is_owned(rlockobject *self, PyObject *Py_UNUSED(ignored))
Antoine Pitrou434736a2009-11-10 18:46:01 +0000494{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200495 unsigned long tid = PyThread_get_thread_ident();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000496
497 if (self->rlock_count > 0 && self->rlock_owner == tid) {
498 Py_RETURN_TRUE;
499 }
500 Py_RETURN_FALSE;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000501}
502
503PyDoc_STRVAR(rlock_is_owned_doc,
504"_is_owned() -> bool\n\
505\n\
506For internal use by `threading.Condition`.");
507
508static PyObject *
509rlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
510{
Victor Stinner87255be2020-04-07 23:11:49 +0200511 rlockobject *self = (rlockobject *) type->tp_alloc(type, 0);
512 if (self == NULL) {
513 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000514 }
Victor Stinner87255be2020-04-07 23:11:49 +0200515 self->in_weakreflist = NULL;
516 self->rlock_owner = 0;
517 self->rlock_count = 0;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000518
Victor Stinner87255be2020-04-07 23:11:49 +0200519 self->rlock_lock = PyThread_allocate_lock();
520 if (self->rlock_lock == NULL) {
521 Py_DECREF(self);
522 PyErr_SetString(ThreadError, "can't allocate lock");
523 return NULL;
524 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000525 return (PyObject *) self;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000526}
527
528static PyObject *
529rlock_repr(rlockobject *self)
530{
Raymond Hettinger62f4dad2014-05-25 18:22:35 -0700531 return PyUnicode_FromFormat("<%s %s object owner=%ld count=%lu at %p>",
532 self->rlock_count ? "locked" : "unlocked",
533 Py_TYPE(self)->tp_name, self->rlock_owner,
534 self->rlock_count, self);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000535}
536
537
Victor Stinner87255be2020-04-07 23:11:49 +0200538#ifdef HAVE_FORK
539static PyObject *
540rlock__at_fork_reinit(rlockobject *self, PyObject *Py_UNUSED(args))
541{
542 if (_PyThread_at_fork_reinit(&self->rlock_lock) < 0) {
543 PyErr_SetString(ThreadError, "failed to reinitialize lock at fork");
544 return NULL;
545 }
546
547 self->rlock_owner = 0;
548 self->rlock_count = 0;
549
550 Py_RETURN_NONE;
551}
552#endif /* HAVE_FORK */
553
554
Antoine Pitrou434736a2009-11-10 18:46:01 +0000555static PyMethodDef rlock_methods[] = {
Serhiy Storchaka62be7422018-11-27 13:27:31 +0200556 {"acquire", (PyCFunction)(void(*)(void))rlock_acquire,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000557 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
558 {"release", (PyCFunction)rlock_release,
559 METH_NOARGS, rlock_release_doc},
560 {"_is_owned", (PyCFunction)rlock_is_owned,
561 METH_NOARGS, rlock_is_owned_doc},
562 {"_acquire_restore", (PyCFunction)rlock_acquire_restore,
Victor Stinnere8794522014-01-02 12:47:24 +0100563 METH_VARARGS, rlock_acquire_restore_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000564 {"_release_save", (PyCFunction)rlock_release_save,
565 METH_NOARGS, rlock_release_save_doc},
Serhiy Storchaka62be7422018-11-27 13:27:31 +0200566 {"__enter__", (PyCFunction)(void(*)(void))rlock_acquire,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000567 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
568 {"__exit__", (PyCFunction)rlock_release,
569 METH_VARARGS, rlock_release_doc},
Victor Stinner87255be2020-04-07 23:11:49 +0200570#ifdef HAVE_FORK
571 {"_at_fork_reinit", (PyCFunction)rlock__at_fork_reinit,
572 METH_NOARGS, NULL},
573#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000574 {NULL, NULL} /* sentinel */
Antoine Pitrou434736a2009-11-10 18:46:01 +0000575};
576
577
Victor Stinner61040132020-12-18 01:39:00 +0100578static PyMemberDef rlock_type_members[] = {
579 {"__weaklistoffset__", T_PYSSIZET, offsetof(rlockobject, in_weakreflist), READONLY},
580 {NULL},
581};
582
583static PyType_Slot rlock_type_slots[] = {
584 {Py_tp_dealloc, (destructor)rlock_dealloc},
585 {Py_tp_repr, (reprfunc)rlock_repr},
586 {Py_tp_methods, rlock_methods},
587 {Py_tp_alloc, PyType_GenericAlloc},
588 {Py_tp_new, rlock_new},
589 {Py_tp_members, rlock_type_members},
Miss Islington (bot)e30fe272021-06-15 06:29:44 -0700590 {Py_tp_traverse, rlock_traverse},
Victor Stinner61040132020-12-18 01:39:00 +0100591 {0, 0},
592};
593
594static PyType_Spec rlock_type_spec = {
595 .name = "_thread.RLock",
596 .basicsize = sizeof(rlockobject),
Miss Islington (bot)7297d742021-06-17 03:19:44 -0700597 .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
598 Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE),
Victor Stinner61040132020-12-18 01:39:00 +0100599 .slots = rlock_type_slots,
Antoine Pitrou434736a2009-11-10 18:46:01 +0000600};
601
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000602static lockobject *
Victor Stinner61040132020-12-18 01:39:00 +0100603newlockobject(PyObject *module)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000604{
Victor Stinner61040132020-12-18 01:39:00 +0100605 thread_module_state *state = get_thread_state(module);
606
607 PyTypeObject *type = state->lock_type;
608 lockobject *self = (lockobject *)type->tp_alloc(type, 0);
Victor Stinner8203c732020-12-16 12:20:33 +0100609 if (self == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000610 return NULL;
Victor Stinner8203c732020-12-16 12:20:33 +0100611 }
612
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000613 self->lock_lock = PyThread_allocate_lock();
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +0000614 self->locked = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000615 self->in_weakreflist = NULL;
Victor Stinner8203c732020-12-16 12:20:33 +0100616
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000617 if (self->lock_lock == NULL) {
618 Py_DECREF(self);
619 PyErr_SetString(ThreadError, "can't allocate lock");
620 return NULL;
621 }
622 return self;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000623}
624
Jim Fultond15dc062004-07-14 19:11:50 +0000625/* Thread-local objects */
626
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000627/* Quick overview:
628
629 We need to be able to reclaim reference cycles as soon as possible
630 (both when a thread is being terminated, or a thread-local object
631 becomes unreachable from user data). Constraints:
632 - it must not be possible for thread-state dicts to be involved in
633 reference cycles (otherwise the cyclic GC will refuse to consider
634 objects referenced from a reachable thread-state dict, even though
635 local_dealloc would clear them)
636 - the death of a thread-state dict must still imply destruction of the
637 corresponding local dicts in all thread-local objects.
638
639 Our implementation uses small "localdummy" objects in order to break
640 the reference chain. These trivial objects are hashable (using the
641 default scheme of identity hashing) and weakrefable.
642 Each thread-state holds a separate localdummy for each local object
643 (as a /strong reference/),
644 and each thread-local object holds a dict mapping /weak references/
645 of localdummies to local dicts.
646
647 Therefore:
648 - only the thread-state dict holds a strong reference to the dummies
649 - only the thread-local object holds a strong reference to the local dicts
650 - only outside objects (application- or library-level) hold strong
651 references to the thread-local objects
652 - as soon as a thread-state dict is destroyed, the weakref callbacks of all
653 dummies attached to that thread are called, and destroy the corresponding
654 local dicts from thread-local objects
655 - as soon as a thread-local object is destroyed, its local dicts are
656 destroyed and its dummies are manually removed from all thread states
657 - the GC can do its work correctly when a thread-local object is dangling,
658 without any interference from the thread-state dicts
659
660 As an additional optimization, each localdummy holds a borrowed reference
661 to the corresponding localdict. This borrowed reference is only used
662 by the thread-local object which has created the localdummy, which should
663 guarantee that the localdict still exists when accessed.
664*/
665
666typedef struct {
667 PyObject_HEAD
668 PyObject *localdict; /* Borrowed reference! */
669 PyObject *weakreflist; /* List of weak references to self */
670} localdummyobject;
671
672static void
673localdummy_dealloc(localdummyobject *self)
674{
675 if (self->weakreflist != NULL)
676 PyObject_ClearWeakRefs((PyObject *) self);
Victor Stinner61040132020-12-18 01:39:00 +0100677 PyTypeObject *tp = Py_TYPE(self);
678 tp->tp_free((PyObject*)self);
679 Py_DECREF(tp);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000680}
681
Victor Stinner61040132020-12-18 01:39:00 +0100682static PyMemberDef local_dummy_type_members[] = {
683 {"__weaklistoffset__", T_PYSSIZET, offsetof(localdummyobject, weakreflist), READONLY},
684 {NULL},
685};
686
687static PyType_Slot local_dummy_type_slots[] = {
688 {Py_tp_dealloc, (destructor)localdummy_dealloc},
689 {Py_tp_doc, "Thread-local dummy"},
690 {Py_tp_members, local_dummy_type_members},
691 {0, 0}
692};
693
694static PyType_Spec local_dummy_type_spec = {
695 .name = "_thread._localdummy",
696 .basicsize = sizeof(localdummyobject),
Miss Islington (bot)7297d742021-06-17 03:19:44 -0700697 .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION |
698 Py_TPFLAGS_IMMUTABLETYPE),
Victor Stinner61040132020-12-18 01:39:00 +0100699 .slots = local_dummy_type_slots,
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000700};
701
702
Jim Fultond15dc062004-07-14 19:11:50 +0000703typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000704 PyObject_HEAD
705 PyObject *key;
706 PyObject *args;
707 PyObject *kw;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000708 PyObject *weakreflist; /* List of weak references to self */
709 /* A {localdummy weakref -> localdict} dict */
710 PyObject *dummies;
711 /* The callback for weakrefs to localdummies */
712 PyObject *wr_callback;
Jim Fultond15dc062004-07-14 19:11:50 +0000713} localobject;
714
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000715/* Forward declaration */
Victor Stinner61040132020-12-18 01:39:00 +0100716static PyObject *_ldict(localobject *self, thread_module_state *state);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000717static PyObject *_localdummy_destroyed(PyObject *meth_self, PyObject *dummyweakref);
718
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000719/* Create and register the dummy for the current thread.
720 Returns a borrowed reference of the corresponding local dict */
721static PyObject *
Victor Stinner61040132020-12-18 01:39:00 +0100722_local_create_dummy(localobject *self, thread_module_state *state)
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000723{
Victor Stinner8203c732020-12-16 12:20:33 +0100724 PyObject *ldict = NULL, *wr = NULL;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000725 localdummyobject *dummy = NULL;
Victor Stinner61040132020-12-18 01:39:00 +0100726 PyTypeObject *type = state->local_dummy_type;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000727
Victor Stinner8203c732020-12-16 12:20:33 +0100728 PyObject *tdict = PyThreadState_GetDict();
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000729 if (tdict == NULL) {
730 PyErr_SetString(PyExc_SystemError,
731 "Couldn't get thread-state dictionary");
732 goto err;
733 }
734
735 ldict = PyDict_New();
Victor Stinner8203c732020-12-16 12:20:33 +0100736 if (ldict == NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000737 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100738 }
Victor Stinner61040132020-12-18 01:39:00 +0100739 dummy = (localdummyobject *) type->tp_alloc(type, 0);
Victor Stinner8203c732020-12-16 12:20:33 +0100740 if (dummy == NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000741 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100742 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000743 dummy->localdict = ldict;
744 wr = PyWeakref_NewRef((PyObject *) dummy, self->wr_callback);
Victor Stinner8203c732020-12-16 12:20:33 +0100745 if (wr == NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000746 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100747 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000748
749 /* As a side-effect, this will cache the weakref's hash before the
750 dummy gets deleted */
Victor Stinner8203c732020-12-16 12:20:33 +0100751 int r = PyDict_SetItem(self->dummies, wr, ldict);
752 if (r < 0) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000753 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100754 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000755 Py_CLEAR(wr);
756 r = PyDict_SetItem(tdict, self->key, (PyObject *) dummy);
Victor Stinner8203c732020-12-16 12:20:33 +0100757 if (r < 0) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000758 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100759 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000760 Py_CLEAR(dummy);
761
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000762 Py_DECREF(ldict);
763 return ldict;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000764
765err:
766 Py_XDECREF(ldict);
767 Py_XDECREF(wr);
768 Py_XDECREF(dummy);
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000769 return NULL;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000770}
771
Jim Fultond15dc062004-07-14 19:11:50 +0000772static PyObject *
773local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
774{
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000775 static PyMethodDef wr_callback_def = {
776 "_localdummy_destroyed", (PyCFunction) _localdummy_destroyed, METH_O
777 };
Jim Fultond15dc062004-07-14 19:11:50 +0000778
Serhiy Storchakafa494fd2015-05-30 17:45:22 +0300779 if (type->tp_init == PyBaseObject_Type.tp_init) {
780 int rc = 0;
781 if (args != NULL)
782 rc = PyObject_IsTrue(args);
783 if (rc == 0 && kw != NULL)
784 rc = PyObject_IsTrue(kw);
785 if (rc != 0) {
Victor Stinner8203c732020-12-16 12:20:33 +0100786 if (rc > 0) {
Serhiy Storchakafa494fd2015-05-30 17:45:22 +0300787 PyErr_SetString(PyExc_TypeError,
788 "Initialization arguments are not supported");
Victor Stinner8203c732020-12-16 12:20:33 +0100789 }
Serhiy Storchakafa494fd2015-05-30 17:45:22 +0300790 return NULL;
791 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000792 }
Jim Fultond15dc062004-07-14 19:11:50 +0000793
Victor Stinner61040132020-12-18 01:39:00 +0100794 PyObject *module = _PyType_GetModuleByDef(type, &thread_module);
795 thread_module_state *state = get_thread_state(module);
796
797 localobject *self = (localobject *)type->tp_alloc(type, 0);
Victor Stinner8203c732020-12-16 12:20:33 +0100798 if (self == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000799 return NULL;
Victor Stinner8203c732020-12-16 12:20:33 +0100800 }
Jim Fultond15dc062004-07-14 19:11:50 +0000801
Victor Stinner8203c732020-12-16 12:20:33 +0100802 self->args = Py_XNewRef(args);
803 self->kw = Py_XNewRef(kw);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000804 self->key = PyUnicode_FromFormat("thread.local.%p", self);
Victor Stinner8203c732020-12-16 12:20:33 +0100805 if (self->key == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000806 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100807 }
Jim Fultond15dc062004-07-14 19:11:50 +0000808
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000809 self->dummies = PyDict_New();
Victor Stinner8203c732020-12-16 12:20:33 +0100810 if (self->dummies == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000811 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100812 }
Jim Fultond15dc062004-07-14 19:11:50 +0000813
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000814 /* We use a weak reference to self in the callback closure
815 in order to avoid spurious reference cycles */
Victor Stinner8203c732020-12-16 12:20:33 +0100816 PyObject *wr = PyWeakref_NewRef((PyObject *) self, NULL);
817 if (wr == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000818 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100819 }
Andrew Svetlov3ba3a3e2012-12-25 13:32:35 +0200820 self->wr_callback = PyCFunction_NewEx(&wr_callback_def, wr, NULL);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000821 Py_DECREF(wr);
Victor Stinner8203c732020-12-16 12:20:33 +0100822 if (self->wr_callback == NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000823 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100824 }
Victor Stinner61040132020-12-18 01:39:00 +0100825 if (_local_create_dummy(self, state) == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000826 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100827 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000828 return (PyObject *)self;
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000829
830 err:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000831 Py_DECREF(self);
832 return NULL;
Jim Fultond15dc062004-07-14 19:11:50 +0000833}
834
835static int
836local_traverse(localobject *self, visitproc visit, void *arg)
837{
Victor Stinner61040132020-12-18 01:39:00 +0100838 Py_VISIT(Py_TYPE(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000839 Py_VISIT(self->args);
840 Py_VISIT(self->kw);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000841 Py_VISIT(self->dummies);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000842 return 0;
Jim Fultond15dc062004-07-14 19:11:50 +0000843}
844
845static int
846local_clear(localobject *self)
847{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000848 Py_CLEAR(self->args);
849 Py_CLEAR(self->kw);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000850 Py_CLEAR(self->dummies);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000851 Py_CLEAR(self->wr_callback);
852 /* Remove all strong references to dummies from the thread states */
Victor Stinner839184f2021-02-19 15:51:36 +0100853 if (self->key) {
854 PyInterpreterState *interp = _PyInterpreterState_GET();
855 PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
856 for(; tstate; tstate = PyThreadState_Next(tstate)) {
857 if (tstate->dict == NULL) {
858 continue;
Serhiy Storchaka8905fcc2018-12-11 08:38:03 +0200859 }
Victor Stinner839184f2021-02-19 15:51:36 +0100860 PyObject *v = _PyDict_Pop(tstate->dict, self->key, Py_None);
861 if (v != NULL) {
862 Py_DECREF(v);
863 }
864 else {
865 PyErr_Clear();
866 }
867 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000868 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000869 return 0;
870}
Jim Fultond15dc062004-07-14 19:11:50 +0000871
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000872static void
873local_dealloc(localobject *self)
874{
875 /* Weakrefs must be invalidated right now, otherwise they can be used
876 from code called below, which is very dangerous since Py_REFCNT(self) == 0 */
Victor Stinner8203c732020-12-16 12:20:33 +0100877 if (self->weakreflist != NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000878 PyObject_ClearWeakRefs((PyObject *) self);
Victor Stinner8203c732020-12-16 12:20:33 +0100879 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000880
881 PyObject_GC_UnTrack(self);
882
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000883 local_clear(self);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000884 Py_XDECREF(self->key);
Victor Stinner61040132020-12-18 01:39:00 +0100885
886 PyTypeObject *tp = Py_TYPE(self);
887 tp->tp_free((PyObject*)self);
888 Py_DECREF(tp);
Jim Fultond15dc062004-07-14 19:11:50 +0000889}
890
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000891/* Returns a borrowed reference to the local dict, creating it if necessary */
Jim Fultond15dc062004-07-14 19:11:50 +0000892static PyObject *
Victor Stinner61040132020-12-18 01:39:00 +0100893_ldict(localobject *self, thread_module_state *state)
Jim Fultond15dc062004-07-14 19:11:50 +0000894{
Victor Stinner8203c732020-12-16 12:20:33 +0100895 PyObject *tdict = PyThreadState_GetDict();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000896 if (tdict == NULL) {
897 PyErr_SetString(PyExc_SystemError,
898 "Couldn't get thread-state dictionary");
899 return NULL;
900 }
Jim Fultond15dc062004-07-14 19:11:50 +0000901
Victor Stinner8203c732020-12-16 12:20:33 +0100902 PyObject *ldict;
903 PyObject *dummy = PyDict_GetItemWithError(tdict, self->key);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000904 if (dummy == NULL) {
Serhiy Storchakaa24107b2019-02-25 17:59:46 +0200905 if (PyErr_Occurred()) {
906 return NULL;
907 }
Victor Stinner61040132020-12-18 01:39:00 +0100908 ldict = _local_create_dummy(self, state);
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000909 if (ldict == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000910 return NULL;
Jim Fultond15dc062004-07-14 19:11:50 +0000911
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000912 if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init &&
913 Py_TYPE(self)->tp_init((PyObject*)self,
914 self->args, self->kw) < 0) {
915 /* we need to get rid of ldict from thread so
916 we create a new one the next time we do an attr
Ezio Melotti42da6632011-03-15 05:18:48 +0200917 access */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000918 PyDict_DelItem(tdict, self->key);
919 return NULL;
920 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000921 }
922 else {
Victor Stinner61040132020-12-18 01:39:00 +0100923 assert(Py_IS_TYPE(dummy, state->local_dummy_type));
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000924 ldict = ((localdummyobject *) dummy)->localdict;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000925 }
Jim Fultond15dc062004-07-14 19:11:50 +0000926
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000927 return ldict;
Jim Fultond15dc062004-07-14 19:11:50 +0000928}
929
Jim Fultond15dc062004-07-14 19:11:50 +0000930static int
931local_setattro(localobject *self, PyObject *name, PyObject *v)
932{
Victor Stinner61040132020-12-18 01:39:00 +0100933 PyObject *module = _PyType_GetModuleByDef(Py_TYPE(self), &thread_module);
934 thread_module_state *state = get_thread_state(module);
935
936 PyObject *ldict = _ldict(self, state);
Victor Stinner8203c732020-12-16 12:20:33 +0100937 if (ldict == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000938 return -1;
Victor Stinner8203c732020-12-16 12:20:33 +0100939 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000940
Victor Stinner8203c732020-12-16 12:20:33 +0100941 PyObject *str_dict = _PyUnicode_FromId(&PyId___dict__); // borrowed ref
942 if (str_dict == NULL) {
943 return -1;
944 }
945
946 int r = PyObject_RichCompareBool(name, str_dict, Py_EQ);
947 if (r == -1) {
948 return -1;
949 }
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000950 if (r == 1) {
951 PyErr_Format(PyExc_AttributeError,
952 "'%.50s' object attribute '%U' is read-only",
953 Py_TYPE(self)->tp_name, name);
954 return -1;
955 }
Jim Fultond15dc062004-07-14 19:11:50 +0000956
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000957 return _PyObject_GenericSetAttrWithDict((PyObject *)self, name, v, ldict);
Jim Fultond15dc062004-07-14 19:11:50 +0000958}
959
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000960static PyObject *local_getattro(localobject *, PyObject *);
961
Victor Stinner61040132020-12-18 01:39:00 +0100962static PyMemberDef local_type_members[] = {
963 {"__weaklistoffset__", T_PYSSIZET, offsetof(localobject, weakreflist), READONLY},
964 {NULL},
965};
966
967static PyType_Slot local_type_slots[] = {
968 {Py_tp_dealloc, (destructor)local_dealloc},
969 {Py_tp_getattro, (getattrofunc)local_getattro},
970 {Py_tp_setattro, (setattrofunc)local_setattro},
971 {Py_tp_doc, "Thread-local data"},
972 {Py_tp_traverse, (traverseproc)local_traverse},
973 {Py_tp_clear, (inquiry)local_clear},
974 {Py_tp_new, local_new},
975 {Py_tp_members, local_type_members},
976 {0, 0}
977};
978
979static PyType_Spec local_type_spec = {
980 .name = "_thread._local",
981 .basicsize = sizeof(localobject),
Miss Islington (bot)7297d742021-06-17 03:19:44 -0700982 .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
983 Py_TPFLAGS_IMMUTABLETYPE),
Victor Stinner61040132020-12-18 01:39:00 +0100984 .slots = local_type_slots,
Jim Fultond15dc062004-07-14 19:11:50 +0000985};
986
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000987static PyObject *
988local_getattro(localobject *self, PyObject *name)
989{
Victor Stinner61040132020-12-18 01:39:00 +0100990 PyObject *module = _PyType_GetModuleByDef(Py_TYPE(self), &thread_module);
991 thread_module_state *state = get_thread_state(module);
992
993 PyObject *ldict = _ldict(self, state);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000994 if (ldict == NULL)
995 return NULL;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000996
Victor Stinner8203c732020-12-16 12:20:33 +0100997 PyObject *str_dict = _PyUnicode_FromId(&PyId___dict__); // borrowed ref
998 if (str_dict == NULL) {
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000999 return NULL;
Victor Stinner8203c732020-12-16 12:20:33 +01001000 }
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +00001001
Victor Stinner8203c732020-12-16 12:20:33 +01001002 int r = PyObject_RichCompareBool(name, str_dict, Py_EQ);
1003 if (r == 1) {
1004 return Py_NewRef(ldict);
1005 }
1006 if (r == -1) {
1007 return NULL;
1008 }
1009
Victor Stinner61040132020-12-18 01:39:00 +01001010 if (!Py_IS_TYPE(self, state->local_type)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001011 /* use generic lookup for subtypes */
Victor Stinner8203c732020-12-16 12:20:33 +01001012 return _PyObject_GenericGetAttrWithDict((PyObject *)self, name,
1013 ldict, 0);
1014 }
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001015
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001016 /* Optimization: just look in dict ourselves */
Victor Stinner8203c732020-12-16 12:20:33 +01001017 PyObject *value = PyDict_GetItemWithError(ldict, name);
Serhiy Storchakaa24107b2019-02-25 17:59:46 +02001018 if (value != NULL) {
Victor Stinner8203c732020-12-16 12:20:33 +01001019 return Py_NewRef(value);
Serhiy Storchakaa24107b2019-02-25 17:59:46 +02001020 }
Victor Stinner8203c732020-12-16 12:20:33 +01001021 if (PyErr_Occurred()) {
Serhiy Storchakaa24107b2019-02-25 17:59:46 +02001022 return NULL;
1023 }
Victor Stinner8203c732020-12-16 12:20:33 +01001024
Serhiy Storchakaa24107b2019-02-25 17:59:46 +02001025 /* Fall back on generic to get __class__ and __dict__ */
1026 return _PyObject_GenericGetAttrWithDict(
1027 (PyObject *)self, name, ldict, 0);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001028}
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001029
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001030/* Called when a dummy is destroyed. */
1031static PyObject *
1032_localdummy_destroyed(PyObject *localweakref, PyObject *dummyweakref)
1033{
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001034 assert(PyWeakref_CheckRef(localweakref));
Victor Stinner8203c732020-12-16 12:20:33 +01001035 PyObject *obj = PyWeakref_GET_OBJECT(localweakref);
1036 if (obj == Py_None) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001037 Py_RETURN_NONE;
Victor Stinner8203c732020-12-16 12:20:33 +01001038 }
1039
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001040 /* If the thread-local object is still alive and not being cleared,
1041 remove the corresponding local dict */
Victor Stinner8203c732020-12-16 12:20:33 +01001042 localobject *self = (localobject *)Py_NewRef(obj);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001043 if (self->dummies != NULL) {
1044 PyObject *ldict;
Serhiy Storchakaa24107b2019-02-25 17:59:46 +02001045 ldict = PyDict_GetItemWithError(self->dummies, dummyweakref);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001046 if (ldict != NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001047 PyDict_DelItem(self->dummies, dummyweakref);
1048 }
1049 if (PyErr_Occurred())
1050 PyErr_WriteUnraisable(obj);
1051 }
1052 Py_DECREF(obj);
1053 Py_RETURN_NONE;
1054}
1055
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001056/* Module functions */
1057
Guido van Rossuma027efa1997-05-05 20:56:21 +00001058struct bootstate {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001059 PyInterpreterState *interp;
1060 PyObject *func;
1061 PyObject *args;
Victor Stinner8203c732020-12-16 12:20:33 +01001062 PyObject *kwargs;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001063 PyThreadState *tstate;
Joannah Nanjekye2bc43cd2019-09-05 13:06:49 -03001064 _PyRuntimeState *runtime;
Guido van Rossuma027efa1997-05-05 20:56:21 +00001065};
1066
Victor Stinner8203c732020-12-16 12:20:33 +01001067
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001068static void
Victor Stinner8203c732020-12-16 12:20:33 +01001069thread_bootstate_free(struct bootstate *boot)
1070{
1071 Py_DECREF(boot->func);
1072 Py_DECREF(boot->args);
1073 Py_XDECREF(boot->kwargs);
1074 PyMem_Free(boot);
1075}
1076
1077
1078static void
1079thread_run(void *boot_raw)
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001080{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001081 struct bootstate *boot = (struct bootstate *) boot_raw;
1082 PyThreadState *tstate;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001083
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001084 tstate = boot->tstate;
1085 tstate->thread_id = PyThread_get_thread_ident();
Victor Stinner01b1cc12019-11-20 02:27:56 +01001086 _PyThreadState_Init(tstate);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001087 PyEval_AcquireThread(tstate);
Eric Snow2ebc5ce2017-09-07 23:51:28 -06001088 tstate->interp->num_threads++;
Victor Stinner8203c732020-12-16 12:20:33 +01001089
1090 PyObject *res = PyObject_Call(boot->func, boot->args, boot->kwargs);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001091 if (res == NULL) {
1092 if (PyErr_ExceptionMatches(PyExc_SystemExit))
Victor Stinner8b095002019-05-29 02:57:56 +02001093 /* SystemExit is ignored silently */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001094 PyErr_Clear();
1095 else {
Victor Stinner8b095002019-05-29 02:57:56 +02001096 _PyErr_WriteUnraisableMsg("in thread started by", boot->func);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001097 }
1098 }
Victor Stinner8b095002019-05-29 02:57:56 +02001099 else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001100 Py_DECREF(res);
Victor Stinner8b095002019-05-29 02:57:56 +02001101 }
Victor Stinner8203c732020-12-16 12:20:33 +01001102
1103 thread_bootstate_free(boot);
Eric Snow2ebc5ce2017-09-07 23:51:28 -06001104 tstate->interp->num_threads--;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001105 PyThreadState_Clear(tstate);
Victor Stinner23ef89d2020-03-18 02:26:04 +01001106 _PyThreadState_DeleteCurrent(tstate);
Victor Stinner8203c732020-12-16 12:20:33 +01001107
Miss Islington (bot)6614eac2021-06-21 05:29:17 -07001108 // bpo-44434: Don't call explicitly PyThread_exit_thread(). On Linux with
1109 // the glibc, pthread_exit() can abort the whole process if dlopen() fails
1110 // to open the libgcc_s.so library (ex: EMFILE error).
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001111}
1112
Barry Warsawd0c10421996-12-17 00:05:22 +00001113static PyObject *
Peter Schneider-Kamp3707efe2000-07-10 10:03:58 +00001114thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001115{
Joannah Nanjekye2bc43cd2019-09-05 13:06:49 -03001116 _PyRuntimeState *runtime = &_PyRuntime;
Victor Stinner8203c732020-12-16 12:20:33 +01001117 PyObject *func, *args, *kwargs = NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001118
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001119 if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3,
Victor Stinner8203c732020-12-16 12:20:33 +01001120 &func, &args, &kwargs))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001121 return NULL;
1122 if (!PyCallable_Check(func)) {
1123 PyErr_SetString(PyExc_TypeError,
1124 "first arg must be callable");
1125 return NULL;
1126 }
1127 if (!PyTuple_Check(args)) {
1128 PyErr_SetString(PyExc_TypeError,
1129 "2nd arg must be a tuple");
1130 return NULL;
1131 }
Victor Stinner8203c732020-12-16 12:20:33 +01001132 if (kwargs != NULL && !PyDict_Check(kwargs)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001133 PyErr_SetString(PyExc_TypeError,
1134 "optional 3rd arg must be a dictionary");
1135 return NULL;
1136 }
Victor Stinner252346a2020-05-01 11:33:44 +02001137
1138 PyInterpreterState *interp = _PyInterpreterState_GET();
1139 if (interp->config._isolated_interpreter) {
1140 PyErr_SetString(PyExc_RuntimeError,
1141 "thread is not supported for isolated subinterpreters");
1142 return NULL;
1143 }
1144
Victor Stinner8203c732020-12-16 12:20:33 +01001145 struct bootstate *boot = PyMem_NEW(struct bootstate, 1);
1146 if (boot == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001147 return PyErr_NoMemory();
Victor Stinner8203c732020-12-16 12:20:33 +01001148 }
Victor Stinner81a7be32020-04-14 15:14:01 +02001149 boot->interp = _PyInterpreterState_GET();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001150 boot->tstate = _PyThreadState_Prealloc(boot->interp);
1151 if (boot->tstate == NULL) {
Victor Stinner00d7abd2020-12-01 09:56:42 +01001152 PyMem_Free(boot);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001153 return PyErr_NoMemory();
1154 }
Victor Stinner8203c732020-12-16 12:20:33 +01001155 boot->runtime = runtime;
1156 boot->func = Py_NewRef(func);
1157 boot->args = Py_NewRef(args);
1158 boot->kwargs = Py_XNewRef(kwargs);
Victor Stinner3225b9f2020-03-09 20:56:57 +01001159
Victor Stinner8203c732020-12-16 12:20:33 +01001160 unsigned long ident = PyThread_start_new_thread(thread_run, (void*) boot);
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001161 if (ident == PYTHREAD_INVALID_THREAD_ID) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001162 PyErr_SetString(ThreadError, "can't start new thread");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001163 PyThreadState_Clear(boot->tstate);
Victor Stinner8203c732020-12-16 12:20:33 +01001164 thread_bootstate_free(boot);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001165 return NULL;
1166 }
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001167 return PyLong_FromUnsignedLong(ident);
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001168}
1169
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001170PyDoc_STRVAR(start_new_doc,
Andrew M. Kuchling38300c62001-10-05 12:24:15 +00001171"start_new_thread(function, args[, kwargs])\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001172(start_new() is an obsolete synonym)\n\
1173\n\
Guido van Rossum3c288632001-10-16 21:13:49 +00001174Start a new thread and return its identifier. The thread will call the\n\
1175function with positional arguments from the tuple args and keyword arguments\n\
1176taken from the optional dictionary kwargs. The thread exits when the\n\
1177function returns; the return value is ignored. The thread will also exit\n\
1178when the function raises an unhandled exception; a stack trace will be\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001179printed unless the exception is SystemExit.\n");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001180
Barry Warsawd0c10421996-12-17 00:05:22 +00001181static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301182thread_PyThread_exit_thread(PyObject *self, PyObject *Py_UNUSED(ignored))
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001183{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001184 PyErr_SetNone(PyExc_SystemExit);
1185 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001186}
1187
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001188PyDoc_STRVAR(exit_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001189"exit()\n\
Éric Araujo9bcf8bf2011-05-31 14:08:26 +02001190(exit_thread() is an obsolete synonym)\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001191\n\
1192This is synonymous to ``raise SystemExit''. It will cause the current\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001193thread to exit silently unless the exception is caught.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001194
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001195static PyObject *
Antoine Pitrouba251c22021-03-11 23:35:45 +01001196thread_PyThread_interrupt_main(PyObject *self, PyObject *args)
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001197{
Antoine Pitrouba251c22021-03-11 23:35:45 +01001198 int signum = SIGINT;
1199 if (!PyArg_ParseTuple(args, "|i:signum", &signum)) {
1200 return NULL;
1201 }
1202
1203 if (PyErr_SetInterruptEx(signum)) {
1204 PyErr_SetString(PyExc_ValueError, "signal number out of range");
1205 return NULL;
1206 }
Serhiy Storchaka228b12e2017-01-23 09:47:21 +02001207 Py_RETURN_NONE;
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001208}
1209
1210PyDoc_STRVAR(interrupt_doc,
Antoine Pitrouba251c22021-03-11 23:35:45 +01001211"interrupt_main(signum=signal.SIGINT, /)\n\
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001212\n\
Antoine Pitrouba251c22021-03-11 23:35:45 +01001213Simulate the arrival of the given signal in the main thread,\n\
1214where the corresponding signal handler will be executed.\n\
1215If *signum* is omitted, SIGINT is assumed.\n\
1216A subthread can use this function to interrupt the main thread.\n\
1217\n\
1218Note: the default signal hander for SIGINT raises ``KeyboardInterrupt``."
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001219);
1220
Victor Stinner61040132020-12-18 01:39:00 +01001221static lockobject *newlockobject(PyObject *module);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001222
Barry Warsawd0c10421996-12-17 00:05:22 +00001223static PyObject *
Victor Stinner8203c732020-12-16 12:20:33 +01001224thread_PyThread_allocate_lock(PyObject *module, PyObject *Py_UNUSED(ignored))
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001225{
Victor Stinner61040132020-12-18 01:39:00 +01001226 return (PyObject *) newlockobject(module);
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001227}
1228
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001229PyDoc_STRVAR(allocate_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001230"allocate_lock() -> lock object\n\
1231(allocate() is an obsolete synonym)\n\
1232\n\
Berker Peksag720e6552016-05-02 12:25:35 +03001233Create a new lock object. See help(type(threading.Lock())) for\n\
1234information about locks.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001235
Barry Warsawd0c10421996-12-17 00:05:22 +00001236static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301237thread_get_ident(PyObject *self, PyObject *Py_UNUSED(ignored))
Guido van Rossumb6775db1994-08-01 11:34:53 +00001238{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001239 unsigned long ident = PyThread_get_thread_ident();
1240 if (ident == PYTHREAD_INVALID_THREAD_ID) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001241 PyErr_SetString(ThreadError, "no current thread ident");
1242 return NULL;
1243 }
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001244 return PyLong_FromUnsignedLong(ident);
Guido van Rossumb6775db1994-08-01 11:34:53 +00001245}
1246
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001247PyDoc_STRVAR(get_ident_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001248"get_ident() -> integer\n\
1249\n\
1250Return a non-zero integer that uniquely identifies the current thread\n\
1251amongst other threads that exist simultaneously.\n\
1252This may be used to identify per-thread resources.\n\
1253Even though on some platforms threads identities may appear to be\n\
1254allocated consecutive numbers starting at 1, this behavior should not\n\
1255be relied upon, and the number should be seen purely as a magic cookie.\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001256A thread's identity may be reused for another thread after it exits.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001257
Jake Teslerb121f632019-05-22 08:43:17 -07001258#ifdef PY_HAVE_THREAD_NATIVE_ID
1259static PyObject *
1260thread_get_native_id(PyObject *self, PyObject *Py_UNUSED(ignored))
1261{
1262 unsigned long native_id = PyThread_get_thread_native_id();
1263 return PyLong_FromUnsignedLong(native_id);
1264}
1265
1266PyDoc_STRVAR(get_native_id_doc,
1267"get_native_id() -> integer\n\
1268\n\
1269Return a non-negative integer identifying the thread as reported\n\
1270by the OS (kernel). This may be used to uniquely identify a\n\
1271particular thread within a system.");
1272#endif
1273
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001274static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301275thread__count(PyObject *self, PyObject *Py_UNUSED(ignored))
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001276{
Victor Stinner81a7be32020-04-14 15:14:01 +02001277 PyInterpreterState *interp = _PyInterpreterState_GET();
Victor Stinnercaba55b2018-08-03 15:33:52 +02001278 return PyLong_FromLong(interp->num_threads);
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001279}
1280
1281PyDoc_STRVAR(_count_doc,
1282"_count() -> integer\n\
1283\n\
Antoine Pitrou9257f5e2009-10-30 22:23:02 +00001284\
oldkaa0735f2018-02-02 16:52:55 +08001285Return the number of currently running Python threads, excluding\n\
Antoine Pitrou9257f5e2009-10-30 22:23:02 +00001286the main thread. The returned number comprises all threads created\n\
1287through `start_new_thread()` as well as `threading.Thread`, and not\n\
1288yet finished.\n\
1289\n\
1290This function is meant for internal and specialized purposes only.\n\
1291In most applications `threading.enumerate()` should be used instead.");
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001292
Antoine Pitrou7b476992013-09-07 23:38:37 +02001293static void
Victor Stinnera42de742018-11-22 10:25:22 +01001294release_sentinel(void *wr_raw)
Antoine Pitrou7b476992013-09-07 23:38:37 +02001295{
Victor Stinnera42de742018-11-22 10:25:22 +01001296 PyObject *wr = _PyObject_CAST(wr_raw);
Antoine Pitrou7b476992013-09-07 23:38:37 +02001297 /* Tricky: this function is called when the current thread state
1298 is being deleted. Therefore, only simple C code can safely
1299 execute here. */
1300 PyObject *obj = PyWeakref_GET_OBJECT(wr);
1301 lockobject *lock;
1302 if (obj != Py_None) {
Antoine Pitrou7b476992013-09-07 23:38:37 +02001303 lock = (lockobject *) obj;
1304 if (lock->locked) {
1305 PyThread_release_lock(lock->lock_lock);
1306 lock->locked = 0;
1307 }
1308 }
1309 /* Deallocating a weakref with a NULL callback only calls
1310 PyObject_GC_Del(), which can't call any Python code. */
1311 Py_DECREF(wr);
1312}
1313
1314static PyObject *
Victor Stinner8203c732020-12-16 12:20:33 +01001315thread__set_sentinel(PyObject *module, PyObject *Py_UNUSED(ignored))
Antoine Pitrou7b476992013-09-07 23:38:37 +02001316{
1317 PyObject *wr;
1318 PyThreadState *tstate = PyThreadState_Get();
1319 lockobject *lock;
1320
1321 if (tstate->on_delete_data != NULL) {
1322 /* We must support the re-creation of the lock from a
1323 fork()ed child. */
1324 assert(tstate->on_delete == &release_sentinel);
1325 wr = (PyObject *) tstate->on_delete_data;
1326 tstate->on_delete = NULL;
1327 tstate->on_delete_data = NULL;
1328 Py_DECREF(wr);
1329 }
Victor Stinner61040132020-12-18 01:39:00 +01001330 lock = newlockobject(module);
Antoine Pitrou7b476992013-09-07 23:38:37 +02001331 if (lock == NULL)
1332 return NULL;
1333 /* The lock is owned by whoever called _set_sentinel(), but the weakref
1334 hangs to the thread state. */
1335 wr = PyWeakref_NewRef((PyObject *) lock, NULL);
1336 if (wr == NULL) {
1337 Py_DECREF(lock);
1338 return NULL;
1339 }
1340 tstate->on_delete_data = (void *) wr;
1341 tstate->on_delete = &release_sentinel;
1342 return (PyObject *) lock;
1343}
1344
1345PyDoc_STRVAR(_set_sentinel_doc,
1346"_set_sentinel() -> lock\n\
1347\n\
1348Set a sentinel lock that will be released when the current thread\n\
1349state is finalized (after it is untied from the interpreter).\n\
1350\n\
1351This is a private API for the threading module.");
1352
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001353static PyObject *
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001354thread_stack_size(PyObject *self, PyObject *args)
1355{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001356 size_t old_size;
1357 Py_ssize_t new_size = 0;
1358 int rc;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001359
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001360 if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size))
1361 return NULL;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001362
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001363 if (new_size < 0) {
1364 PyErr_SetString(PyExc_ValueError,
1365 "size must be 0 or a positive value");
1366 return NULL;
1367 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001368
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001369 old_size = PyThread_get_stacksize();
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001370
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001371 rc = PyThread_set_stacksize((size_t) new_size);
1372 if (rc == -1) {
1373 PyErr_Format(PyExc_ValueError,
1374 "size not valid: %zd bytes",
1375 new_size);
1376 return NULL;
1377 }
1378 if (rc == -2) {
1379 PyErr_SetString(ThreadError,
1380 "setting stack size not supported");
1381 return NULL;
1382 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001383
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001384 return PyLong_FromSsize_t((Py_ssize_t) old_size);
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001385}
1386
1387PyDoc_STRVAR(stack_size_doc,
1388"stack_size([size]) -> size\n\
1389\n\
1390Return the thread stack size used when creating new threads. The\n\
1391optional size argument specifies the stack size (in bytes) to be used\n\
1392for subsequently created threads, and must be 0 (use platform or\n\
1393configured default) or a positive integer value of at least 32,768 (32k).\n\
1394If changing the thread stack size is unsupported, a ThreadError\n\
1395exception is raised. If the specified size is invalid, a ValueError\n\
1396exception is raised, and the stack size is unmodified. 32k bytes\n\
1397 currently the minimum supported stack size value to guarantee\n\
1398sufficient stack space for the interpreter itself.\n\
1399\n\
1400Note that some platforms may have particular restrictions on values for\n\
Victor Stinner8c663fd2017-11-08 14:44:44 -08001401the stack size, such as requiring a minimum stack size larger than 32 KiB or\n\
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001402requiring allocation in multiples of the system memory page size\n\
1403- platform documentation should be referred to for more information\n\
Victor Stinner8c663fd2017-11-08 14:44:44 -08001404(4 KiB pages are common; using multiples of 4096 for the stack size is\n\
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001405the suggested approach in the absence of more specific information).");
1406
Victor Stinnercd590a72019-05-28 00:39:52 +02001407static int
1408thread_excepthook_file(PyObject *file, PyObject *exc_type, PyObject *exc_value,
1409 PyObject *exc_traceback, PyObject *thread)
1410{
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001411 _Py_IDENTIFIER(name);
Victor Stinnercd590a72019-05-28 00:39:52 +02001412 /* print(f"Exception in thread {thread.name}:", file=file) */
1413 if (PyFile_WriteString("Exception in thread ", file) < 0) {
1414 return -1;
1415 }
1416
1417 PyObject *name = NULL;
1418 if (thread != Py_None) {
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001419 if (_PyObject_LookupAttrId(thread, &PyId_name, &name) < 0) {
1420 return -1;
1421 }
Victor Stinnercd590a72019-05-28 00:39:52 +02001422 }
1423 if (name != NULL) {
1424 if (PyFile_WriteObject(name, file, Py_PRINT_RAW) < 0) {
1425 Py_DECREF(name);
1426 return -1;
1427 }
1428 Py_DECREF(name);
1429 }
1430 else {
Victor Stinnercd590a72019-05-28 00:39:52 +02001431 unsigned long ident = PyThread_get_thread_ident();
1432 PyObject *str = PyUnicode_FromFormat("%lu", ident);
1433 if (str != NULL) {
1434 if (PyFile_WriteObject(str, file, Py_PRINT_RAW) < 0) {
1435 Py_DECREF(str);
1436 return -1;
1437 }
1438 Py_DECREF(str);
1439 }
1440 else {
1441 PyErr_Clear();
1442
1443 if (PyFile_WriteString("<failed to get thread name>", file) < 0) {
1444 return -1;
1445 }
1446 }
1447 }
1448
1449 if (PyFile_WriteString(":\n", file) < 0) {
1450 return -1;
1451 }
1452
1453 /* Display the traceback */
1454 _PyErr_Display(file, exc_type, exc_value, exc_traceback);
1455
1456 /* Call file.flush() */
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001457 PyObject *res = _PyObject_CallMethodIdNoArgs(file, &PyId_flush);
Victor Stinnercd590a72019-05-28 00:39:52 +02001458 if (!res) {
1459 return -1;
1460 }
1461 Py_DECREF(res);
1462
1463 return 0;
1464}
1465
1466
1467PyDoc_STRVAR(ExceptHookArgs__doc__,
1468"ExceptHookArgs\n\
1469\n\
1470Type used to pass arguments to threading.excepthook.");
1471
1472static PyTypeObject ExceptHookArgsType;
1473
1474static PyStructSequence_Field ExceptHookArgs_fields[] = {
1475 {"exc_type", "Exception type"},
1476 {"exc_value", "Exception value"},
1477 {"exc_traceback", "Exception traceback"},
1478 {"thread", "Thread"},
1479 {0}
1480};
1481
1482static PyStructSequence_Desc ExceptHookArgs_desc = {
Victor Stinner8203c732020-12-16 12:20:33 +01001483 .name = "_thread._ExceptHookArgs",
Victor Stinnercd590a72019-05-28 00:39:52 +02001484 .doc = ExceptHookArgs__doc__,
1485 .fields = ExceptHookArgs_fields,
1486 .n_in_sequence = 4
1487};
1488
1489
1490static PyObject *
1491thread_excepthook(PyObject *self, PyObject *args)
1492{
Andy Lester55728702020-03-06 16:53:17 -06001493 if (!Py_IS_TYPE(args, &ExceptHookArgsType)) {
Victor Stinnercd590a72019-05-28 00:39:52 +02001494 PyErr_SetString(PyExc_TypeError,
1495 "_thread.excepthook argument type "
1496 "must be ExceptHookArgs");
1497 return NULL;
1498 }
1499
1500 /* Borrowed reference */
1501 PyObject *exc_type = PyStructSequence_GET_ITEM(args, 0);
1502 if (exc_type == PyExc_SystemExit) {
1503 /* silently ignore SystemExit */
1504 Py_RETURN_NONE;
1505 }
1506
1507 /* Borrowed references */
1508 PyObject *exc_value = PyStructSequence_GET_ITEM(args, 1);
1509 PyObject *exc_tb = PyStructSequence_GET_ITEM(args, 2);
1510 PyObject *thread = PyStructSequence_GET_ITEM(args, 3);
1511
1512 PyObject *file = _PySys_GetObjectId(&PyId_stderr);
1513 if (file == NULL || file == Py_None) {
1514 if (thread == Py_None) {
1515 /* do nothing if sys.stderr is None and thread is None */
1516 Py_RETURN_NONE;
1517 }
1518
1519 file = PyObject_GetAttrString(thread, "_stderr");
1520 if (file == NULL) {
1521 return NULL;
1522 }
1523 if (file == Py_None) {
1524 Py_DECREF(file);
1525 /* do nothing if sys.stderr is None and sys.stderr was None
1526 when the thread was created */
1527 Py_RETURN_NONE;
1528 }
1529 }
1530 else {
1531 Py_INCREF(file);
1532 }
1533
1534 int res = thread_excepthook_file(file, exc_type, exc_value, exc_tb,
1535 thread);
1536 Py_DECREF(file);
1537 if (res < 0) {
1538 return NULL;
1539 }
1540
1541 Py_RETURN_NONE;
1542}
1543
1544PyDoc_STRVAR(excepthook_doc,
1545"excepthook(exc_type, exc_value, exc_traceback, thread)\n\
1546\n\
1547Handle uncaught Thread.run() exception.");
1548
Barry Warsawd0c10421996-12-17 00:05:22 +00001549static PyMethodDef thread_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001550 {"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread,
Victor Stinner754851f2011-04-19 23:58:51 +02001551 METH_VARARGS, start_new_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001552 {"start_new", (PyCFunction)thread_PyThread_start_new_thread,
Victor Stinner754851f2011-04-19 23:58:51 +02001553 METH_VARARGS, start_new_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301554 {"allocate_lock", thread_PyThread_allocate_lock,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001555 METH_NOARGS, allocate_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301556 {"allocate", thread_PyThread_allocate_lock,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001557 METH_NOARGS, allocate_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301558 {"exit_thread", thread_PyThread_exit_thread,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001559 METH_NOARGS, exit_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301560 {"exit", thread_PyThread_exit_thread,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001561 METH_NOARGS, exit_doc},
Antoine Pitrouba251c22021-03-11 23:35:45 +01001562 {"interrupt_main", (PyCFunction)thread_PyThread_interrupt_main,
1563 METH_VARARGS, interrupt_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301564 {"get_ident", thread_get_ident,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001565 METH_NOARGS, get_ident_doc},
Jake Teslerb121f632019-05-22 08:43:17 -07001566#ifdef PY_HAVE_THREAD_NATIVE_ID
1567 {"get_native_id", thread_get_native_id,
1568 METH_NOARGS, get_native_id_doc},
1569#endif
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301570 {"_count", thread__count,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001571 METH_NOARGS, _count_doc},
1572 {"stack_size", (PyCFunction)thread_stack_size,
Victor Stinner754851f2011-04-19 23:58:51 +02001573 METH_VARARGS, stack_size_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301574 {"_set_sentinel", thread__set_sentinel,
Antoine Pitrou7b476992013-09-07 23:38:37 +02001575 METH_NOARGS, _set_sentinel_doc},
Victor Stinnercd590a72019-05-28 00:39:52 +02001576 {"_excepthook", thread_excepthook,
1577 METH_O, excepthook_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001578 {NULL, NULL} /* sentinel */
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001579};
1580
1581
1582/* Initialization function */
1583
Victor Stinner8203c732020-12-16 12:20:33 +01001584static int
Victor Stinner61040132020-12-18 01:39:00 +01001585thread_module_exec(PyObject *module)
Victor Stinner8203c732020-12-16 12:20:33 +01001586{
Victor Stinner61040132020-12-18 01:39:00 +01001587 thread_module_state *state = get_thread_state(module);
1588 PyObject *d = PyModule_GetDict(module);
1589
Victor Stinner8203c732020-12-16 12:20:33 +01001590 // Initialize the C thread library
1591 PyThread_init_thread();
1592
Victor Stinner61040132020-12-18 01:39:00 +01001593 // Lock
1594 state->lock_type = (PyTypeObject *)PyType_FromSpec(&lock_type_spec);
1595 if (state->lock_type == NULL) {
Victor Stinner8203c732020-12-16 12:20:33 +01001596 return -1;
1597 }
Victor Stinner61040132020-12-18 01:39:00 +01001598 if (PyDict_SetItemString(d, "LockType", (PyObject *)state->lock_type) < 0) {
Victor Stinner8203c732020-12-16 12:20:33 +01001599 return -1;
1600 }
Victor Stinner61040132020-12-18 01:39:00 +01001601
1602 // RLock
1603 PyTypeObject *rlock_type = (PyTypeObject *)PyType_FromSpec(&rlock_type_spec);
1604 if (rlock_type == NULL) {
Victor Stinner8203c732020-12-16 12:20:33 +01001605 return -1;
1606 }
Victor Stinner61040132020-12-18 01:39:00 +01001607 if (PyModule_AddType(module, rlock_type) < 0) {
1608 Py_DECREF(rlock_type);
1609 return -1;
1610 }
1611 Py_DECREF(rlock_type);
1612
1613 // Local dummy
1614 state->local_dummy_type = (PyTypeObject *)PyType_FromSpec(&local_dummy_type_spec);
1615 if (state->local_dummy_type == NULL) {
1616 return -1;
1617 }
1618
1619 // Local
1620 state->local_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, &local_type_spec, NULL);
1621 if (state->local_type == NULL) {
1622 return -1;
1623 }
1624 if (PyModule_AddType(module, state->local_type) < 0) {
1625 return -1;
1626 }
1627
Victor Stinner8203c732020-12-16 12:20:33 +01001628 if (ExceptHookArgsType.tp_name == NULL) {
1629 if (PyStructSequence_InitType2(&ExceptHookArgsType,
1630 &ExceptHookArgs_desc) < 0) {
1631 return -1;
1632 }
1633 }
1634
1635 // Add module attributes
Victor Stinner8203c732020-12-16 12:20:33 +01001636 if (PyDict_SetItemString(d, "error", ThreadError) < 0) {
1637 return -1;
1638 }
Victor Stinner8203c732020-12-16 12:20:33 +01001639 if (PyModule_AddType(module, &ExceptHookArgsType) < 0) {
1640 return -1;
1641 }
1642
1643 // TIMEOUT_MAX
1644 double timeout_max = (_PyTime_t)PY_TIMEOUT_MAX * 1e-6;
1645 double time_max = _PyTime_AsSecondsDouble(_PyTime_MAX);
1646 timeout_max = Py_MIN(timeout_max, time_max);
1647 // Round towards minus infinity
1648 timeout_max = floor(timeout_max);
1649
1650 if (PyModule_AddObject(module, "TIMEOUT_MAX",
1651 PyFloat_FromDouble(timeout_max)) < 0) {
1652 return -1;
1653 }
1654
1655 return 0;
1656}
1657
1658
Victor Stinner61040132020-12-18 01:39:00 +01001659static int
1660thread_module_traverse(PyObject *module, visitproc visit, void *arg)
1661{
1662 thread_module_state *state = get_thread_state(module);
1663 Py_VISIT(state->lock_type);
1664 Py_VISIT(state->local_type);
1665 Py_VISIT(state->local_dummy_type);
1666 return 0;
1667}
1668
1669static int
1670thread_module_clear(PyObject *module)
1671{
1672 thread_module_state *state = get_thread_state(module);
1673 Py_CLEAR(state->lock_type);
1674 Py_CLEAR(state->local_type);
1675 Py_CLEAR(state->local_dummy_type);
1676 return 0;
1677}
1678
1679static void
1680thread_module_free(void *module)
1681{
1682 thread_module_clear((PyObject *)module);
1683}
1684
1685
1686
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001687PyDoc_STRVAR(thread_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001688"This module provides primitive operations to write multi-threaded programs.\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001689The 'threading' module provides a more convenient interface.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001690
Victor Stinner61040132020-12-18 01:39:00 +01001691static PyModuleDef_Slot thread_module_slots[] = {
1692 {Py_mod_exec, thread_module_exec},
1693 {0, NULL}
1694};
1695
1696static struct PyModuleDef thread_module = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001697 PyModuleDef_HEAD_INIT,
Victor Stinner8203c732020-12-16 12:20:33 +01001698 .m_name = "_thread",
1699 .m_doc = thread_doc,
Victor Stinner61040132020-12-18 01:39:00 +01001700 .m_size = sizeof(thread_module_state),
Victor Stinner8203c732020-12-16 12:20:33 +01001701 .m_methods = thread_methods,
Victor Stinner61040132020-12-18 01:39:00 +01001702 .m_traverse = thread_module_traverse,
1703 .m_clear = thread_module_clear,
1704 .m_free = thread_module_free,
1705 .m_slots = thread_module_slots,
Martin v. Löwis1a214512008-06-11 05:26:20 +00001706};
1707
Mark Hammondfe51c6d2002-08-02 02:27:13 +00001708PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00001709PyInit__thread(void)
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001710{
Victor Stinner61040132020-12-18 01:39:00 +01001711 return PyModuleDef_Init(&thread_module);
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001712}