blob: d9a71af8d5cde4258d6bf8a5b352265b80141a99 [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
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001108 PyThread_exit_thread();
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001109}
1110
Barry Warsawd0c10421996-12-17 00:05:22 +00001111static PyObject *
Peter Schneider-Kamp3707efe2000-07-10 10:03:58 +00001112thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001113{
Joannah Nanjekye2bc43cd2019-09-05 13:06:49 -03001114 _PyRuntimeState *runtime = &_PyRuntime;
Victor Stinner8203c732020-12-16 12:20:33 +01001115 PyObject *func, *args, *kwargs = NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001116
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001117 if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3,
Victor Stinner8203c732020-12-16 12:20:33 +01001118 &func, &args, &kwargs))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001119 return NULL;
1120 if (!PyCallable_Check(func)) {
1121 PyErr_SetString(PyExc_TypeError,
1122 "first arg must be callable");
1123 return NULL;
1124 }
1125 if (!PyTuple_Check(args)) {
1126 PyErr_SetString(PyExc_TypeError,
1127 "2nd arg must be a tuple");
1128 return NULL;
1129 }
Victor Stinner8203c732020-12-16 12:20:33 +01001130 if (kwargs != NULL && !PyDict_Check(kwargs)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001131 PyErr_SetString(PyExc_TypeError,
1132 "optional 3rd arg must be a dictionary");
1133 return NULL;
1134 }
Victor Stinner252346a2020-05-01 11:33:44 +02001135
1136 PyInterpreterState *interp = _PyInterpreterState_GET();
1137 if (interp->config._isolated_interpreter) {
1138 PyErr_SetString(PyExc_RuntimeError,
1139 "thread is not supported for isolated subinterpreters");
1140 return NULL;
1141 }
1142
Victor Stinner8203c732020-12-16 12:20:33 +01001143 struct bootstate *boot = PyMem_NEW(struct bootstate, 1);
1144 if (boot == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001145 return PyErr_NoMemory();
Victor Stinner8203c732020-12-16 12:20:33 +01001146 }
Victor Stinner81a7be32020-04-14 15:14:01 +02001147 boot->interp = _PyInterpreterState_GET();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001148 boot->tstate = _PyThreadState_Prealloc(boot->interp);
1149 if (boot->tstate == NULL) {
Victor Stinner00d7abd2020-12-01 09:56:42 +01001150 PyMem_Free(boot);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001151 return PyErr_NoMemory();
1152 }
Victor Stinner8203c732020-12-16 12:20:33 +01001153 boot->runtime = runtime;
1154 boot->func = Py_NewRef(func);
1155 boot->args = Py_NewRef(args);
1156 boot->kwargs = Py_XNewRef(kwargs);
Victor Stinner3225b9f2020-03-09 20:56:57 +01001157
Victor Stinner8203c732020-12-16 12:20:33 +01001158 unsigned long ident = PyThread_start_new_thread(thread_run, (void*) boot);
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001159 if (ident == PYTHREAD_INVALID_THREAD_ID) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001160 PyErr_SetString(ThreadError, "can't start new thread");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001161 PyThreadState_Clear(boot->tstate);
Victor Stinner8203c732020-12-16 12:20:33 +01001162 thread_bootstate_free(boot);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001163 return NULL;
1164 }
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001165 return PyLong_FromUnsignedLong(ident);
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001166}
1167
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001168PyDoc_STRVAR(start_new_doc,
Andrew M. Kuchling38300c62001-10-05 12:24:15 +00001169"start_new_thread(function, args[, kwargs])\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001170(start_new() is an obsolete synonym)\n\
1171\n\
Guido van Rossum3c288632001-10-16 21:13:49 +00001172Start a new thread and return its identifier. The thread will call the\n\
1173function with positional arguments from the tuple args and keyword arguments\n\
1174taken from the optional dictionary kwargs. The thread exits when the\n\
1175function returns; the return value is ignored. The thread will also exit\n\
1176when the function raises an unhandled exception; a stack trace will be\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001177printed unless the exception is SystemExit.\n");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001178
Barry Warsawd0c10421996-12-17 00:05:22 +00001179static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301180thread_PyThread_exit_thread(PyObject *self, PyObject *Py_UNUSED(ignored))
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001181{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001182 PyErr_SetNone(PyExc_SystemExit);
1183 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001184}
1185
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001186PyDoc_STRVAR(exit_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001187"exit()\n\
Éric Araujo9bcf8bf2011-05-31 14:08:26 +02001188(exit_thread() is an obsolete synonym)\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001189\n\
1190This is synonymous to ``raise SystemExit''. It will cause the current\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001191thread to exit silently unless the exception is caught.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001192
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001193static PyObject *
Antoine Pitrouba251c22021-03-11 23:35:45 +01001194thread_PyThread_interrupt_main(PyObject *self, PyObject *args)
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001195{
Antoine Pitrouba251c22021-03-11 23:35:45 +01001196 int signum = SIGINT;
1197 if (!PyArg_ParseTuple(args, "|i:signum", &signum)) {
1198 return NULL;
1199 }
1200
1201 if (PyErr_SetInterruptEx(signum)) {
1202 PyErr_SetString(PyExc_ValueError, "signal number out of range");
1203 return NULL;
1204 }
Serhiy Storchaka228b12e2017-01-23 09:47:21 +02001205 Py_RETURN_NONE;
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001206}
1207
1208PyDoc_STRVAR(interrupt_doc,
Antoine Pitrouba251c22021-03-11 23:35:45 +01001209"interrupt_main(signum=signal.SIGINT, /)\n\
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001210\n\
Antoine Pitrouba251c22021-03-11 23:35:45 +01001211Simulate the arrival of the given signal in the main thread,\n\
1212where the corresponding signal handler will be executed.\n\
1213If *signum* is omitted, SIGINT is assumed.\n\
1214A subthread can use this function to interrupt the main thread.\n\
1215\n\
1216Note: the default signal hander for SIGINT raises ``KeyboardInterrupt``."
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001217);
1218
Victor Stinner61040132020-12-18 01:39:00 +01001219static lockobject *newlockobject(PyObject *module);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001220
Barry Warsawd0c10421996-12-17 00:05:22 +00001221static PyObject *
Victor Stinner8203c732020-12-16 12:20:33 +01001222thread_PyThread_allocate_lock(PyObject *module, PyObject *Py_UNUSED(ignored))
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001223{
Victor Stinner61040132020-12-18 01:39:00 +01001224 return (PyObject *) newlockobject(module);
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001225}
1226
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001227PyDoc_STRVAR(allocate_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001228"allocate_lock() -> lock object\n\
1229(allocate() is an obsolete synonym)\n\
1230\n\
Berker Peksag720e6552016-05-02 12:25:35 +03001231Create a new lock object. See help(type(threading.Lock())) for\n\
1232information about locks.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001233
Barry Warsawd0c10421996-12-17 00:05:22 +00001234static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301235thread_get_ident(PyObject *self, PyObject *Py_UNUSED(ignored))
Guido van Rossumb6775db1994-08-01 11:34:53 +00001236{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001237 unsigned long ident = PyThread_get_thread_ident();
1238 if (ident == PYTHREAD_INVALID_THREAD_ID) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001239 PyErr_SetString(ThreadError, "no current thread ident");
1240 return NULL;
1241 }
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001242 return PyLong_FromUnsignedLong(ident);
Guido van Rossumb6775db1994-08-01 11:34:53 +00001243}
1244
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001245PyDoc_STRVAR(get_ident_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001246"get_ident() -> integer\n\
1247\n\
1248Return a non-zero integer that uniquely identifies the current thread\n\
1249amongst other threads that exist simultaneously.\n\
1250This may be used to identify per-thread resources.\n\
1251Even though on some platforms threads identities may appear to be\n\
1252allocated consecutive numbers starting at 1, this behavior should not\n\
1253be relied upon, and the number should be seen purely as a magic cookie.\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001254A thread's identity may be reused for another thread after it exits.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001255
Jake Teslerb121f632019-05-22 08:43:17 -07001256#ifdef PY_HAVE_THREAD_NATIVE_ID
1257static PyObject *
1258thread_get_native_id(PyObject *self, PyObject *Py_UNUSED(ignored))
1259{
1260 unsigned long native_id = PyThread_get_thread_native_id();
1261 return PyLong_FromUnsignedLong(native_id);
1262}
1263
1264PyDoc_STRVAR(get_native_id_doc,
1265"get_native_id() -> integer\n\
1266\n\
1267Return a non-negative integer identifying the thread as reported\n\
1268by the OS (kernel). This may be used to uniquely identify a\n\
1269particular thread within a system.");
1270#endif
1271
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001272static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301273thread__count(PyObject *self, PyObject *Py_UNUSED(ignored))
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001274{
Victor Stinner81a7be32020-04-14 15:14:01 +02001275 PyInterpreterState *interp = _PyInterpreterState_GET();
Victor Stinnercaba55b2018-08-03 15:33:52 +02001276 return PyLong_FromLong(interp->num_threads);
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001277}
1278
1279PyDoc_STRVAR(_count_doc,
1280"_count() -> integer\n\
1281\n\
Antoine Pitrou9257f5e2009-10-30 22:23:02 +00001282\
oldkaa0735f2018-02-02 16:52:55 +08001283Return the number of currently running Python threads, excluding\n\
Antoine Pitrou9257f5e2009-10-30 22:23:02 +00001284the main thread. The returned number comprises all threads created\n\
1285through `start_new_thread()` as well as `threading.Thread`, and not\n\
1286yet finished.\n\
1287\n\
1288This function is meant for internal and specialized purposes only.\n\
1289In most applications `threading.enumerate()` should be used instead.");
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001290
Antoine Pitrou7b476992013-09-07 23:38:37 +02001291static void
Victor Stinnera42de742018-11-22 10:25:22 +01001292release_sentinel(void *wr_raw)
Antoine Pitrou7b476992013-09-07 23:38:37 +02001293{
Victor Stinnera42de742018-11-22 10:25:22 +01001294 PyObject *wr = _PyObject_CAST(wr_raw);
Antoine Pitrou7b476992013-09-07 23:38:37 +02001295 /* Tricky: this function is called when the current thread state
1296 is being deleted. Therefore, only simple C code can safely
1297 execute here. */
1298 PyObject *obj = PyWeakref_GET_OBJECT(wr);
1299 lockobject *lock;
1300 if (obj != Py_None) {
Antoine Pitrou7b476992013-09-07 23:38:37 +02001301 lock = (lockobject *) obj;
1302 if (lock->locked) {
1303 PyThread_release_lock(lock->lock_lock);
1304 lock->locked = 0;
1305 }
1306 }
1307 /* Deallocating a weakref with a NULL callback only calls
1308 PyObject_GC_Del(), which can't call any Python code. */
1309 Py_DECREF(wr);
1310}
1311
1312static PyObject *
Victor Stinner8203c732020-12-16 12:20:33 +01001313thread__set_sentinel(PyObject *module, PyObject *Py_UNUSED(ignored))
Antoine Pitrou7b476992013-09-07 23:38:37 +02001314{
1315 PyObject *wr;
1316 PyThreadState *tstate = PyThreadState_Get();
1317 lockobject *lock;
1318
1319 if (tstate->on_delete_data != NULL) {
1320 /* We must support the re-creation of the lock from a
1321 fork()ed child. */
1322 assert(tstate->on_delete == &release_sentinel);
1323 wr = (PyObject *) tstate->on_delete_data;
1324 tstate->on_delete = NULL;
1325 tstate->on_delete_data = NULL;
1326 Py_DECREF(wr);
1327 }
Victor Stinner61040132020-12-18 01:39:00 +01001328 lock = newlockobject(module);
Antoine Pitrou7b476992013-09-07 23:38:37 +02001329 if (lock == NULL)
1330 return NULL;
1331 /* The lock is owned by whoever called _set_sentinel(), but the weakref
1332 hangs to the thread state. */
1333 wr = PyWeakref_NewRef((PyObject *) lock, NULL);
1334 if (wr == NULL) {
1335 Py_DECREF(lock);
1336 return NULL;
1337 }
1338 tstate->on_delete_data = (void *) wr;
1339 tstate->on_delete = &release_sentinel;
1340 return (PyObject *) lock;
1341}
1342
1343PyDoc_STRVAR(_set_sentinel_doc,
1344"_set_sentinel() -> lock\n\
1345\n\
1346Set a sentinel lock that will be released when the current thread\n\
1347state is finalized (after it is untied from the interpreter).\n\
1348\n\
1349This is a private API for the threading module.");
1350
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001351static PyObject *
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001352thread_stack_size(PyObject *self, PyObject *args)
1353{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001354 size_t old_size;
1355 Py_ssize_t new_size = 0;
1356 int rc;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001357
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001358 if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size))
1359 return NULL;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001360
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001361 if (new_size < 0) {
1362 PyErr_SetString(PyExc_ValueError,
1363 "size must be 0 or a positive value");
1364 return NULL;
1365 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001366
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001367 old_size = PyThread_get_stacksize();
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001368
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001369 rc = PyThread_set_stacksize((size_t) new_size);
1370 if (rc == -1) {
1371 PyErr_Format(PyExc_ValueError,
1372 "size not valid: %zd bytes",
1373 new_size);
1374 return NULL;
1375 }
1376 if (rc == -2) {
1377 PyErr_SetString(ThreadError,
1378 "setting stack size not supported");
1379 return NULL;
1380 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001381
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001382 return PyLong_FromSsize_t((Py_ssize_t) old_size);
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001383}
1384
1385PyDoc_STRVAR(stack_size_doc,
1386"stack_size([size]) -> size\n\
1387\n\
1388Return the thread stack size used when creating new threads. The\n\
1389optional size argument specifies the stack size (in bytes) to be used\n\
1390for subsequently created threads, and must be 0 (use platform or\n\
1391configured default) or a positive integer value of at least 32,768 (32k).\n\
1392If changing the thread stack size is unsupported, a ThreadError\n\
1393exception is raised. If the specified size is invalid, a ValueError\n\
1394exception is raised, and the stack size is unmodified. 32k bytes\n\
1395 currently the minimum supported stack size value to guarantee\n\
1396sufficient stack space for the interpreter itself.\n\
1397\n\
1398Note that some platforms may have particular restrictions on values for\n\
Victor Stinner8c663fd2017-11-08 14:44:44 -08001399the stack size, such as requiring a minimum stack size larger than 32 KiB or\n\
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001400requiring allocation in multiples of the system memory page size\n\
1401- platform documentation should be referred to for more information\n\
Victor Stinner8c663fd2017-11-08 14:44:44 -08001402(4 KiB pages are common; using multiples of 4096 for the stack size is\n\
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001403the suggested approach in the absence of more specific information).");
1404
Victor Stinnercd590a72019-05-28 00:39:52 +02001405static int
1406thread_excepthook_file(PyObject *file, PyObject *exc_type, PyObject *exc_value,
1407 PyObject *exc_traceback, PyObject *thread)
1408{
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001409 _Py_IDENTIFIER(name);
Victor Stinnercd590a72019-05-28 00:39:52 +02001410 /* print(f"Exception in thread {thread.name}:", file=file) */
1411 if (PyFile_WriteString("Exception in thread ", file) < 0) {
1412 return -1;
1413 }
1414
1415 PyObject *name = NULL;
1416 if (thread != Py_None) {
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001417 if (_PyObject_LookupAttrId(thread, &PyId_name, &name) < 0) {
1418 return -1;
1419 }
Victor Stinnercd590a72019-05-28 00:39:52 +02001420 }
1421 if (name != NULL) {
1422 if (PyFile_WriteObject(name, file, Py_PRINT_RAW) < 0) {
1423 Py_DECREF(name);
1424 return -1;
1425 }
1426 Py_DECREF(name);
1427 }
1428 else {
Victor Stinnercd590a72019-05-28 00:39:52 +02001429 unsigned long ident = PyThread_get_thread_ident();
1430 PyObject *str = PyUnicode_FromFormat("%lu", ident);
1431 if (str != NULL) {
1432 if (PyFile_WriteObject(str, file, Py_PRINT_RAW) < 0) {
1433 Py_DECREF(str);
1434 return -1;
1435 }
1436 Py_DECREF(str);
1437 }
1438 else {
1439 PyErr_Clear();
1440
1441 if (PyFile_WriteString("<failed to get thread name>", file) < 0) {
1442 return -1;
1443 }
1444 }
1445 }
1446
1447 if (PyFile_WriteString(":\n", file) < 0) {
1448 return -1;
1449 }
1450
1451 /* Display the traceback */
1452 _PyErr_Display(file, exc_type, exc_value, exc_traceback);
1453
1454 /* Call file.flush() */
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001455 PyObject *res = _PyObject_CallMethodIdNoArgs(file, &PyId_flush);
Victor Stinnercd590a72019-05-28 00:39:52 +02001456 if (!res) {
1457 return -1;
1458 }
1459 Py_DECREF(res);
1460
1461 return 0;
1462}
1463
1464
1465PyDoc_STRVAR(ExceptHookArgs__doc__,
1466"ExceptHookArgs\n\
1467\n\
1468Type used to pass arguments to threading.excepthook.");
1469
1470static PyTypeObject ExceptHookArgsType;
1471
1472static PyStructSequence_Field ExceptHookArgs_fields[] = {
1473 {"exc_type", "Exception type"},
1474 {"exc_value", "Exception value"},
1475 {"exc_traceback", "Exception traceback"},
1476 {"thread", "Thread"},
1477 {0}
1478};
1479
1480static PyStructSequence_Desc ExceptHookArgs_desc = {
Victor Stinner8203c732020-12-16 12:20:33 +01001481 .name = "_thread._ExceptHookArgs",
Victor Stinnercd590a72019-05-28 00:39:52 +02001482 .doc = ExceptHookArgs__doc__,
1483 .fields = ExceptHookArgs_fields,
1484 .n_in_sequence = 4
1485};
1486
1487
1488static PyObject *
1489thread_excepthook(PyObject *self, PyObject *args)
1490{
Andy Lester55728702020-03-06 16:53:17 -06001491 if (!Py_IS_TYPE(args, &ExceptHookArgsType)) {
Victor Stinnercd590a72019-05-28 00:39:52 +02001492 PyErr_SetString(PyExc_TypeError,
1493 "_thread.excepthook argument type "
1494 "must be ExceptHookArgs");
1495 return NULL;
1496 }
1497
1498 /* Borrowed reference */
1499 PyObject *exc_type = PyStructSequence_GET_ITEM(args, 0);
1500 if (exc_type == PyExc_SystemExit) {
1501 /* silently ignore SystemExit */
1502 Py_RETURN_NONE;
1503 }
1504
1505 /* Borrowed references */
1506 PyObject *exc_value = PyStructSequence_GET_ITEM(args, 1);
1507 PyObject *exc_tb = PyStructSequence_GET_ITEM(args, 2);
1508 PyObject *thread = PyStructSequence_GET_ITEM(args, 3);
1509
1510 PyObject *file = _PySys_GetObjectId(&PyId_stderr);
1511 if (file == NULL || file == Py_None) {
1512 if (thread == Py_None) {
1513 /* do nothing if sys.stderr is None and thread is None */
1514 Py_RETURN_NONE;
1515 }
1516
1517 file = PyObject_GetAttrString(thread, "_stderr");
1518 if (file == NULL) {
1519 return NULL;
1520 }
1521 if (file == Py_None) {
1522 Py_DECREF(file);
1523 /* do nothing if sys.stderr is None and sys.stderr was None
1524 when the thread was created */
1525 Py_RETURN_NONE;
1526 }
1527 }
1528 else {
1529 Py_INCREF(file);
1530 }
1531
1532 int res = thread_excepthook_file(file, exc_type, exc_value, exc_tb,
1533 thread);
1534 Py_DECREF(file);
1535 if (res < 0) {
1536 return NULL;
1537 }
1538
1539 Py_RETURN_NONE;
1540}
1541
1542PyDoc_STRVAR(excepthook_doc,
1543"excepthook(exc_type, exc_value, exc_traceback, thread)\n\
1544\n\
1545Handle uncaught Thread.run() exception.");
1546
Barry Warsawd0c10421996-12-17 00:05:22 +00001547static PyMethodDef thread_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001548 {"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread,
Victor Stinner754851f2011-04-19 23:58:51 +02001549 METH_VARARGS, start_new_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001550 {"start_new", (PyCFunction)thread_PyThread_start_new_thread,
Victor Stinner754851f2011-04-19 23:58:51 +02001551 METH_VARARGS, start_new_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301552 {"allocate_lock", thread_PyThread_allocate_lock,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001553 METH_NOARGS, allocate_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301554 {"allocate", thread_PyThread_allocate_lock,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001555 METH_NOARGS, allocate_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301556 {"exit_thread", thread_PyThread_exit_thread,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001557 METH_NOARGS, exit_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301558 {"exit", thread_PyThread_exit_thread,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001559 METH_NOARGS, exit_doc},
Antoine Pitrouba251c22021-03-11 23:35:45 +01001560 {"interrupt_main", (PyCFunction)thread_PyThread_interrupt_main,
1561 METH_VARARGS, interrupt_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301562 {"get_ident", thread_get_ident,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001563 METH_NOARGS, get_ident_doc},
Jake Teslerb121f632019-05-22 08:43:17 -07001564#ifdef PY_HAVE_THREAD_NATIVE_ID
1565 {"get_native_id", thread_get_native_id,
1566 METH_NOARGS, get_native_id_doc},
1567#endif
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301568 {"_count", thread__count,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001569 METH_NOARGS, _count_doc},
1570 {"stack_size", (PyCFunction)thread_stack_size,
Victor Stinner754851f2011-04-19 23:58:51 +02001571 METH_VARARGS, stack_size_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301572 {"_set_sentinel", thread__set_sentinel,
Antoine Pitrou7b476992013-09-07 23:38:37 +02001573 METH_NOARGS, _set_sentinel_doc},
Victor Stinnercd590a72019-05-28 00:39:52 +02001574 {"_excepthook", thread_excepthook,
1575 METH_O, excepthook_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001576 {NULL, NULL} /* sentinel */
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001577};
1578
1579
1580/* Initialization function */
1581
Victor Stinner8203c732020-12-16 12:20:33 +01001582static int
Victor Stinner61040132020-12-18 01:39:00 +01001583thread_module_exec(PyObject *module)
Victor Stinner8203c732020-12-16 12:20:33 +01001584{
Victor Stinner61040132020-12-18 01:39:00 +01001585 thread_module_state *state = get_thread_state(module);
1586 PyObject *d = PyModule_GetDict(module);
1587
Victor Stinner8203c732020-12-16 12:20:33 +01001588 // Initialize the C thread library
1589 PyThread_init_thread();
1590
Victor Stinner61040132020-12-18 01:39:00 +01001591 // Lock
1592 state->lock_type = (PyTypeObject *)PyType_FromSpec(&lock_type_spec);
1593 if (state->lock_type == NULL) {
Victor Stinner8203c732020-12-16 12:20:33 +01001594 return -1;
1595 }
Victor Stinner61040132020-12-18 01:39:00 +01001596 if (PyDict_SetItemString(d, "LockType", (PyObject *)state->lock_type) < 0) {
Victor Stinner8203c732020-12-16 12:20:33 +01001597 return -1;
1598 }
Victor Stinner61040132020-12-18 01:39:00 +01001599
1600 // RLock
1601 PyTypeObject *rlock_type = (PyTypeObject *)PyType_FromSpec(&rlock_type_spec);
1602 if (rlock_type == NULL) {
Victor Stinner8203c732020-12-16 12:20:33 +01001603 return -1;
1604 }
Victor Stinner61040132020-12-18 01:39:00 +01001605 if (PyModule_AddType(module, rlock_type) < 0) {
1606 Py_DECREF(rlock_type);
1607 return -1;
1608 }
1609 Py_DECREF(rlock_type);
1610
1611 // Local dummy
1612 state->local_dummy_type = (PyTypeObject *)PyType_FromSpec(&local_dummy_type_spec);
1613 if (state->local_dummy_type == NULL) {
1614 return -1;
1615 }
1616
1617 // Local
1618 state->local_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, &local_type_spec, NULL);
1619 if (state->local_type == NULL) {
1620 return -1;
1621 }
1622 if (PyModule_AddType(module, state->local_type) < 0) {
1623 return -1;
1624 }
1625
Victor Stinner8203c732020-12-16 12:20:33 +01001626 if (ExceptHookArgsType.tp_name == NULL) {
1627 if (PyStructSequence_InitType2(&ExceptHookArgsType,
1628 &ExceptHookArgs_desc) < 0) {
1629 return -1;
1630 }
1631 }
1632
1633 // Add module attributes
Victor Stinner8203c732020-12-16 12:20:33 +01001634 if (PyDict_SetItemString(d, "error", ThreadError) < 0) {
1635 return -1;
1636 }
Victor Stinner8203c732020-12-16 12:20:33 +01001637 if (PyModule_AddType(module, &ExceptHookArgsType) < 0) {
1638 return -1;
1639 }
1640
1641 // TIMEOUT_MAX
1642 double timeout_max = (_PyTime_t)PY_TIMEOUT_MAX * 1e-6;
1643 double time_max = _PyTime_AsSecondsDouble(_PyTime_MAX);
1644 timeout_max = Py_MIN(timeout_max, time_max);
1645 // Round towards minus infinity
1646 timeout_max = floor(timeout_max);
1647
1648 if (PyModule_AddObject(module, "TIMEOUT_MAX",
1649 PyFloat_FromDouble(timeout_max)) < 0) {
1650 return -1;
1651 }
1652
1653 return 0;
1654}
1655
1656
Victor Stinner61040132020-12-18 01:39:00 +01001657static int
1658thread_module_traverse(PyObject *module, visitproc visit, void *arg)
1659{
1660 thread_module_state *state = get_thread_state(module);
1661 Py_VISIT(state->lock_type);
1662 Py_VISIT(state->local_type);
1663 Py_VISIT(state->local_dummy_type);
1664 return 0;
1665}
1666
1667static int
1668thread_module_clear(PyObject *module)
1669{
1670 thread_module_state *state = get_thread_state(module);
1671 Py_CLEAR(state->lock_type);
1672 Py_CLEAR(state->local_type);
1673 Py_CLEAR(state->local_dummy_type);
1674 return 0;
1675}
1676
1677static void
1678thread_module_free(void *module)
1679{
1680 thread_module_clear((PyObject *)module);
1681}
1682
1683
1684
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001685PyDoc_STRVAR(thread_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001686"This module provides primitive operations to write multi-threaded programs.\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001687The 'threading' module provides a more convenient interface.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001688
Victor Stinner61040132020-12-18 01:39:00 +01001689static PyModuleDef_Slot thread_module_slots[] = {
1690 {Py_mod_exec, thread_module_exec},
1691 {0, NULL}
1692};
1693
1694static struct PyModuleDef thread_module = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001695 PyModuleDef_HEAD_INIT,
Victor Stinner8203c732020-12-16 12:20:33 +01001696 .m_name = "_thread",
1697 .m_doc = thread_doc,
Victor Stinner61040132020-12-18 01:39:00 +01001698 .m_size = sizeof(thread_module_state),
Victor Stinner8203c732020-12-16 12:20:33 +01001699 .m_methods = thread_methods,
Victor Stinner61040132020-12-18 01:39:00 +01001700 .m_traverse = thread_module_traverse,
1701 .m_clear = thread_module_clear,
1702 .m_free = thread_module_free,
1703 .m_slots = thread_module_slots,
Martin v. Löwis1a214512008-06-11 05:26:20 +00001704};
1705
Mark Hammondfe51c6d2002-08-02 02:27:13 +00001706PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00001707PyInit__thread(void)
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001708{
Victor Stinner61040132020-12-18 01:39:00 +01001709 return PyModuleDef_Init(&thread_module);
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001710}