blob: 5a2001c8fbf268572f5c61942085bdd3d769ceb4 [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 |
316 Py_TPFLAGS_DISALLOW_INSTANTIATION),
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)e30fe272021-06-15 06:29:44 -0700597 .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
Victor Stinner61040132020-12-18 01:39:00 +0100598 .slots = rlock_type_slots,
Antoine Pitrou434736a2009-11-10 18:46:01 +0000599};
600
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000601static lockobject *
Victor Stinner61040132020-12-18 01:39:00 +0100602newlockobject(PyObject *module)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000603{
Victor Stinner61040132020-12-18 01:39:00 +0100604 thread_module_state *state = get_thread_state(module);
605
606 PyTypeObject *type = state->lock_type;
607 lockobject *self = (lockobject *)type->tp_alloc(type, 0);
Victor Stinner8203c732020-12-16 12:20:33 +0100608 if (self == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000609 return NULL;
Victor Stinner8203c732020-12-16 12:20:33 +0100610 }
611
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000612 self->lock_lock = PyThread_allocate_lock();
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +0000613 self->locked = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000614 self->in_weakreflist = NULL;
Victor Stinner8203c732020-12-16 12:20:33 +0100615
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000616 if (self->lock_lock == NULL) {
617 Py_DECREF(self);
618 PyErr_SetString(ThreadError, "can't allocate lock");
619 return NULL;
620 }
621 return self;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000622}
623
Jim Fultond15dc062004-07-14 19:11:50 +0000624/* Thread-local objects */
625
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000626/* Quick overview:
627
628 We need to be able to reclaim reference cycles as soon as possible
629 (both when a thread is being terminated, or a thread-local object
630 becomes unreachable from user data). Constraints:
631 - it must not be possible for thread-state dicts to be involved in
632 reference cycles (otherwise the cyclic GC will refuse to consider
633 objects referenced from a reachable thread-state dict, even though
634 local_dealloc would clear them)
635 - the death of a thread-state dict must still imply destruction of the
636 corresponding local dicts in all thread-local objects.
637
638 Our implementation uses small "localdummy" objects in order to break
639 the reference chain. These trivial objects are hashable (using the
640 default scheme of identity hashing) and weakrefable.
641 Each thread-state holds a separate localdummy for each local object
642 (as a /strong reference/),
643 and each thread-local object holds a dict mapping /weak references/
644 of localdummies to local dicts.
645
646 Therefore:
647 - only the thread-state dict holds a strong reference to the dummies
648 - only the thread-local object holds a strong reference to the local dicts
649 - only outside objects (application- or library-level) hold strong
650 references to the thread-local objects
651 - as soon as a thread-state dict is destroyed, the weakref callbacks of all
652 dummies attached to that thread are called, and destroy the corresponding
653 local dicts from thread-local objects
654 - as soon as a thread-local object is destroyed, its local dicts are
655 destroyed and its dummies are manually removed from all thread states
656 - the GC can do its work correctly when a thread-local object is dangling,
657 without any interference from the thread-state dicts
658
659 As an additional optimization, each localdummy holds a borrowed reference
660 to the corresponding localdict. This borrowed reference is only used
661 by the thread-local object which has created the localdummy, which should
662 guarantee that the localdict still exists when accessed.
663*/
664
665typedef struct {
666 PyObject_HEAD
667 PyObject *localdict; /* Borrowed reference! */
668 PyObject *weakreflist; /* List of weak references to self */
669} localdummyobject;
670
671static void
672localdummy_dealloc(localdummyobject *self)
673{
674 if (self->weakreflist != NULL)
675 PyObject_ClearWeakRefs((PyObject *) self);
Victor Stinner61040132020-12-18 01:39:00 +0100676 PyTypeObject *tp = Py_TYPE(self);
677 tp->tp_free((PyObject*)self);
678 Py_DECREF(tp);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000679}
680
Victor Stinner61040132020-12-18 01:39:00 +0100681static PyMemberDef local_dummy_type_members[] = {
682 {"__weaklistoffset__", T_PYSSIZET, offsetof(localdummyobject, weakreflist), READONLY},
683 {NULL},
684};
685
686static PyType_Slot local_dummy_type_slots[] = {
687 {Py_tp_dealloc, (destructor)localdummy_dealloc},
688 {Py_tp_doc, "Thread-local dummy"},
689 {Py_tp_members, local_dummy_type_members},
690 {0, 0}
691};
692
693static PyType_Spec local_dummy_type_spec = {
694 .name = "_thread._localdummy",
695 .basicsize = sizeof(localdummyobject),
Erlend Egeberg Aasland9746cda2021-04-30 16:04:57 +0200696 .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
Victor Stinner61040132020-12-18 01:39:00 +0100697 .slots = local_dummy_type_slots,
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000698};
699
700
Jim Fultond15dc062004-07-14 19:11:50 +0000701typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000702 PyObject_HEAD
703 PyObject *key;
704 PyObject *args;
705 PyObject *kw;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000706 PyObject *weakreflist; /* List of weak references to self */
707 /* A {localdummy weakref -> localdict} dict */
708 PyObject *dummies;
709 /* The callback for weakrefs to localdummies */
710 PyObject *wr_callback;
Jim Fultond15dc062004-07-14 19:11:50 +0000711} localobject;
712
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000713/* Forward declaration */
Victor Stinner61040132020-12-18 01:39:00 +0100714static PyObject *_ldict(localobject *self, thread_module_state *state);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000715static PyObject *_localdummy_destroyed(PyObject *meth_self, PyObject *dummyweakref);
716
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000717/* Create and register the dummy for the current thread.
718 Returns a borrowed reference of the corresponding local dict */
719static PyObject *
Victor Stinner61040132020-12-18 01:39:00 +0100720_local_create_dummy(localobject *self, thread_module_state *state)
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000721{
Victor Stinner8203c732020-12-16 12:20:33 +0100722 PyObject *ldict = NULL, *wr = NULL;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000723 localdummyobject *dummy = NULL;
Victor Stinner61040132020-12-18 01:39:00 +0100724 PyTypeObject *type = state->local_dummy_type;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000725
Victor Stinner8203c732020-12-16 12:20:33 +0100726 PyObject *tdict = PyThreadState_GetDict();
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000727 if (tdict == NULL) {
728 PyErr_SetString(PyExc_SystemError,
729 "Couldn't get thread-state dictionary");
730 goto err;
731 }
732
733 ldict = PyDict_New();
Victor Stinner8203c732020-12-16 12:20:33 +0100734 if (ldict == NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000735 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100736 }
Victor Stinner61040132020-12-18 01:39:00 +0100737 dummy = (localdummyobject *) type->tp_alloc(type, 0);
Victor Stinner8203c732020-12-16 12:20:33 +0100738 if (dummy == NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000739 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100740 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000741 dummy->localdict = ldict;
742 wr = PyWeakref_NewRef((PyObject *) dummy, self->wr_callback);
Victor Stinner8203c732020-12-16 12:20:33 +0100743 if (wr == NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000744 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100745 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000746
747 /* As a side-effect, this will cache the weakref's hash before the
748 dummy gets deleted */
Victor Stinner8203c732020-12-16 12:20:33 +0100749 int r = PyDict_SetItem(self->dummies, wr, ldict);
750 if (r < 0) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000751 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100752 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000753 Py_CLEAR(wr);
754 r = PyDict_SetItem(tdict, self->key, (PyObject *) dummy);
Victor Stinner8203c732020-12-16 12:20:33 +0100755 if (r < 0) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000756 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100757 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000758 Py_CLEAR(dummy);
759
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000760 Py_DECREF(ldict);
761 return ldict;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000762
763err:
764 Py_XDECREF(ldict);
765 Py_XDECREF(wr);
766 Py_XDECREF(dummy);
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000767 return NULL;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000768}
769
Jim Fultond15dc062004-07-14 19:11:50 +0000770static PyObject *
771local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
772{
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000773 static PyMethodDef wr_callback_def = {
774 "_localdummy_destroyed", (PyCFunction) _localdummy_destroyed, METH_O
775 };
Jim Fultond15dc062004-07-14 19:11:50 +0000776
Serhiy Storchakafa494fd2015-05-30 17:45:22 +0300777 if (type->tp_init == PyBaseObject_Type.tp_init) {
778 int rc = 0;
779 if (args != NULL)
780 rc = PyObject_IsTrue(args);
781 if (rc == 0 && kw != NULL)
782 rc = PyObject_IsTrue(kw);
783 if (rc != 0) {
Victor Stinner8203c732020-12-16 12:20:33 +0100784 if (rc > 0) {
Serhiy Storchakafa494fd2015-05-30 17:45:22 +0300785 PyErr_SetString(PyExc_TypeError,
786 "Initialization arguments are not supported");
Victor Stinner8203c732020-12-16 12:20:33 +0100787 }
Serhiy Storchakafa494fd2015-05-30 17:45:22 +0300788 return NULL;
789 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000790 }
Jim Fultond15dc062004-07-14 19:11:50 +0000791
Victor Stinner61040132020-12-18 01:39:00 +0100792 PyObject *module = _PyType_GetModuleByDef(type, &thread_module);
793 thread_module_state *state = get_thread_state(module);
794
795 localobject *self = (localobject *)type->tp_alloc(type, 0);
Victor Stinner8203c732020-12-16 12:20:33 +0100796 if (self == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000797 return NULL;
Victor Stinner8203c732020-12-16 12:20:33 +0100798 }
Jim Fultond15dc062004-07-14 19:11:50 +0000799
Victor Stinner8203c732020-12-16 12:20:33 +0100800 self->args = Py_XNewRef(args);
801 self->kw = Py_XNewRef(kw);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000802 self->key = PyUnicode_FromFormat("thread.local.%p", self);
Victor Stinner8203c732020-12-16 12:20:33 +0100803 if (self->key == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000804 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100805 }
Jim Fultond15dc062004-07-14 19:11:50 +0000806
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000807 self->dummies = PyDict_New();
Victor Stinner8203c732020-12-16 12:20:33 +0100808 if (self->dummies == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000809 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100810 }
Jim Fultond15dc062004-07-14 19:11:50 +0000811
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000812 /* We use a weak reference to self in the callback closure
813 in order to avoid spurious reference cycles */
Victor Stinner8203c732020-12-16 12:20:33 +0100814 PyObject *wr = PyWeakref_NewRef((PyObject *) self, NULL);
815 if (wr == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000816 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100817 }
Andrew Svetlov3ba3a3e2012-12-25 13:32:35 +0200818 self->wr_callback = PyCFunction_NewEx(&wr_callback_def, wr, NULL);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000819 Py_DECREF(wr);
Victor Stinner8203c732020-12-16 12:20:33 +0100820 if (self->wr_callback == NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000821 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100822 }
Victor Stinner61040132020-12-18 01:39:00 +0100823 if (_local_create_dummy(self, state) == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000824 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100825 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000826 return (PyObject *)self;
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000827
828 err:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000829 Py_DECREF(self);
830 return NULL;
Jim Fultond15dc062004-07-14 19:11:50 +0000831}
832
833static int
834local_traverse(localobject *self, visitproc visit, void *arg)
835{
Victor Stinner61040132020-12-18 01:39:00 +0100836 Py_VISIT(Py_TYPE(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000837 Py_VISIT(self->args);
838 Py_VISIT(self->kw);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000839 Py_VISIT(self->dummies);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000840 return 0;
Jim Fultond15dc062004-07-14 19:11:50 +0000841}
842
843static int
844local_clear(localobject *self)
845{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000846 Py_CLEAR(self->args);
847 Py_CLEAR(self->kw);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000848 Py_CLEAR(self->dummies);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000849 Py_CLEAR(self->wr_callback);
850 /* Remove all strong references to dummies from the thread states */
Victor Stinner839184f2021-02-19 15:51:36 +0100851 if (self->key) {
852 PyInterpreterState *interp = _PyInterpreterState_GET();
853 PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
854 for(; tstate; tstate = PyThreadState_Next(tstate)) {
855 if (tstate->dict == NULL) {
856 continue;
Serhiy Storchaka8905fcc2018-12-11 08:38:03 +0200857 }
Victor Stinner839184f2021-02-19 15:51:36 +0100858 PyObject *v = _PyDict_Pop(tstate->dict, self->key, Py_None);
859 if (v != NULL) {
860 Py_DECREF(v);
861 }
862 else {
863 PyErr_Clear();
864 }
865 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000866 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000867 return 0;
868}
Jim Fultond15dc062004-07-14 19:11:50 +0000869
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000870static void
871local_dealloc(localobject *self)
872{
873 /* Weakrefs must be invalidated right now, otherwise they can be used
874 from code called below, which is very dangerous since Py_REFCNT(self) == 0 */
Victor Stinner8203c732020-12-16 12:20:33 +0100875 if (self->weakreflist != NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000876 PyObject_ClearWeakRefs((PyObject *) self);
Victor Stinner8203c732020-12-16 12:20:33 +0100877 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000878
879 PyObject_GC_UnTrack(self);
880
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000881 local_clear(self);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000882 Py_XDECREF(self->key);
Victor Stinner61040132020-12-18 01:39:00 +0100883
884 PyTypeObject *tp = Py_TYPE(self);
885 tp->tp_free((PyObject*)self);
886 Py_DECREF(tp);
Jim Fultond15dc062004-07-14 19:11:50 +0000887}
888
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000889/* Returns a borrowed reference to the local dict, creating it if necessary */
Jim Fultond15dc062004-07-14 19:11:50 +0000890static PyObject *
Victor Stinner61040132020-12-18 01:39:00 +0100891_ldict(localobject *self, thread_module_state *state)
Jim Fultond15dc062004-07-14 19:11:50 +0000892{
Victor Stinner8203c732020-12-16 12:20:33 +0100893 PyObject *tdict = PyThreadState_GetDict();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000894 if (tdict == NULL) {
895 PyErr_SetString(PyExc_SystemError,
896 "Couldn't get thread-state dictionary");
897 return NULL;
898 }
Jim Fultond15dc062004-07-14 19:11:50 +0000899
Victor Stinner8203c732020-12-16 12:20:33 +0100900 PyObject *ldict;
901 PyObject *dummy = PyDict_GetItemWithError(tdict, self->key);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000902 if (dummy == NULL) {
Serhiy Storchakaa24107b2019-02-25 17:59:46 +0200903 if (PyErr_Occurred()) {
904 return NULL;
905 }
Victor Stinner61040132020-12-18 01:39:00 +0100906 ldict = _local_create_dummy(self, state);
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000907 if (ldict == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000908 return NULL;
Jim Fultond15dc062004-07-14 19:11:50 +0000909
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000910 if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init &&
911 Py_TYPE(self)->tp_init((PyObject*)self,
912 self->args, self->kw) < 0) {
913 /* we need to get rid of ldict from thread so
914 we create a new one the next time we do an attr
Ezio Melotti42da6632011-03-15 05:18:48 +0200915 access */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000916 PyDict_DelItem(tdict, self->key);
917 return NULL;
918 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000919 }
920 else {
Victor Stinner61040132020-12-18 01:39:00 +0100921 assert(Py_IS_TYPE(dummy, state->local_dummy_type));
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000922 ldict = ((localdummyobject *) dummy)->localdict;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000923 }
Jim Fultond15dc062004-07-14 19:11:50 +0000924
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000925 return ldict;
Jim Fultond15dc062004-07-14 19:11:50 +0000926}
927
Jim Fultond15dc062004-07-14 19:11:50 +0000928static int
929local_setattro(localobject *self, PyObject *name, PyObject *v)
930{
Victor Stinner61040132020-12-18 01:39:00 +0100931 PyObject *module = _PyType_GetModuleByDef(Py_TYPE(self), &thread_module);
932 thread_module_state *state = get_thread_state(module);
933
934 PyObject *ldict = _ldict(self, state);
Victor Stinner8203c732020-12-16 12:20:33 +0100935 if (ldict == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000936 return -1;
Victor Stinner8203c732020-12-16 12:20:33 +0100937 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000938
Victor Stinner8203c732020-12-16 12:20:33 +0100939 PyObject *str_dict = _PyUnicode_FromId(&PyId___dict__); // borrowed ref
940 if (str_dict == NULL) {
941 return -1;
942 }
943
944 int r = PyObject_RichCompareBool(name, str_dict, Py_EQ);
945 if (r == -1) {
946 return -1;
947 }
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000948 if (r == 1) {
949 PyErr_Format(PyExc_AttributeError,
950 "'%.50s' object attribute '%U' is read-only",
951 Py_TYPE(self)->tp_name, name);
952 return -1;
953 }
Jim Fultond15dc062004-07-14 19:11:50 +0000954
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000955 return _PyObject_GenericSetAttrWithDict((PyObject *)self, name, v, ldict);
Jim Fultond15dc062004-07-14 19:11:50 +0000956}
957
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000958static PyObject *local_getattro(localobject *, PyObject *);
959
Victor Stinner61040132020-12-18 01:39:00 +0100960static PyMemberDef local_type_members[] = {
961 {"__weaklistoffset__", T_PYSSIZET, offsetof(localobject, weakreflist), READONLY},
962 {NULL},
963};
964
965static PyType_Slot local_type_slots[] = {
966 {Py_tp_dealloc, (destructor)local_dealloc},
967 {Py_tp_getattro, (getattrofunc)local_getattro},
968 {Py_tp_setattro, (setattrofunc)local_setattro},
969 {Py_tp_doc, "Thread-local data"},
970 {Py_tp_traverse, (traverseproc)local_traverse},
971 {Py_tp_clear, (inquiry)local_clear},
972 {Py_tp_new, local_new},
973 {Py_tp_members, local_type_members},
974 {0, 0}
975};
976
977static PyType_Spec local_type_spec = {
978 .name = "_thread._local",
979 .basicsize = sizeof(localobject),
980 .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
981 .slots = local_type_slots,
Jim Fultond15dc062004-07-14 19:11:50 +0000982};
983
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000984static PyObject *
985local_getattro(localobject *self, PyObject *name)
986{
Victor Stinner61040132020-12-18 01:39:00 +0100987 PyObject *module = _PyType_GetModuleByDef(Py_TYPE(self), &thread_module);
988 thread_module_state *state = get_thread_state(module);
989
990 PyObject *ldict = _ldict(self, state);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000991 if (ldict == NULL)
992 return NULL;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000993
Victor Stinner8203c732020-12-16 12:20:33 +0100994 PyObject *str_dict = _PyUnicode_FromId(&PyId___dict__); // borrowed ref
995 if (str_dict == NULL) {
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000996 return NULL;
Victor Stinner8203c732020-12-16 12:20:33 +0100997 }
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000998
Victor Stinner8203c732020-12-16 12:20:33 +0100999 int r = PyObject_RichCompareBool(name, str_dict, Py_EQ);
1000 if (r == 1) {
1001 return Py_NewRef(ldict);
1002 }
1003 if (r == -1) {
1004 return NULL;
1005 }
1006
Victor Stinner61040132020-12-18 01:39:00 +01001007 if (!Py_IS_TYPE(self, state->local_type)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001008 /* use generic lookup for subtypes */
Victor Stinner8203c732020-12-16 12:20:33 +01001009 return _PyObject_GenericGetAttrWithDict((PyObject *)self, name,
1010 ldict, 0);
1011 }
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001012
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001013 /* Optimization: just look in dict ourselves */
Victor Stinner8203c732020-12-16 12:20:33 +01001014 PyObject *value = PyDict_GetItemWithError(ldict, name);
Serhiy Storchakaa24107b2019-02-25 17:59:46 +02001015 if (value != NULL) {
Victor Stinner8203c732020-12-16 12:20:33 +01001016 return Py_NewRef(value);
Serhiy Storchakaa24107b2019-02-25 17:59:46 +02001017 }
Victor Stinner8203c732020-12-16 12:20:33 +01001018 if (PyErr_Occurred()) {
Serhiy Storchakaa24107b2019-02-25 17:59:46 +02001019 return NULL;
1020 }
Victor Stinner8203c732020-12-16 12:20:33 +01001021
Serhiy Storchakaa24107b2019-02-25 17:59:46 +02001022 /* Fall back on generic to get __class__ and __dict__ */
1023 return _PyObject_GenericGetAttrWithDict(
1024 (PyObject *)self, name, ldict, 0);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001025}
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001026
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001027/* Called when a dummy is destroyed. */
1028static PyObject *
1029_localdummy_destroyed(PyObject *localweakref, PyObject *dummyweakref)
1030{
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001031 assert(PyWeakref_CheckRef(localweakref));
Victor Stinner8203c732020-12-16 12:20:33 +01001032 PyObject *obj = PyWeakref_GET_OBJECT(localweakref);
1033 if (obj == Py_None) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001034 Py_RETURN_NONE;
Victor Stinner8203c732020-12-16 12:20:33 +01001035 }
1036
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001037 /* If the thread-local object is still alive and not being cleared,
1038 remove the corresponding local dict */
Victor Stinner8203c732020-12-16 12:20:33 +01001039 localobject *self = (localobject *)Py_NewRef(obj);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001040 if (self->dummies != NULL) {
1041 PyObject *ldict;
Serhiy Storchakaa24107b2019-02-25 17:59:46 +02001042 ldict = PyDict_GetItemWithError(self->dummies, dummyweakref);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001043 if (ldict != NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001044 PyDict_DelItem(self->dummies, dummyweakref);
1045 }
1046 if (PyErr_Occurred())
1047 PyErr_WriteUnraisable(obj);
1048 }
1049 Py_DECREF(obj);
1050 Py_RETURN_NONE;
1051}
1052
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001053/* Module functions */
1054
Guido van Rossuma027efa1997-05-05 20:56:21 +00001055struct bootstate {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001056 PyInterpreterState *interp;
1057 PyObject *func;
1058 PyObject *args;
Victor Stinner8203c732020-12-16 12:20:33 +01001059 PyObject *kwargs;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001060 PyThreadState *tstate;
Joannah Nanjekye2bc43cd2019-09-05 13:06:49 -03001061 _PyRuntimeState *runtime;
Guido van Rossuma027efa1997-05-05 20:56:21 +00001062};
1063
Victor Stinner8203c732020-12-16 12:20:33 +01001064
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001065static void
Victor Stinner8203c732020-12-16 12:20:33 +01001066thread_bootstate_free(struct bootstate *boot)
1067{
1068 Py_DECREF(boot->func);
1069 Py_DECREF(boot->args);
1070 Py_XDECREF(boot->kwargs);
1071 PyMem_Free(boot);
1072}
1073
1074
1075static void
1076thread_run(void *boot_raw)
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001077{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001078 struct bootstate *boot = (struct bootstate *) boot_raw;
1079 PyThreadState *tstate;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001080
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001081 tstate = boot->tstate;
1082 tstate->thread_id = PyThread_get_thread_ident();
Victor Stinner01b1cc12019-11-20 02:27:56 +01001083 _PyThreadState_Init(tstate);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001084 PyEval_AcquireThread(tstate);
Eric Snow2ebc5ce2017-09-07 23:51:28 -06001085 tstate->interp->num_threads++;
Victor Stinner8203c732020-12-16 12:20:33 +01001086
1087 PyObject *res = PyObject_Call(boot->func, boot->args, boot->kwargs);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001088 if (res == NULL) {
1089 if (PyErr_ExceptionMatches(PyExc_SystemExit))
Victor Stinner8b095002019-05-29 02:57:56 +02001090 /* SystemExit is ignored silently */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001091 PyErr_Clear();
1092 else {
Victor Stinner8b095002019-05-29 02:57:56 +02001093 _PyErr_WriteUnraisableMsg("in thread started by", boot->func);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001094 }
1095 }
Victor Stinner8b095002019-05-29 02:57:56 +02001096 else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001097 Py_DECREF(res);
Victor Stinner8b095002019-05-29 02:57:56 +02001098 }
Victor Stinner8203c732020-12-16 12:20:33 +01001099
1100 thread_bootstate_free(boot);
Eric Snow2ebc5ce2017-09-07 23:51:28 -06001101 tstate->interp->num_threads--;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001102 PyThreadState_Clear(tstate);
Victor Stinner23ef89d2020-03-18 02:26:04 +01001103 _PyThreadState_DeleteCurrent(tstate);
Victor Stinner8203c732020-12-16 12:20:33 +01001104
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001105 PyThread_exit_thread();
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001106}
1107
Barry Warsawd0c10421996-12-17 00:05:22 +00001108static PyObject *
Peter Schneider-Kamp3707efe2000-07-10 10:03:58 +00001109thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001110{
Joannah Nanjekye2bc43cd2019-09-05 13:06:49 -03001111 _PyRuntimeState *runtime = &_PyRuntime;
Victor Stinner8203c732020-12-16 12:20:33 +01001112 PyObject *func, *args, *kwargs = NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001113
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001114 if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3,
Victor Stinner8203c732020-12-16 12:20:33 +01001115 &func, &args, &kwargs))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001116 return NULL;
1117 if (!PyCallable_Check(func)) {
1118 PyErr_SetString(PyExc_TypeError,
1119 "first arg must be callable");
1120 return NULL;
1121 }
1122 if (!PyTuple_Check(args)) {
1123 PyErr_SetString(PyExc_TypeError,
1124 "2nd arg must be a tuple");
1125 return NULL;
1126 }
Victor Stinner8203c732020-12-16 12:20:33 +01001127 if (kwargs != NULL && !PyDict_Check(kwargs)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001128 PyErr_SetString(PyExc_TypeError,
1129 "optional 3rd arg must be a dictionary");
1130 return NULL;
1131 }
Victor Stinner252346a2020-05-01 11:33:44 +02001132
1133 PyInterpreterState *interp = _PyInterpreterState_GET();
1134 if (interp->config._isolated_interpreter) {
1135 PyErr_SetString(PyExc_RuntimeError,
1136 "thread is not supported for isolated subinterpreters");
1137 return NULL;
1138 }
1139
Victor Stinner8203c732020-12-16 12:20:33 +01001140 struct bootstate *boot = PyMem_NEW(struct bootstate, 1);
1141 if (boot == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001142 return PyErr_NoMemory();
Victor Stinner8203c732020-12-16 12:20:33 +01001143 }
Victor Stinner81a7be32020-04-14 15:14:01 +02001144 boot->interp = _PyInterpreterState_GET();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001145 boot->tstate = _PyThreadState_Prealloc(boot->interp);
1146 if (boot->tstate == NULL) {
Victor Stinner00d7abd2020-12-01 09:56:42 +01001147 PyMem_Free(boot);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001148 return PyErr_NoMemory();
1149 }
Victor Stinner8203c732020-12-16 12:20:33 +01001150 boot->runtime = runtime;
1151 boot->func = Py_NewRef(func);
1152 boot->args = Py_NewRef(args);
1153 boot->kwargs = Py_XNewRef(kwargs);
Victor Stinner3225b9f2020-03-09 20:56:57 +01001154
Victor Stinner8203c732020-12-16 12:20:33 +01001155 unsigned long ident = PyThread_start_new_thread(thread_run, (void*) boot);
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001156 if (ident == PYTHREAD_INVALID_THREAD_ID) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001157 PyErr_SetString(ThreadError, "can't start new thread");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001158 PyThreadState_Clear(boot->tstate);
Victor Stinner8203c732020-12-16 12:20:33 +01001159 thread_bootstate_free(boot);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001160 return NULL;
1161 }
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001162 return PyLong_FromUnsignedLong(ident);
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001163}
1164
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001165PyDoc_STRVAR(start_new_doc,
Andrew M. Kuchling38300c62001-10-05 12:24:15 +00001166"start_new_thread(function, args[, kwargs])\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001167(start_new() is an obsolete synonym)\n\
1168\n\
Guido van Rossum3c288632001-10-16 21:13:49 +00001169Start a new thread and return its identifier. The thread will call the\n\
1170function with positional arguments from the tuple args and keyword arguments\n\
1171taken from the optional dictionary kwargs. The thread exits when the\n\
1172function returns; the return value is ignored. The thread will also exit\n\
1173when the function raises an unhandled exception; a stack trace will be\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001174printed unless the exception is SystemExit.\n");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001175
Barry Warsawd0c10421996-12-17 00:05:22 +00001176static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301177thread_PyThread_exit_thread(PyObject *self, PyObject *Py_UNUSED(ignored))
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001178{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001179 PyErr_SetNone(PyExc_SystemExit);
1180 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001181}
1182
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001183PyDoc_STRVAR(exit_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001184"exit()\n\
Éric Araujo9bcf8bf2011-05-31 14:08:26 +02001185(exit_thread() is an obsolete synonym)\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001186\n\
1187This is synonymous to ``raise SystemExit''. It will cause the current\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001188thread to exit silently unless the exception is caught.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001189
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001190static PyObject *
Antoine Pitrouba251c22021-03-11 23:35:45 +01001191thread_PyThread_interrupt_main(PyObject *self, PyObject *args)
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001192{
Antoine Pitrouba251c22021-03-11 23:35:45 +01001193 int signum = SIGINT;
1194 if (!PyArg_ParseTuple(args, "|i:signum", &signum)) {
1195 return NULL;
1196 }
1197
1198 if (PyErr_SetInterruptEx(signum)) {
1199 PyErr_SetString(PyExc_ValueError, "signal number out of range");
1200 return NULL;
1201 }
Serhiy Storchaka228b12e2017-01-23 09:47:21 +02001202 Py_RETURN_NONE;
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001203}
1204
1205PyDoc_STRVAR(interrupt_doc,
Antoine Pitrouba251c22021-03-11 23:35:45 +01001206"interrupt_main(signum=signal.SIGINT, /)\n\
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001207\n\
Antoine Pitrouba251c22021-03-11 23:35:45 +01001208Simulate the arrival of the given signal in the main thread,\n\
1209where the corresponding signal handler will be executed.\n\
1210If *signum* is omitted, SIGINT is assumed.\n\
1211A subthread can use this function to interrupt the main thread.\n\
1212\n\
1213Note: the default signal hander for SIGINT raises ``KeyboardInterrupt``."
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001214);
1215
Victor Stinner61040132020-12-18 01:39:00 +01001216static lockobject *newlockobject(PyObject *module);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001217
Barry Warsawd0c10421996-12-17 00:05:22 +00001218static PyObject *
Victor Stinner8203c732020-12-16 12:20:33 +01001219thread_PyThread_allocate_lock(PyObject *module, PyObject *Py_UNUSED(ignored))
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001220{
Victor Stinner61040132020-12-18 01:39:00 +01001221 return (PyObject *) newlockobject(module);
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001222}
1223
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001224PyDoc_STRVAR(allocate_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001225"allocate_lock() -> lock object\n\
1226(allocate() is an obsolete synonym)\n\
1227\n\
Berker Peksag720e6552016-05-02 12:25:35 +03001228Create a new lock object. See help(type(threading.Lock())) for\n\
1229information about locks.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001230
Barry Warsawd0c10421996-12-17 00:05:22 +00001231static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301232thread_get_ident(PyObject *self, PyObject *Py_UNUSED(ignored))
Guido van Rossumb6775db1994-08-01 11:34:53 +00001233{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001234 unsigned long ident = PyThread_get_thread_ident();
1235 if (ident == PYTHREAD_INVALID_THREAD_ID) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001236 PyErr_SetString(ThreadError, "no current thread ident");
1237 return NULL;
1238 }
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001239 return PyLong_FromUnsignedLong(ident);
Guido van Rossumb6775db1994-08-01 11:34:53 +00001240}
1241
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001242PyDoc_STRVAR(get_ident_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001243"get_ident() -> integer\n\
1244\n\
1245Return a non-zero integer that uniquely identifies the current thread\n\
1246amongst other threads that exist simultaneously.\n\
1247This may be used to identify per-thread resources.\n\
1248Even though on some platforms threads identities may appear to be\n\
1249allocated consecutive numbers starting at 1, this behavior should not\n\
1250be relied upon, and the number should be seen purely as a magic cookie.\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001251A thread's identity may be reused for another thread after it exits.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001252
Jake Teslerb121f632019-05-22 08:43:17 -07001253#ifdef PY_HAVE_THREAD_NATIVE_ID
1254static PyObject *
1255thread_get_native_id(PyObject *self, PyObject *Py_UNUSED(ignored))
1256{
1257 unsigned long native_id = PyThread_get_thread_native_id();
1258 return PyLong_FromUnsignedLong(native_id);
1259}
1260
1261PyDoc_STRVAR(get_native_id_doc,
1262"get_native_id() -> integer\n\
1263\n\
1264Return a non-negative integer identifying the thread as reported\n\
1265by the OS (kernel). This may be used to uniquely identify a\n\
1266particular thread within a system.");
1267#endif
1268
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001269static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301270thread__count(PyObject *self, PyObject *Py_UNUSED(ignored))
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001271{
Victor Stinner81a7be32020-04-14 15:14:01 +02001272 PyInterpreterState *interp = _PyInterpreterState_GET();
Victor Stinnercaba55b2018-08-03 15:33:52 +02001273 return PyLong_FromLong(interp->num_threads);
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001274}
1275
1276PyDoc_STRVAR(_count_doc,
1277"_count() -> integer\n\
1278\n\
Antoine Pitrou9257f5e2009-10-30 22:23:02 +00001279\
oldkaa0735f2018-02-02 16:52:55 +08001280Return the number of currently running Python threads, excluding\n\
Antoine Pitrou9257f5e2009-10-30 22:23:02 +00001281the main thread. The returned number comprises all threads created\n\
1282through `start_new_thread()` as well as `threading.Thread`, and not\n\
1283yet finished.\n\
1284\n\
1285This function is meant for internal and specialized purposes only.\n\
1286In most applications `threading.enumerate()` should be used instead.");
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001287
Antoine Pitrou7b476992013-09-07 23:38:37 +02001288static void
Victor Stinnera42de742018-11-22 10:25:22 +01001289release_sentinel(void *wr_raw)
Antoine Pitrou7b476992013-09-07 23:38:37 +02001290{
Victor Stinnera42de742018-11-22 10:25:22 +01001291 PyObject *wr = _PyObject_CAST(wr_raw);
Antoine Pitrou7b476992013-09-07 23:38:37 +02001292 /* Tricky: this function is called when the current thread state
1293 is being deleted. Therefore, only simple C code can safely
1294 execute here. */
1295 PyObject *obj = PyWeakref_GET_OBJECT(wr);
1296 lockobject *lock;
1297 if (obj != Py_None) {
Antoine Pitrou7b476992013-09-07 23:38:37 +02001298 lock = (lockobject *) obj;
1299 if (lock->locked) {
1300 PyThread_release_lock(lock->lock_lock);
1301 lock->locked = 0;
1302 }
1303 }
1304 /* Deallocating a weakref with a NULL callback only calls
1305 PyObject_GC_Del(), which can't call any Python code. */
1306 Py_DECREF(wr);
1307}
1308
1309static PyObject *
Victor Stinner8203c732020-12-16 12:20:33 +01001310thread__set_sentinel(PyObject *module, PyObject *Py_UNUSED(ignored))
Antoine Pitrou7b476992013-09-07 23:38:37 +02001311{
1312 PyObject *wr;
1313 PyThreadState *tstate = PyThreadState_Get();
1314 lockobject *lock;
1315
1316 if (tstate->on_delete_data != NULL) {
1317 /* We must support the re-creation of the lock from a
1318 fork()ed child. */
1319 assert(tstate->on_delete == &release_sentinel);
1320 wr = (PyObject *) tstate->on_delete_data;
1321 tstate->on_delete = NULL;
1322 tstate->on_delete_data = NULL;
1323 Py_DECREF(wr);
1324 }
Victor Stinner61040132020-12-18 01:39:00 +01001325 lock = newlockobject(module);
Antoine Pitrou7b476992013-09-07 23:38:37 +02001326 if (lock == NULL)
1327 return NULL;
1328 /* The lock is owned by whoever called _set_sentinel(), but the weakref
1329 hangs to the thread state. */
1330 wr = PyWeakref_NewRef((PyObject *) lock, NULL);
1331 if (wr == NULL) {
1332 Py_DECREF(lock);
1333 return NULL;
1334 }
1335 tstate->on_delete_data = (void *) wr;
1336 tstate->on_delete = &release_sentinel;
1337 return (PyObject *) lock;
1338}
1339
1340PyDoc_STRVAR(_set_sentinel_doc,
1341"_set_sentinel() -> lock\n\
1342\n\
1343Set a sentinel lock that will be released when the current thread\n\
1344state is finalized (after it is untied from the interpreter).\n\
1345\n\
1346This is a private API for the threading module.");
1347
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001348static PyObject *
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001349thread_stack_size(PyObject *self, PyObject *args)
1350{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001351 size_t old_size;
1352 Py_ssize_t new_size = 0;
1353 int rc;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001354
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001355 if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size))
1356 return NULL;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001357
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001358 if (new_size < 0) {
1359 PyErr_SetString(PyExc_ValueError,
1360 "size must be 0 or a positive value");
1361 return NULL;
1362 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001363
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001364 old_size = PyThread_get_stacksize();
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001365
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001366 rc = PyThread_set_stacksize((size_t) new_size);
1367 if (rc == -1) {
1368 PyErr_Format(PyExc_ValueError,
1369 "size not valid: %zd bytes",
1370 new_size);
1371 return NULL;
1372 }
1373 if (rc == -2) {
1374 PyErr_SetString(ThreadError,
1375 "setting stack size not supported");
1376 return NULL;
1377 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001378
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001379 return PyLong_FromSsize_t((Py_ssize_t) old_size);
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001380}
1381
1382PyDoc_STRVAR(stack_size_doc,
1383"stack_size([size]) -> size\n\
1384\n\
1385Return the thread stack size used when creating new threads. The\n\
1386optional size argument specifies the stack size (in bytes) to be used\n\
1387for subsequently created threads, and must be 0 (use platform or\n\
1388configured default) or a positive integer value of at least 32,768 (32k).\n\
1389If changing the thread stack size is unsupported, a ThreadError\n\
1390exception is raised. If the specified size is invalid, a ValueError\n\
1391exception is raised, and the stack size is unmodified. 32k bytes\n\
1392 currently the minimum supported stack size value to guarantee\n\
1393sufficient stack space for the interpreter itself.\n\
1394\n\
1395Note that some platforms may have particular restrictions on values for\n\
Victor Stinner8c663fd2017-11-08 14:44:44 -08001396the stack size, such as requiring a minimum stack size larger than 32 KiB or\n\
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001397requiring allocation in multiples of the system memory page size\n\
1398- platform documentation should be referred to for more information\n\
Victor Stinner8c663fd2017-11-08 14:44:44 -08001399(4 KiB pages are common; using multiples of 4096 for the stack size is\n\
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001400the suggested approach in the absence of more specific information).");
1401
Victor Stinnercd590a72019-05-28 00:39:52 +02001402static int
1403thread_excepthook_file(PyObject *file, PyObject *exc_type, PyObject *exc_value,
1404 PyObject *exc_traceback, PyObject *thread)
1405{
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001406 _Py_IDENTIFIER(name);
Victor Stinnercd590a72019-05-28 00:39:52 +02001407 /* print(f"Exception in thread {thread.name}:", file=file) */
1408 if (PyFile_WriteString("Exception in thread ", file) < 0) {
1409 return -1;
1410 }
1411
1412 PyObject *name = NULL;
1413 if (thread != Py_None) {
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001414 if (_PyObject_LookupAttrId(thread, &PyId_name, &name) < 0) {
1415 return -1;
1416 }
Victor Stinnercd590a72019-05-28 00:39:52 +02001417 }
1418 if (name != NULL) {
1419 if (PyFile_WriteObject(name, file, Py_PRINT_RAW) < 0) {
1420 Py_DECREF(name);
1421 return -1;
1422 }
1423 Py_DECREF(name);
1424 }
1425 else {
Victor Stinnercd590a72019-05-28 00:39:52 +02001426 unsigned long ident = PyThread_get_thread_ident();
1427 PyObject *str = PyUnicode_FromFormat("%lu", ident);
1428 if (str != NULL) {
1429 if (PyFile_WriteObject(str, file, Py_PRINT_RAW) < 0) {
1430 Py_DECREF(str);
1431 return -1;
1432 }
1433 Py_DECREF(str);
1434 }
1435 else {
1436 PyErr_Clear();
1437
1438 if (PyFile_WriteString("<failed to get thread name>", file) < 0) {
1439 return -1;
1440 }
1441 }
1442 }
1443
1444 if (PyFile_WriteString(":\n", file) < 0) {
1445 return -1;
1446 }
1447
1448 /* Display the traceback */
1449 _PyErr_Display(file, exc_type, exc_value, exc_traceback);
1450
1451 /* Call file.flush() */
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001452 PyObject *res = _PyObject_CallMethodIdNoArgs(file, &PyId_flush);
Victor Stinnercd590a72019-05-28 00:39:52 +02001453 if (!res) {
1454 return -1;
1455 }
1456 Py_DECREF(res);
1457
1458 return 0;
1459}
1460
1461
1462PyDoc_STRVAR(ExceptHookArgs__doc__,
1463"ExceptHookArgs\n\
1464\n\
1465Type used to pass arguments to threading.excepthook.");
1466
1467static PyTypeObject ExceptHookArgsType;
1468
1469static PyStructSequence_Field ExceptHookArgs_fields[] = {
1470 {"exc_type", "Exception type"},
1471 {"exc_value", "Exception value"},
1472 {"exc_traceback", "Exception traceback"},
1473 {"thread", "Thread"},
1474 {0}
1475};
1476
1477static PyStructSequence_Desc ExceptHookArgs_desc = {
Victor Stinner8203c732020-12-16 12:20:33 +01001478 .name = "_thread._ExceptHookArgs",
Victor Stinnercd590a72019-05-28 00:39:52 +02001479 .doc = ExceptHookArgs__doc__,
1480 .fields = ExceptHookArgs_fields,
1481 .n_in_sequence = 4
1482};
1483
1484
1485static PyObject *
1486thread_excepthook(PyObject *self, PyObject *args)
1487{
Andy Lester55728702020-03-06 16:53:17 -06001488 if (!Py_IS_TYPE(args, &ExceptHookArgsType)) {
Victor Stinnercd590a72019-05-28 00:39:52 +02001489 PyErr_SetString(PyExc_TypeError,
1490 "_thread.excepthook argument type "
1491 "must be ExceptHookArgs");
1492 return NULL;
1493 }
1494
1495 /* Borrowed reference */
1496 PyObject *exc_type = PyStructSequence_GET_ITEM(args, 0);
1497 if (exc_type == PyExc_SystemExit) {
1498 /* silently ignore SystemExit */
1499 Py_RETURN_NONE;
1500 }
1501
1502 /* Borrowed references */
1503 PyObject *exc_value = PyStructSequence_GET_ITEM(args, 1);
1504 PyObject *exc_tb = PyStructSequence_GET_ITEM(args, 2);
1505 PyObject *thread = PyStructSequence_GET_ITEM(args, 3);
1506
1507 PyObject *file = _PySys_GetObjectId(&PyId_stderr);
1508 if (file == NULL || file == Py_None) {
1509 if (thread == Py_None) {
1510 /* do nothing if sys.stderr is None and thread is None */
1511 Py_RETURN_NONE;
1512 }
1513
1514 file = PyObject_GetAttrString(thread, "_stderr");
1515 if (file == NULL) {
1516 return NULL;
1517 }
1518 if (file == Py_None) {
1519 Py_DECREF(file);
1520 /* do nothing if sys.stderr is None and sys.stderr was None
1521 when the thread was created */
1522 Py_RETURN_NONE;
1523 }
1524 }
1525 else {
1526 Py_INCREF(file);
1527 }
1528
1529 int res = thread_excepthook_file(file, exc_type, exc_value, exc_tb,
1530 thread);
1531 Py_DECREF(file);
1532 if (res < 0) {
1533 return NULL;
1534 }
1535
1536 Py_RETURN_NONE;
1537}
1538
1539PyDoc_STRVAR(excepthook_doc,
1540"excepthook(exc_type, exc_value, exc_traceback, thread)\n\
1541\n\
1542Handle uncaught Thread.run() exception.");
1543
Barry Warsawd0c10421996-12-17 00:05:22 +00001544static PyMethodDef thread_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001545 {"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread,
Victor Stinner754851f2011-04-19 23:58:51 +02001546 METH_VARARGS, start_new_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001547 {"start_new", (PyCFunction)thread_PyThread_start_new_thread,
Victor Stinner754851f2011-04-19 23:58:51 +02001548 METH_VARARGS, start_new_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301549 {"allocate_lock", thread_PyThread_allocate_lock,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001550 METH_NOARGS, allocate_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301551 {"allocate", thread_PyThread_allocate_lock,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001552 METH_NOARGS, allocate_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301553 {"exit_thread", thread_PyThread_exit_thread,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001554 METH_NOARGS, exit_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301555 {"exit", thread_PyThread_exit_thread,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001556 METH_NOARGS, exit_doc},
Antoine Pitrouba251c22021-03-11 23:35:45 +01001557 {"interrupt_main", (PyCFunction)thread_PyThread_interrupt_main,
1558 METH_VARARGS, interrupt_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301559 {"get_ident", thread_get_ident,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001560 METH_NOARGS, get_ident_doc},
Jake Teslerb121f632019-05-22 08:43:17 -07001561#ifdef PY_HAVE_THREAD_NATIVE_ID
1562 {"get_native_id", thread_get_native_id,
1563 METH_NOARGS, get_native_id_doc},
1564#endif
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301565 {"_count", thread__count,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001566 METH_NOARGS, _count_doc},
1567 {"stack_size", (PyCFunction)thread_stack_size,
Victor Stinner754851f2011-04-19 23:58:51 +02001568 METH_VARARGS, stack_size_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301569 {"_set_sentinel", thread__set_sentinel,
Antoine Pitrou7b476992013-09-07 23:38:37 +02001570 METH_NOARGS, _set_sentinel_doc},
Victor Stinnercd590a72019-05-28 00:39:52 +02001571 {"_excepthook", thread_excepthook,
1572 METH_O, excepthook_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001573 {NULL, NULL} /* sentinel */
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001574};
1575
1576
1577/* Initialization function */
1578
Victor Stinner8203c732020-12-16 12:20:33 +01001579static int
Victor Stinner61040132020-12-18 01:39:00 +01001580thread_module_exec(PyObject *module)
Victor Stinner8203c732020-12-16 12:20:33 +01001581{
Victor Stinner61040132020-12-18 01:39:00 +01001582 thread_module_state *state = get_thread_state(module);
1583 PyObject *d = PyModule_GetDict(module);
1584
Victor Stinner8203c732020-12-16 12:20:33 +01001585 // Initialize the C thread library
1586 PyThread_init_thread();
1587
Victor Stinner61040132020-12-18 01:39:00 +01001588 // Lock
1589 state->lock_type = (PyTypeObject *)PyType_FromSpec(&lock_type_spec);
1590 if (state->lock_type == NULL) {
Victor Stinner8203c732020-12-16 12:20:33 +01001591 return -1;
1592 }
Victor Stinner61040132020-12-18 01:39:00 +01001593 if (PyDict_SetItemString(d, "LockType", (PyObject *)state->lock_type) < 0) {
Victor Stinner8203c732020-12-16 12:20:33 +01001594 return -1;
1595 }
Victor Stinner61040132020-12-18 01:39:00 +01001596
1597 // RLock
1598 PyTypeObject *rlock_type = (PyTypeObject *)PyType_FromSpec(&rlock_type_spec);
1599 if (rlock_type == NULL) {
Victor Stinner8203c732020-12-16 12:20:33 +01001600 return -1;
1601 }
Victor Stinner61040132020-12-18 01:39:00 +01001602 if (PyModule_AddType(module, rlock_type) < 0) {
1603 Py_DECREF(rlock_type);
1604 return -1;
1605 }
1606 Py_DECREF(rlock_type);
1607
1608 // Local dummy
1609 state->local_dummy_type = (PyTypeObject *)PyType_FromSpec(&local_dummy_type_spec);
1610 if (state->local_dummy_type == NULL) {
1611 return -1;
1612 }
1613
1614 // Local
1615 state->local_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, &local_type_spec, NULL);
1616 if (state->local_type == NULL) {
1617 return -1;
1618 }
1619 if (PyModule_AddType(module, state->local_type) < 0) {
1620 return -1;
1621 }
1622
Victor Stinner8203c732020-12-16 12:20:33 +01001623 if (ExceptHookArgsType.tp_name == NULL) {
1624 if (PyStructSequence_InitType2(&ExceptHookArgsType,
1625 &ExceptHookArgs_desc) < 0) {
1626 return -1;
1627 }
1628 }
1629
1630 // Add module attributes
Victor Stinner8203c732020-12-16 12:20:33 +01001631 if (PyDict_SetItemString(d, "error", ThreadError) < 0) {
1632 return -1;
1633 }
Victor Stinner8203c732020-12-16 12:20:33 +01001634 if (PyModule_AddType(module, &ExceptHookArgsType) < 0) {
1635 return -1;
1636 }
1637
1638 // TIMEOUT_MAX
1639 double timeout_max = (_PyTime_t)PY_TIMEOUT_MAX * 1e-6;
1640 double time_max = _PyTime_AsSecondsDouble(_PyTime_MAX);
1641 timeout_max = Py_MIN(timeout_max, time_max);
1642 // Round towards minus infinity
1643 timeout_max = floor(timeout_max);
1644
1645 if (PyModule_AddObject(module, "TIMEOUT_MAX",
1646 PyFloat_FromDouble(timeout_max)) < 0) {
1647 return -1;
1648 }
1649
1650 return 0;
1651}
1652
1653
Victor Stinner61040132020-12-18 01:39:00 +01001654static int
1655thread_module_traverse(PyObject *module, visitproc visit, void *arg)
1656{
1657 thread_module_state *state = get_thread_state(module);
1658 Py_VISIT(state->lock_type);
1659 Py_VISIT(state->local_type);
1660 Py_VISIT(state->local_dummy_type);
1661 return 0;
1662}
1663
1664static int
1665thread_module_clear(PyObject *module)
1666{
1667 thread_module_state *state = get_thread_state(module);
1668 Py_CLEAR(state->lock_type);
1669 Py_CLEAR(state->local_type);
1670 Py_CLEAR(state->local_dummy_type);
1671 return 0;
1672}
1673
1674static void
1675thread_module_free(void *module)
1676{
1677 thread_module_clear((PyObject *)module);
1678}
1679
1680
1681
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001682PyDoc_STRVAR(thread_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001683"This module provides primitive operations to write multi-threaded programs.\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001684The 'threading' module provides a more convenient interface.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001685
Victor Stinner61040132020-12-18 01:39:00 +01001686static PyModuleDef_Slot thread_module_slots[] = {
1687 {Py_mod_exec, thread_module_exec},
1688 {0, NULL}
1689};
1690
1691static struct PyModuleDef thread_module = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001692 PyModuleDef_HEAD_INIT,
Victor Stinner8203c732020-12-16 12:20:33 +01001693 .m_name = "_thread",
1694 .m_doc = thread_doc,
Victor Stinner61040132020-12-18 01:39:00 +01001695 .m_size = sizeof(thread_module_state),
Victor Stinner8203c732020-12-16 12:20:33 +01001696 .m_methods = thread_methods,
Victor Stinner61040132020-12-18 01:39:00 +01001697 .m_traverse = thread_module_traverse,
1698 .m_clear = thread_module_clear,
1699 .m_free = thread_module_free,
1700 .m_slots = thread_module_slots,
Martin v. Löwis1a214512008-06-11 05:26:20 +00001701};
1702
Mark Hammondfe51c6d2002-08-02 02:27:13 +00001703PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00001704PyInit__thread(void)
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001705{
Victor Stinner61040132020-12-18 01:39:00 +01001706 return PyModuleDef_Init(&thread_module);
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001707}