blob: 6924d6553a1ff8ffec7ef2e78b1008469d8b9b25 [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
330static void
331rlock_dealloc(rlockobject *self)
332{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000333 if (self->in_weakreflist != NULL)
334 PyObject_ClearWeakRefs((PyObject *) self);
Victor Stinner357f5152013-11-05 15:10:19 +0100335 /* self->rlock_lock can be NULL if PyThread_allocate_lock() failed
336 in rlock_new() */
337 if (self->rlock_lock != NULL) {
338 /* Unlock the lock so it's safe to free it */
339 if (self->rlock_count > 0)
340 PyThread_release_lock(self->rlock_lock);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000341
Victor Stinner357f5152013-11-05 15:10:19 +0100342 PyThread_free_lock(self->rlock_lock);
343 }
Victor Stinner61040132020-12-18 01:39:00 +0100344 PyTypeObject *tp = Py_TYPE(self);
345 tp->tp_free(self);
346 Py_DECREF(tp);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000347}
348
349static PyObject *
350rlock_acquire(rlockobject *self, PyObject *args, PyObject *kwds)
351{
Victor Stinnerf5faad22015-03-28 03:52:05 +0100352 _PyTime_t timeout;
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200353 unsigned long tid;
Antoine Pitrou810023d2010-12-15 22:59:16 +0000354 PyLockStatus r = PY_LOCK_ACQUIRED;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000355
Victor Stinnerf5faad22015-03-28 03:52:05 +0100356 if (lock_acquire_parse_args(args, kwds, &timeout) < 0)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000357 return NULL;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000358
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000359 tid = PyThread_get_thread_ident();
360 if (self->rlock_count > 0 && tid == self->rlock_owner) {
361 unsigned long count = self->rlock_count + 1;
362 if (count <= self->rlock_count) {
363 PyErr_SetString(PyExc_OverflowError,
364 "Internal lock count overflowed");
365 return NULL;
366 }
367 self->rlock_count = count;
368 Py_RETURN_TRUE;
369 }
Victor Stinnerf5faad22015-03-28 03:52:05 +0100370 r = acquire_timed(self->rlock_lock, timeout);
Antoine Pitrou810023d2010-12-15 22:59:16 +0000371 if (r == PY_LOCK_ACQUIRED) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000372 assert(self->rlock_count == 0);
373 self->rlock_owner = tid;
374 self->rlock_count = 1;
375 }
Antoine Pitrou810023d2010-12-15 22:59:16 +0000376 else if (r == PY_LOCK_INTR) {
377 return NULL;
378 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000379
Antoine Pitrou810023d2010-12-15 22:59:16 +0000380 return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000381}
382
383PyDoc_STRVAR(rlock_acquire_doc,
384"acquire(blocking=True) -> bool\n\
385\n\
386Lock the lock. `blocking` indicates whether we should wait\n\
387for the lock to be available or not. If `blocking` is False\n\
388and another thread holds the lock, the method will return False\n\
389immediately. If `blocking` is True and another thread holds\n\
390the lock, the method will wait for the lock to be released,\n\
391take it and then return True.\n\
Antoine Pitrou810023d2010-12-15 22:59:16 +0000392(note: the blocking operation is interruptible.)\n\
Antoine Pitrou434736a2009-11-10 18:46:01 +0000393\n\
394In all other cases, the method will return True immediately.\n\
395Precisely, if the current thread already holds the lock, its\n\
396internal counter is simply incremented. If nobody holds the lock,\n\
397the lock is taken and its internal counter initialized to 1.");
398
399static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530400rlock_release(rlockobject *self, PyObject *Py_UNUSED(ignored))
Antoine Pitrou434736a2009-11-10 18:46:01 +0000401{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200402 unsigned long tid = PyThread_get_thread_ident();
Antoine Pitrou434736a2009-11-10 18:46:01 +0000403
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000404 if (self->rlock_count == 0 || self->rlock_owner != tid) {
405 PyErr_SetString(PyExc_RuntimeError,
406 "cannot release un-acquired lock");
407 return NULL;
408 }
409 if (--self->rlock_count == 0) {
410 self->rlock_owner = 0;
411 PyThread_release_lock(self->rlock_lock);
412 }
413 Py_RETURN_NONE;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000414}
415
416PyDoc_STRVAR(rlock_release_doc,
417"release()\n\
418\n\
419Release the lock, allowing another thread that is blocked waiting for\n\
420the lock to acquire the lock. The lock must be in the locked state,\n\
421and must be locked by the same thread that unlocks it; otherwise a\n\
422`RuntimeError` is raised.\n\
423\n\
424Do note that if the lock was acquire()d several times in a row by the\n\
425current thread, release() needs to be called as many times for the lock\n\
426to be available for other threads.");
427
428static PyObject *
Victor Stinnere8794522014-01-02 12:47:24 +0100429rlock_acquire_restore(rlockobject *self, PyObject *args)
Antoine Pitrou434736a2009-11-10 18:46:01 +0000430{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200431 unsigned long owner;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000432 unsigned long count;
433 int r = 1;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000434
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200435 if (!PyArg_ParseTuple(args, "(kk):_acquire_restore", &count, &owner))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000436 return NULL;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000437
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000438 if (!PyThread_acquire_lock(self->rlock_lock, 0)) {
439 Py_BEGIN_ALLOW_THREADS
440 r = PyThread_acquire_lock(self->rlock_lock, 1);
441 Py_END_ALLOW_THREADS
442 }
443 if (!r) {
444 PyErr_SetString(ThreadError, "couldn't acquire lock");
445 return NULL;
446 }
447 assert(self->rlock_count == 0);
448 self->rlock_owner = owner;
449 self->rlock_count = count;
450 Py_RETURN_NONE;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000451}
452
453PyDoc_STRVAR(rlock_acquire_restore_doc,
454"_acquire_restore(state) -> None\n\
455\n\
456For internal use by `threading.Condition`.");
457
458static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530459rlock_release_save(rlockobject *self, PyObject *Py_UNUSED(ignored))
Antoine Pitrou434736a2009-11-10 18:46:01 +0000460{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200461 unsigned long owner;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000462 unsigned long count;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000463
Victor Stinnerc2824d42011-04-24 23:41:33 +0200464 if (self->rlock_count == 0) {
465 PyErr_SetString(PyExc_RuntimeError,
466 "cannot release un-acquired lock");
467 return NULL;
468 }
469
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000470 owner = self->rlock_owner;
471 count = self->rlock_count;
472 self->rlock_count = 0;
473 self->rlock_owner = 0;
474 PyThread_release_lock(self->rlock_lock);
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200475 return Py_BuildValue("kk", count, owner);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000476}
477
478PyDoc_STRVAR(rlock_release_save_doc,
479"_release_save() -> tuple\n\
480\n\
481For internal use by `threading.Condition`.");
482
483
484static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530485rlock_is_owned(rlockobject *self, PyObject *Py_UNUSED(ignored))
Antoine Pitrou434736a2009-11-10 18:46:01 +0000486{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200487 unsigned long tid = PyThread_get_thread_ident();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000488
489 if (self->rlock_count > 0 && self->rlock_owner == tid) {
490 Py_RETURN_TRUE;
491 }
492 Py_RETURN_FALSE;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000493}
494
495PyDoc_STRVAR(rlock_is_owned_doc,
496"_is_owned() -> bool\n\
497\n\
498For internal use by `threading.Condition`.");
499
500static PyObject *
501rlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
502{
Victor Stinner87255be2020-04-07 23:11:49 +0200503 rlockobject *self = (rlockobject *) type->tp_alloc(type, 0);
504 if (self == NULL) {
505 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000506 }
Victor Stinner87255be2020-04-07 23:11:49 +0200507 self->in_weakreflist = NULL;
508 self->rlock_owner = 0;
509 self->rlock_count = 0;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000510
Victor Stinner87255be2020-04-07 23:11:49 +0200511 self->rlock_lock = PyThread_allocate_lock();
512 if (self->rlock_lock == NULL) {
513 Py_DECREF(self);
514 PyErr_SetString(ThreadError, "can't allocate lock");
515 return NULL;
516 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000517 return (PyObject *) self;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000518}
519
520static PyObject *
521rlock_repr(rlockobject *self)
522{
Raymond Hettinger62f4dad2014-05-25 18:22:35 -0700523 return PyUnicode_FromFormat("<%s %s object owner=%ld count=%lu at %p>",
524 self->rlock_count ? "locked" : "unlocked",
525 Py_TYPE(self)->tp_name, self->rlock_owner,
526 self->rlock_count, self);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000527}
528
529
Victor Stinner87255be2020-04-07 23:11:49 +0200530#ifdef HAVE_FORK
531static PyObject *
532rlock__at_fork_reinit(rlockobject *self, PyObject *Py_UNUSED(args))
533{
534 if (_PyThread_at_fork_reinit(&self->rlock_lock) < 0) {
535 PyErr_SetString(ThreadError, "failed to reinitialize lock at fork");
536 return NULL;
537 }
538
539 self->rlock_owner = 0;
540 self->rlock_count = 0;
541
542 Py_RETURN_NONE;
543}
544#endif /* HAVE_FORK */
545
546
Antoine Pitrou434736a2009-11-10 18:46:01 +0000547static PyMethodDef rlock_methods[] = {
Serhiy Storchaka62be7422018-11-27 13:27:31 +0200548 {"acquire", (PyCFunction)(void(*)(void))rlock_acquire,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000549 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
550 {"release", (PyCFunction)rlock_release,
551 METH_NOARGS, rlock_release_doc},
552 {"_is_owned", (PyCFunction)rlock_is_owned,
553 METH_NOARGS, rlock_is_owned_doc},
554 {"_acquire_restore", (PyCFunction)rlock_acquire_restore,
Victor Stinnere8794522014-01-02 12:47:24 +0100555 METH_VARARGS, rlock_acquire_restore_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000556 {"_release_save", (PyCFunction)rlock_release_save,
557 METH_NOARGS, rlock_release_save_doc},
Serhiy Storchaka62be7422018-11-27 13:27:31 +0200558 {"__enter__", (PyCFunction)(void(*)(void))rlock_acquire,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000559 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
560 {"__exit__", (PyCFunction)rlock_release,
561 METH_VARARGS, rlock_release_doc},
Victor Stinner87255be2020-04-07 23:11:49 +0200562#ifdef HAVE_FORK
563 {"_at_fork_reinit", (PyCFunction)rlock__at_fork_reinit,
564 METH_NOARGS, NULL},
565#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000566 {NULL, NULL} /* sentinel */
Antoine Pitrou434736a2009-11-10 18:46:01 +0000567};
568
569
Victor Stinner61040132020-12-18 01:39:00 +0100570static PyMemberDef rlock_type_members[] = {
571 {"__weaklistoffset__", T_PYSSIZET, offsetof(rlockobject, in_weakreflist), READONLY},
572 {NULL},
573};
574
575static PyType_Slot rlock_type_slots[] = {
576 {Py_tp_dealloc, (destructor)rlock_dealloc},
577 {Py_tp_repr, (reprfunc)rlock_repr},
578 {Py_tp_methods, rlock_methods},
579 {Py_tp_alloc, PyType_GenericAlloc},
580 {Py_tp_new, rlock_new},
581 {Py_tp_members, rlock_type_members},
582 {0, 0},
583};
584
585static PyType_Spec rlock_type_spec = {
586 .name = "_thread.RLock",
587 .basicsize = sizeof(rlockobject),
588 .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
589 .slots = rlock_type_slots,
Antoine Pitrou434736a2009-11-10 18:46:01 +0000590};
591
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000592static lockobject *
Victor Stinner61040132020-12-18 01:39:00 +0100593newlockobject(PyObject *module)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000594{
Victor Stinner61040132020-12-18 01:39:00 +0100595 thread_module_state *state = get_thread_state(module);
596
597 PyTypeObject *type = state->lock_type;
598 lockobject *self = (lockobject *)type->tp_alloc(type, 0);
Victor Stinner8203c732020-12-16 12:20:33 +0100599 if (self == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000600 return NULL;
Victor Stinner8203c732020-12-16 12:20:33 +0100601 }
602
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000603 self->lock_lock = PyThread_allocate_lock();
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +0000604 self->locked = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000605 self->in_weakreflist = NULL;
Victor Stinner8203c732020-12-16 12:20:33 +0100606
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000607 if (self->lock_lock == NULL) {
608 Py_DECREF(self);
609 PyErr_SetString(ThreadError, "can't allocate lock");
610 return NULL;
611 }
612 return self;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000613}
614
Jim Fultond15dc062004-07-14 19:11:50 +0000615/* Thread-local objects */
616
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000617/* Quick overview:
618
619 We need to be able to reclaim reference cycles as soon as possible
620 (both when a thread is being terminated, or a thread-local object
621 becomes unreachable from user data). Constraints:
622 - it must not be possible for thread-state dicts to be involved in
623 reference cycles (otherwise the cyclic GC will refuse to consider
624 objects referenced from a reachable thread-state dict, even though
625 local_dealloc would clear them)
626 - the death of a thread-state dict must still imply destruction of the
627 corresponding local dicts in all thread-local objects.
628
629 Our implementation uses small "localdummy" objects in order to break
630 the reference chain. These trivial objects are hashable (using the
631 default scheme of identity hashing) and weakrefable.
632 Each thread-state holds a separate localdummy for each local object
633 (as a /strong reference/),
634 and each thread-local object holds a dict mapping /weak references/
635 of localdummies to local dicts.
636
637 Therefore:
638 - only the thread-state dict holds a strong reference to the dummies
639 - only the thread-local object holds a strong reference to the local dicts
640 - only outside objects (application- or library-level) hold strong
641 references to the thread-local objects
642 - as soon as a thread-state dict is destroyed, the weakref callbacks of all
643 dummies attached to that thread are called, and destroy the corresponding
644 local dicts from thread-local objects
645 - as soon as a thread-local object is destroyed, its local dicts are
646 destroyed and its dummies are manually removed from all thread states
647 - the GC can do its work correctly when a thread-local object is dangling,
648 without any interference from the thread-state dicts
649
650 As an additional optimization, each localdummy holds a borrowed reference
651 to the corresponding localdict. This borrowed reference is only used
652 by the thread-local object which has created the localdummy, which should
653 guarantee that the localdict still exists when accessed.
654*/
655
656typedef struct {
657 PyObject_HEAD
658 PyObject *localdict; /* Borrowed reference! */
659 PyObject *weakreflist; /* List of weak references to self */
660} localdummyobject;
661
662static void
663localdummy_dealloc(localdummyobject *self)
664{
665 if (self->weakreflist != NULL)
666 PyObject_ClearWeakRefs((PyObject *) self);
Victor Stinner61040132020-12-18 01:39:00 +0100667 PyTypeObject *tp = Py_TYPE(self);
668 tp->tp_free((PyObject*)self);
669 Py_DECREF(tp);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000670}
671
Victor Stinner61040132020-12-18 01:39:00 +0100672static PyMemberDef local_dummy_type_members[] = {
673 {"__weaklistoffset__", T_PYSSIZET, offsetof(localdummyobject, weakreflist), READONLY},
674 {NULL},
675};
676
677static PyType_Slot local_dummy_type_slots[] = {
678 {Py_tp_dealloc, (destructor)localdummy_dealloc},
679 {Py_tp_doc, "Thread-local dummy"},
680 {Py_tp_members, local_dummy_type_members},
681 {0, 0}
682};
683
684static PyType_Spec local_dummy_type_spec = {
685 .name = "_thread._localdummy",
686 .basicsize = sizeof(localdummyobject),
Erlend Egeberg Aasland9746cda2021-04-30 16:04:57 +0200687 .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
Victor Stinner61040132020-12-18 01:39:00 +0100688 .slots = local_dummy_type_slots,
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000689};
690
691
Jim Fultond15dc062004-07-14 19:11:50 +0000692typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000693 PyObject_HEAD
694 PyObject *key;
695 PyObject *args;
696 PyObject *kw;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000697 PyObject *weakreflist; /* List of weak references to self */
698 /* A {localdummy weakref -> localdict} dict */
699 PyObject *dummies;
700 /* The callback for weakrefs to localdummies */
701 PyObject *wr_callback;
Jim Fultond15dc062004-07-14 19:11:50 +0000702} localobject;
703
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000704/* Forward declaration */
Victor Stinner61040132020-12-18 01:39:00 +0100705static PyObject *_ldict(localobject *self, thread_module_state *state);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000706static PyObject *_localdummy_destroyed(PyObject *meth_self, PyObject *dummyweakref);
707
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000708/* Create and register the dummy for the current thread.
709 Returns a borrowed reference of the corresponding local dict */
710static PyObject *
Victor Stinner61040132020-12-18 01:39:00 +0100711_local_create_dummy(localobject *self, thread_module_state *state)
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000712{
Victor Stinner8203c732020-12-16 12:20:33 +0100713 PyObject *ldict = NULL, *wr = NULL;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000714 localdummyobject *dummy = NULL;
Victor Stinner61040132020-12-18 01:39:00 +0100715 PyTypeObject *type = state->local_dummy_type;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000716
Victor Stinner8203c732020-12-16 12:20:33 +0100717 PyObject *tdict = PyThreadState_GetDict();
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000718 if (tdict == NULL) {
719 PyErr_SetString(PyExc_SystemError,
720 "Couldn't get thread-state dictionary");
721 goto err;
722 }
723
724 ldict = PyDict_New();
Victor Stinner8203c732020-12-16 12:20:33 +0100725 if (ldict == NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000726 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100727 }
Victor Stinner61040132020-12-18 01:39:00 +0100728 dummy = (localdummyobject *) type->tp_alloc(type, 0);
Victor Stinner8203c732020-12-16 12:20:33 +0100729 if (dummy == NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000730 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100731 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000732 dummy->localdict = ldict;
733 wr = PyWeakref_NewRef((PyObject *) dummy, self->wr_callback);
Victor Stinner8203c732020-12-16 12:20:33 +0100734 if (wr == NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000735 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100736 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000737
738 /* As a side-effect, this will cache the weakref's hash before the
739 dummy gets deleted */
Victor Stinner8203c732020-12-16 12:20:33 +0100740 int r = PyDict_SetItem(self->dummies, wr, ldict);
741 if (r < 0) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000742 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100743 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000744 Py_CLEAR(wr);
745 r = PyDict_SetItem(tdict, self->key, (PyObject *) dummy);
Victor Stinner8203c732020-12-16 12:20:33 +0100746 if (r < 0) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000747 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100748 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000749 Py_CLEAR(dummy);
750
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000751 Py_DECREF(ldict);
752 return ldict;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000753
754err:
755 Py_XDECREF(ldict);
756 Py_XDECREF(wr);
757 Py_XDECREF(dummy);
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000758 return NULL;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000759}
760
Jim Fultond15dc062004-07-14 19:11:50 +0000761static PyObject *
762local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
763{
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000764 static PyMethodDef wr_callback_def = {
765 "_localdummy_destroyed", (PyCFunction) _localdummy_destroyed, METH_O
766 };
Jim Fultond15dc062004-07-14 19:11:50 +0000767
Serhiy Storchakafa494fd2015-05-30 17:45:22 +0300768 if (type->tp_init == PyBaseObject_Type.tp_init) {
769 int rc = 0;
770 if (args != NULL)
771 rc = PyObject_IsTrue(args);
772 if (rc == 0 && kw != NULL)
773 rc = PyObject_IsTrue(kw);
774 if (rc != 0) {
Victor Stinner8203c732020-12-16 12:20:33 +0100775 if (rc > 0) {
Serhiy Storchakafa494fd2015-05-30 17:45:22 +0300776 PyErr_SetString(PyExc_TypeError,
777 "Initialization arguments are not supported");
Victor Stinner8203c732020-12-16 12:20:33 +0100778 }
Serhiy Storchakafa494fd2015-05-30 17:45:22 +0300779 return NULL;
780 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000781 }
Jim Fultond15dc062004-07-14 19:11:50 +0000782
Victor Stinner61040132020-12-18 01:39:00 +0100783 PyObject *module = _PyType_GetModuleByDef(type, &thread_module);
784 thread_module_state *state = get_thread_state(module);
785
786 localobject *self = (localobject *)type->tp_alloc(type, 0);
Victor Stinner8203c732020-12-16 12:20:33 +0100787 if (self == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000788 return NULL;
Victor Stinner8203c732020-12-16 12:20:33 +0100789 }
Jim Fultond15dc062004-07-14 19:11:50 +0000790
Victor Stinner8203c732020-12-16 12:20:33 +0100791 self->args = Py_XNewRef(args);
792 self->kw = Py_XNewRef(kw);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000793 self->key = PyUnicode_FromFormat("thread.local.%p", self);
Victor Stinner8203c732020-12-16 12:20:33 +0100794 if (self->key == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000795 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100796 }
Jim Fultond15dc062004-07-14 19:11:50 +0000797
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000798 self->dummies = PyDict_New();
Victor Stinner8203c732020-12-16 12:20:33 +0100799 if (self->dummies == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000800 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100801 }
Jim Fultond15dc062004-07-14 19:11:50 +0000802
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000803 /* We use a weak reference to self in the callback closure
804 in order to avoid spurious reference cycles */
Victor Stinner8203c732020-12-16 12:20:33 +0100805 PyObject *wr = PyWeakref_NewRef((PyObject *) self, NULL);
806 if (wr == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000807 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100808 }
Andrew Svetlov3ba3a3e2012-12-25 13:32:35 +0200809 self->wr_callback = PyCFunction_NewEx(&wr_callback_def, wr, NULL);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000810 Py_DECREF(wr);
Victor Stinner8203c732020-12-16 12:20:33 +0100811 if (self->wr_callback == NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000812 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100813 }
Victor Stinner61040132020-12-18 01:39:00 +0100814 if (_local_create_dummy(self, state) == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000815 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100816 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000817 return (PyObject *)self;
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000818
819 err:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000820 Py_DECREF(self);
821 return NULL;
Jim Fultond15dc062004-07-14 19:11:50 +0000822}
823
824static int
825local_traverse(localobject *self, visitproc visit, void *arg)
826{
Victor Stinner61040132020-12-18 01:39:00 +0100827 Py_VISIT(Py_TYPE(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000828 Py_VISIT(self->args);
829 Py_VISIT(self->kw);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000830 Py_VISIT(self->dummies);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000831 return 0;
Jim Fultond15dc062004-07-14 19:11:50 +0000832}
833
834static int
835local_clear(localobject *self)
836{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000837 Py_CLEAR(self->args);
838 Py_CLEAR(self->kw);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000839 Py_CLEAR(self->dummies);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000840 Py_CLEAR(self->wr_callback);
841 /* Remove all strong references to dummies from the thread states */
Victor Stinner839184f2021-02-19 15:51:36 +0100842 if (self->key) {
843 PyInterpreterState *interp = _PyInterpreterState_GET();
844 PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
845 for(; tstate; tstate = PyThreadState_Next(tstate)) {
846 if (tstate->dict == NULL) {
847 continue;
Serhiy Storchaka8905fcc2018-12-11 08:38:03 +0200848 }
Victor Stinner839184f2021-02-19 15:51:36 +0100849 PyObject *v = _PyDict_Pop(tstate->dict, self->key, Py_None);
850 if (v != NULL) {
851 Py_DECREF(v);
852 }
853 else {
854 PyErr_Clear();
855 }
856 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000857 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000858 return 0;
859}
Jim Fultond15dc062004-07-14 19:11:50 +0000860
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000861static void
862local_dealloc(localobject *self)
863{
864 /* Weakrefs must be invalidated right now, otherwise they can be used
865 from code called below, which is very dangerous since Py_REFCNT(self) == 0 */
Victor Stinner8203c732020-12-16 12:20:33 +0100866 if (self->weakreflist != NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000867 PyObject_ClearWeakRefs((PyObject *) self);
Victor Stinner8203c732020-12-16 12:20:33 +0100868 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000869
870 PyObject_GC_UnTrack(self);
871
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000872 local_clear(self);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000873 Py_XDECREF(self->key);
Victor Stinner61040132020-12-18 01:39:00 +0100874
875 PyTypeObject *tp = Py_TYPE(self);
876 tp->tp_free((PyObject*)self);
877 Py_DECREF(tp);
Jim Fultond15dc062004-07-14 19:11:50 +0000878}
879
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000880/* Returns a borrowed reference to the local dict, creating it if necessary */
Jim Fultond15dc062004-07-14 19:11:50 +0000881static PyObject *
Victor Stinner61040132020-12-18 01:39:00 +0100882_ldict(localobject *self, thread_module_state *state)
Jim Fultond15dc062004-07-14 19:11:50 +0000883{
Victor Stinner8203c732020-12-16 12:20:33 +0100884 PyObject *tdict = PyThreadState_GetDict();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000885 if (tdict == NULL) {
886 PyErr_SetString(PyExc_SystemError,
887 "Couldn't get thread-state dictionary");
888 return NULL;
889 }
Jim Fultond15dc062004-07-14 19:11:50 +0000890
Victor Stinner8203c732020-12-16 12:20:33 +0100891 PyObject *ldict;
892 PyObject *dummy = PyDict_GetItemWithError(tdict, self->key);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000893 if (dummy == NULL) {
Serhiy Storchakaa24107b2019-02-25 17:59:46 +0200894 if (PyErr_Occurred()) {
895 return NULL;
896 }
Victor Stinner61040132020-12-18 01:39:00 +0100897 ldict = _local_create_dummy(self, state);
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000898 if (ldict == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000899 return NULL;
Jim Fultond15dc062004-07-14 19:11:50 +0000900
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000901 if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init &&
902 Py_TYPE(self)->tp_init((PyObject*)self,
903 self->args, self->kw) < 0) {
904 /* we need to get rid of ldict from thread so
905 we create a new one the next time we do an attr
Ezio Melotti42da6632011-03-15 05:18:48 +0200906 access */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000907 PyDict_DelItem(tdict, self->key);
908 return NULL;
909 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000910 }
911 else {
Victor Stinner61040132020-12-18 01:39:00 +0100912 assert(Py_IS_TYPE(dummy, state->local_dummy_type));
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000913 ldict = ((localdummyobject *) dummy)->localdict;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000914 }
Jim Fultond15dc062004-07-14 19:11:50 +0000915
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000916 return ldict;
Jim Fultond15dc062004-07-14 19:11:50 +0000917}
918
Jim Fultond15dc062004-07-14 19:11:50 +0000919static int
920local_setattro(localobject *self, PyObject *name, PyObject *v)
921{
Victor Stinner61040132020-12-18 01:39:00 +0100922 PyObject *module = _PyType_GetModuleByDef(Py_TYPE(self), &thread_module);
923 thread_module_state *state = get_thread_state(module);
924
925 PyObject *ldict = _ldict(self, state);
Victor Stinner8203c732020-12-16 12:20:33 +0100926 if (ldict == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000927 return -1;
Victor Stinner8203c732020-12-16 12:20:33 +0100928 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000929
Victor Stinner8203c732020-12-16 12:20:33 +0100930 PyObject *str_dict = _PyUnicode_FromId(&PyId___dict__); // borrowed ref
931 if (str_dict == NULL) {
932 return -1;
933 }
934
935 int r = PyObject_RichCompareBool(name, str_dict, Py_EQ);
936 if (r == -1) {
937 return -1;
938 }
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000939 if (r == 1) {
940 PyErr_Format(PyExc_AttributeError,
941 "'%.50s' object attribute '%U' is read-only",
942 Py_TYPE(self)->tp_name, name);
943 return -1;
944 }
Jim Fultond15dc062004-07-14 19:11:50 +0000945
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000946 return _PyObject_GenericSetAttrWithDict((PyObject *)self, name, v, ldict);
Jim Fultond15dc062004-07-14 19:11:50 +0000947}
948
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000949static PyObject *local_getattro(localobject *, PyObject *);
950
Victor Stinner61040132020-12-18 01:39:00 +0100951static PyMemberDef local_type_members[] = {
952 {"__weaklistoffset__", T_PYSSIZET, offsetof(localobject, weakreflist), READONLY},
953 {NULL},
954};
955
956static PyType_Slot local_type_slots[] = {
957 {Py_tp_dealloc, (destructor)local_dealloc},
958 {Py_tp_getattro, (getattrofunc)local_getattro},
959 {Py_tp_setattro, (setattrofunc)local_setattro},
960 {Py_tp_doc, "Thread-local data"},
961 {Py_tp_traverse, (traverseproc)local_traverse},
962 {Py_tp_clear, (inquiry)local_clear},
963 {Py_tp_new, local_new},
964 {Py_tp_members, local_type_members},
965 {0, 0}
966};
967
968static PyType_Spec local_type_spec = {
969 .name = "_thread._local",
970 .basicsize = sizeof(localobject),
971 .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
972 .slots = local_type_slots,
Jim Fultond15dc062004-07-14 19:11:50 +0000973};
974
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000975static PyObject *
976local_getattro(localobject *self, PyObject *name)
977{
Victor Stinner61040132020-12-18 01:39:00 +0100978 PyObject *module = _PyType_GetModuleByDef(Py_TYPE(self), &thread_module);
979 thread_module_state *state = get_thread_state(module);
980
981 PyObject *ldict = _ldict(self, state);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000982 if (ldict == NULL)
983 return NULL;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000984
Victor Stinner8203c732020-12-16 12:20:33 +0100985 PyObject *str_dict = _PyUnicode_FromId(&PyId___dict__); // borrowed ref
986 if (str_dict == NULL) {
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000987 return NULL;
Victor Stinner8203c732020-12-16 12:20:33 +0100988 }
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000989
Victor Stinner8203c732020-12-16 12:20:33 +0100990 int r = PyObject_RichCompareBool(name, str_dict, Py_EQ);
991 if (r == 1) {
992 return Py_NewRef(ldict);
993 }
994 if (r == -1) {
995 return NULL;
996 }
997
Victor Stinner61040132020-12-18 01:39:00 +0100998 if (!Py_IS_TYPE(self, state->local_type)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000999 /* use generic lookup for subtypes */
Victor Stinner8203c732020-12-16 12:20:33 +01001000 return _PyObject_GenericGetAttrWithDict((PyObject *)self, name,
1001 ldict, 0);
1002 }
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001003
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001004 /* Optimization: just look in dict ourselves */
Victor Stinner8203c732020-12-16 12:20:33 +01001005 PyObject *value = PyDict_GetItemWithError(ldict, name);
Serhiy Storchakaa24107b2019-02-25 17:59:46 +02001006 if (value != NULL) {
Victor Stinner8203c732020-12-16 12:20:33 +01001007 return Py_NewRef(value);
Serhiy Storchakaa24107b2019-02-25 17:59:46 +02001008 }
Victor Stinner8203c732020-12-16 12:20:33 +01001009 if (PyErr_Occurred()) {
Serhiy Storchakaa24107b2019-02-25 17:59:46 +02001010 return NULL;
1011 }
Victor Stinner8203c732020-12-16 12:20:33 +01001012
Serhiy Storchakaa24107b2019-02-25 17:59:46 +02001013 /* Fall back on generic to get __class__ and __dict__ */
1014 return _PyObject_GenericGetAttrWithDict(
1015 (PyObject *)self, name, ldict, 0);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001016}
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001017
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001018/* Called when a dummy is destroyed. */
1019static PyObject *
1020_localdummy_destroyed(PyObject *localweakref, PyObject *dummyweakref)
1021{
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001022 assert(PyWeakref_CheckRef(localweakref));
Victor Stinner8203c732020-12-16 12:20:33 +01001023 PyObject *obj = PyWeakref_GET_OBJECT(localweakref);
1024 if (obj == Py_None) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001025 Py_RETURN_NONE;
Victor Stinner8203c732020-12-16 12:20:33 +01001026 }
1027
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001028 /* If the thread-local object is still alive and not being cleared,
1029 remove the corresponding local dict */
Victor Stinner8203c732020-12-16 12:20:33 +01001030 localobject *self = (localobject *)Py_NewRef(obj);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001031 if (self->dummies != NULL) {
1032 PyObject *ldict;
Serhiy Storchakaa24107b2019-02-25 17:59:46 +02001033 ldict = PyDict_GetItemWithError(self->dummies, dummyweakref);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001034 if (ldict != NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001035 PyDict_DelItem(self->dummies, dummyweakref);
1036 }
1037 if (PyErr_Occurred())
1038 PyErr_WriteUnraisable(obj);
1039 }
1040 Py_DECREF(obj);
1041 Py_RETURN_NONE;
1042}
1043
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001044/* Module functions */
1045
Guido van Rossuma027efa1997-05-05 20:56:21 +00001046struct bootstate {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001047 PyInterpreterState *interp;
1048 PyObject *func;
1049 PyObject *args;
Victor Stinner8203c732020-12-16 12:20:33 +01001050 PyObject *kwargs;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001051 PyThreadState *tstate;
Joannah Nanjekye2bc43cd2019-09-05 13:06:49 -03001052 _PyRuntimeState *runtime;
Guido van Rossuma027efa1997-05-05 20:56:21 +00001053};
1054
Victor Stinner8203c732020-12-16 12:20:33 +01001055
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001056static void
Victor Stinner8203c732020-12-16 12:20:33 +01001057thread_bootstate_free(struct bootstate *boot)
1058{
1059 Py_DECREF(boot->func);
1060 Py_DECREF(boot->args);
1061 Py_XDECREF(boot->kwargs);
1062 PyMem_Free(boot);
1063}
1064
1065
1066static void
1067thread_run(void *boot_raw)
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001068{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001069 struct bootstate *boot = (struct bootstate *) boot_raw;
1070 PyThreadState *tstate;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001071
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001072 tstate = boot->tstate;
1073 tstate->thread_id = PyThread_get_thread_ident();
Victor Stinner01b1cc12019-11-20 02:27:56 +01001074 _PyThreadState_Init(tstate);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001075 PyEval_AcquireThread(tstate);
Eric Snow2ebc5ce2017-09-07 23:51:28 -06001076 tstate->interp->num_threads++;
Victor Stinner8203c732020-12-16 12:20:33 +01001077
1078 PyObject *res = PyObject_Call(boot->func, boot->args, boot->kwargs);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001079 if (res == NULL) {
1080 if (PyErr_ExceptionMatches(PyExc_SystemExit))
Victor Stinner8b095002019-05-29 02:57:56 +02001081 /* SystemExit is ignored silently */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001082 PyErr_Clear();
1083 else {
Victor Stinner8b095002019-05-29 02:57:56 +02001084 _PyErr_WriteUnraisableMsg("in thread started by", boot->func);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001085 }
1086 }
Victor Stinner8b095002019-05-29 02:57:56 +02001087 else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001088 Py_DECREF(res);
Victor Stinner8b095002019-05-29 02:57:56 +02001089 }
Victor Stinner8203c732020-12-16 12:20:33 +01001090
1091 thread_bootstate_free(boot);
Eric Snow2ebc5ce2017-09-07 23:51:28 -06001092 tstate->interp->num_threads--;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001093 PyThreadState_Clear(tstate);
Victor Stinner23ef89d2020-03-18 02:26:04 +01001094 _PyThreadState_DeleteCurrent(tstate);
Victor Stinner8203c732020-12-16 12:20:33 +01001095
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001096 PyThread_exit_thread();
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001097}
1098
Barry Warsawd0c10421996-12-17 00:05:22 +00001099static PyObject *
Peter Schneider-Kamp3707efe2000-07-10 10:03:58 +00001100thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001101{
Joannah Nanjekye2bc43cd2019-09-05 13:06:49 -03001102 _PyRuntimeState *runtime = &_PyRuntime;
Victor Stinner8203c732020-12-16 12:20:33 +01001103 PyObject *func, *args, *kwargs = NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001104
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001105 if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3,
Victor Stinner8203c732020-12-16 12:20:33 +01001106 &func, &args, &kwargs))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001107 return NULL;
1108 if (!PyCallable_Check(func)) {
1109 PyErr_SetString(PyExc_TypeError,
1110 "first arg must be callable");
1111 return NULL;
1112 }
1113 if (!PyTuple_Check(args)) {
1114 PyErr_SetString(PyExc_TypeError,
1115 "2nd arg must be a tuple");
1116 return NULL;
1117 }
Victor Stinner8203c732020-12-16 12:20:33 +01001118 if (kwargs != NULL && !PyDict_Check(kwargs)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001119 PyErr_SetString(PyExc_TypeError,
1120 "optional 3rd arg must be a dictionary");
1121 return NULL;
1122 }
Victor Stinner252346a2020-05-01 11:33:44 +02001123
1124 PyInterpreterState *interp = _PyInterpreterState_GET();
1125 if (interp->config._isolated_interpreter) {
1126 PyErr_SetString(PyExc_RuntimeError,
1127 "thread is not supported for isolated subinterpreters");
1128 return NULL;
1129 }
1130
Victor Stinner8203c732020-12-16 12:20:33 +01001131 struct bootstate *boot = PyMem_NEW(struct bootstate, 1);
1132 if (boot == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001133 return PyErr_NoMemory();
Victor Stinner8203c732020-12-16 12:20:33 +01001134 }
Victor Stinner81a7be32020-04-14 15:14:01 +02001135 boot->interp = _PyInterpreterState_GET();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001136 boot->tstate = _PyThreadState_Prealloc(boot->interp);
1137 if (boot->tstate == NULL) {
Victor Stinner00d7abd2020-12-01 09:56:42 +01001138 PyMem_Free(boot);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001139 return PyErr_NoMemory();
1140 }
Victor Stinner8203c732020-12-16 12:20:33 +01001141 boot->runtime = runtime;
1142 boot->func = Py_NewRef(func);
1143 boot->args = Py_NewRef(args);
1144 boot->kwargs = Py_XNewRef(kwargs);
Victor Stinner3225b9f2020-03-09 20:56:57 +01001145
Victor Stinner8203c732020-12-16 12:20:33 +01001146 unsigned long ident = PyThread_start_new_thread(thread_run, (void*) boot);
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001147 if (ident == PYTHREAD_INVALID_THREAD_ID) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001148 PyErr_SetString(ThreadError, "can't start new thread");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001149 PyThreadState_Clear(boot->tstate);
Victor Stinner8203c732020-12-16 12:20:33 +01001150 thread_bootstate_free(boot);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001151 return NULL;
1152 }
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001153 return PyLong_FromUnsignedLong(ident);
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001154}
1155
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001156PyDoc_STRVAR(start_new_doc,
Andrew M. Kuchling38300c62001-10-05 12:24:15 +00001157"start_new_thread(function, args[, kwargs])\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001158(start_new() is an obsolete synonym)\n\
1159\n\
Guido van Rossum3c288632001-10-16 21:13:49 +00001160Start a new thread and return its identifier. The thread will call the\n\
1161function with positional arguments from the tuple args and keyword arguments\n\
1162taken from the optional dictionary kwargs. The thread exits when the\n\
1163function returns; the return value is ignored. The thread will also exit\n\
1164when the function raises an unhandled exception; a stack trace will be\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001165printed unless the exception is SystemExit.\n");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001166
Barry Warsawd0c10421996-12-17 00:05:22 +00001167static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301168thread_PyThread_exit_thread(PyObject *self, PyObject *Py_UNUSED(ignored))
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001169{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001170 PyErr_SetNone(PyExc_SystemExit);
1171 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001172}
1173
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001174PyDoc_STRVAR(exit_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001175"exit()\n\
Éric Araujo9bcf8bf2011-05-31 14:08:26 +02001176(exit_thread() is an obsolete synonym)\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001177\n\
1178This is synonymous to ``raise SystemExit''. It will cause the current\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001179thread to exit silently unless the exception is caught.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001180
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001181static PyObject *
Antoine Pitrouba251c22021-03-11 23:35:45 +01001182thread_PyThread_interrupt_main(PyObject *self, PyObject *args)
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001183{
Antoine Pitrouba251c22021-03-11 23:35:45 +01001184 int signum = SIGINT;
1185 if (!PyArg_ParseTuple(args, "|i:signum", &signum)) {
1186 return NULL;
1187 }
1188
1189 if (PyErr_SetInterruptEx(signum)) {
1190 PyErr_SetString(PyExc_ValueError, "signal number out of range");
1191 return NULL;
1192 }
Serhiy Storchaka228b12e2017-01-23 09:47:21 +02001193 Py_RETURN_NONE;
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001194}
1195
1196PyDoc_STRVAR(interrupt_doc,
Antoine Pitrouba251c22021-03-11 23:35:45 +01001197"interrupt_main(signum=signal.SIGINT, /)\n\
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001198\n\
Antoine Pitrouba251c22021-03-11 23:35:45 +01001199Simulate the arrival of the given signal in the main thread,\n\
1200where the corresponding signal handler will be executed.\n\
1201If *signum* is omitted, SIGINT is assumed.\n\
1202A subthread can use this function to interrupt the main thread.\n\
1203\n\
1204Note: the default signal hander for SIGINT raises ``KeyboardInterrupt``."
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001205);
1206
Victor Stinner61040132020-12-18 01:39:00 +01001207static lockobject *newlockobject(PyObject *module);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001208
Barry Warsawd0c10421996-12-17 00:05:22 +00001209static PyObject *
Victor Stinner8203c732020-12-16 12:20:33 +01001210thread_PyThread_allocate_lock(PyObject *module, PyObject *Py_UNUSED(ignored))
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001211{
Victor Stinner61040132020-12-18 01:39:00 +01001212 return (PyObject *) newlockobject(module);
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001213}
1214
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001215PyDoc_STRVAR(allocate_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001216"allocate_lock() -> lock object\n\
1217(allocate() is an obsolete synonym)\n\
1218\n\
Berker Peksag720e6552016-05-02 12:25:35 +03001219Create a new lock object. See help(type(threading.Lock())) for\n\
1220information about locks.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001221
Barry Warsawd0c10421996-12-17 00:05:22 +00001222static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301223thread_get_ident(PyObject *self, PyObject *Py_UNUSED(ignored))
Guido van Rossumb6775db1994-08-01 11:34:53 +00001224{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001225 unsigned long ident = PyThread_get_thread_ident();
1226 if (ident == PYTHREAD_INVALID_THREAD_ID) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001227 PyErr_SetString(ThreadError, "no current thread ident");
1228 return NULL;
1229 }
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001230 return PyLong_FromUnsignedLong(ident);
Guido van Rossumb6775db1994-08-01 11:34:53 +00001231}
1232
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001233PyDoc_STRVAR(get_ident_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001234"get_ident() -> integer\n\
1235\n\
1236Return a non-zero integer that uniquely identifies the current thread\n\
1237amongst other threads that exist simultaneously.\n\
1238This may be used to identify per-thread resources.\n\
1239Even though on some platforms threads identities may appear to be\n\
1240allocated consecutive numbers starting at 1, this behavior should not\n\
1241be relied upon, and the number should be seen purely as a magic cookie.\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001242A thread's identity may be reused for another thread after it exits.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001243
Jake Teslerb121f632019-05-22 08:43:17 -07001244#ifdef PY_HAVE_THREAD_NATIVE_ID
1245static PyObject *
1246thread_get_native_id(PyObject *self, PyObject *Py_UNUSED(ignored))
1247{
1248 unsigned long native_id = PyThread_get_thread_native_id();
1249 return PyLong_FromUnsignedLong(native_id);
1250}
1251
1252PyDoc_STRVAR(get_native_id_doc,
1253"get_native_id() -> integer\n\
1254\n\
1255Return a non-negative integer identifying the thread as reported\n\
1256by the OS (kernel). This may be used to uniquely identify a\n\
1257particular thread within a system.");
1258#endif
1259
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001260static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301261thread__count(PyObject *self, PyObject *Py_UNUSED(ignored))
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001262{
Victor Stinner81a7be32020-04-14 15:14:01 +02001263 PyInterpreterState *interp = _PyInterpreterState_GET();
Victor Stinnercaba55b2018-08-03 15:33:52 +02001264 return PyLong_FromLong(interp->num_threads);
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001265}
1266
1267PyDoc_STRVAR(_count_doc,
1268"_count() -> integer\n\
1269\n\
Antoine Pitrou9257f5e2009-10-30 22:23:02 +00001270\
oldkaa0735f2018-02-02 16:52:55 +08001271Return the number of currently running Python threads, excluding\n\
Antoine Pitrou9257f5e2009-10-30 22:23:02 +00001272the main thread. The returned number comprises all threads created\n\
1273through `start_new_thread()` as well as `threading.Thread`, and not\n\
1274yet finished.\n\
1275\n\
1276This function is meant for internal and specialized purposes only.\n\
1277In most applications `threading.enumerate()` should be used instead.");
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001278
Antoine Pitrou7b476992013-09-07 23:38:37 +02001279static void
Victor Stinnera42de742018-11-22 10:25:22 +01001280release_sentinel(void *wr_raw)
Antoine Pitrou7b476992013-09-07 23:38:37 +02001281{
Victor Stinnera42de742018-11-22 10:25:22 +01001282 PyObject *wr = _PyObject_CAST(wr_raw);
Antoine Pitrou7b476992013-09-07 23:38:37 +02001283 /* Tricky: this function is called when the current thread state
1284 is being deleted. Therefore, only simple C code can safely
1285 execute here. */
1286 PyObject *obj = PyWeakref_GET_OBJECT(wr);
1287 lockobject *lock;
1288 if (obj != Py_None) {
Antoine Pitrou7b476992013-09-07 23:38:37 +02001289 lock = (lockobject *) obj;
1290 if (lock->locked) {
1291 PyThread_release_lock(lock->lock_lock);
1292 lock->locked = 0;
1293 }
1294 }
1295 /* Deallocating a weakref with a NULL callback only calls
1296 PyObject_GC_Del(), which can't call any Python code. */
1297 Py_DECREF(wr);
1298}
1299
1300static PyObject *
Victor Stinner8203c732020-12-16 12:20:33 +01001301thread__set_sentinel(PyObject *module, PyObject *Py_UNUSED(ignored))
Antoine Pitrou7b476992013-09-07 23:38:37 +02001302{
1303 PyObject *wr;
1304 PyThreadState *tstate = PyThreadState_Get();
1305 lockobject *lock;
1306
1307 if (tstate->on_delete_data != NULL) {
1308 /* We must support the re-creation of the lock from a
1309 fork()ed child. */
1310 assert(tstate->on_delete == &release_sentinel);
1311 wr = (PyObject *) tstate->on_delete_data;
1312 tstate->on_delete = NULL;
1313 tstate->on_delete_data = NULL;
1314 Py_DECREF(wr);
1315 }
Victor Stinner61040132020-12-18 01:39:00 +01001316 lock = newlockobject(module);
Antoine Pitrou7b476992013-09-07 23:38:37 +02001317 if (lock == NULL)
1318 return NULL;
1319 /* The lock is owned by whoever called _set_sentinel(), but the weakref
1320 hangs to the thread state. */
1321 wr = PyWeakref_NewRef((PyObject *) lock, NULL);
1322 if (wr == NULL) {
1323 Py_DECREF(lock);
1324 return NULL;
1325 }
1326 tstate->on_delete_data = (void *) wr;
1327 tstate->on_delete = &release_sentinel;
1328 return (PyObject *) lock;
1329}
1330
1331PyDoc_STRVAR(_set_sentinel_doc,
1332"_set_sentinel() -> lock\n\
1333\n\
1334Set a sentinel lock that will be released when the current thread\n\
1335state is finalized (after it is untied from the interpreter).\n\
1336\n\
1337This is a private API for the threading module.");
1338
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001339static PyObject *
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001340thread_stack_size(PyObject *self, PyObject *args)
1341{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001342 size_t old_size;
1343 Py_ssize_t new_size = 0;
1344 int rc;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001345
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001346 if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size))
1347 return NULL;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001348
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001349 if (new_size < 0) {
1350 PyErr_SetString(PyExc_ValueError,
1351 "size must be 0 or a positive value");
1352 return NULL;
1353 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001354
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001355 old_size = PyThread_get_stacksize();
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001356
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001357 rc = PyThread_set_stacksize((size_t) new_size);
1358 if (rc == -1) {
1359 PyErr_Format(PyExc_ValueError,
1360 "size not valid: %zd bytes",
1361 new_size);
1362 return NULL;
1363 }
1364 if (rc == -2) {
1365 PyErr_SetString(ThreadError,
1366 "setting stack size not supported");
1367 return NULL;
1368 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001369
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001370 return PyLong_FromSsize_t((Py_ssize_t) old_size);
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001371}
1372
1373PyDoc_STRVAR(stack_size_doc,
1374"stack_size([size]) -> size\n\
1375\n\
1376Return the thread stack size used when creating new threads. The\n\
1377optional size argument specifies the stack size (in bytes) to be used\n\
1378for subsequently created threads, and must be 0 (use platform or\n\
1379configured default) or a positive integer value of at least 32,768 (32k).\n\
1380If changing the thread stack size is unsupported, a ThreadError\n\
1381exception is raised. If the specified size is invalid, a ValueError\n\
1382exception is raised, and the stack size is unmodified. 32k bytes\n\
1383 currently the minimum supported stack size value to guarantee\n\
1384sufficient stack space for the interpreter itself.\n\
1385\n\
1386Note that some platforms may have particular restrictions on values for\n\
Victor Stinner8c663fd2017-11-08 14:44:44 -08001387the stack size, such as requiring a minimum stack size larger than 32 KiB or\n\
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001388requiring allocation in multiples of the system memory page size\n\
1389- platform documentation should be referred to for more information\n\
Victor Stinner8c663fd2017-11-08 14:44:44 -08001390(4 KiB pages are common; using multiples of 4096 for the stack size is\n\
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001391the suggested approach in the absence of more specific information).");
1392
Victor Stinnercd590a72019-05-28 00:39:52 +02001393static int
1394thread_excepthook_file(PyObject *file, PyObject *exc_type, PyObject *exc_value,
1395 PyObject *exc_traceback, PyObject *thread)
1396{
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001397 _Py_IDENTIFIER(name);
Victor Stinnercd590a72019-05-28 00:39:52 +02001398 /* print(f"Exception in thread {thread.name}:", file=file) */
1399 if (PyFile_WriteString("Exception in thread ", file) < 0) {
1400 return -1;
1401 }
1402
1403 PyObject *name = NULL;
1404 if (thread != Py_None) {
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001405 if (_PyObject_LookupAttrId(thread, &PyId_name, &name) < 0) {
1406 return -1;
1407 }
Victor Stinnercd590a72019-05-28 00:39:52 +02001408 }
1409 if (name != NULL) {
1410 if (PyFile_WriteObject(name, file, Py_PRINT_RAW) < 0) {
1411 Py_DECREF(name);
1412 return -1;
1413 }
1414 Py_DECREF(name);
1415 }
1416 else {
Victor Stinnercd590a72019-05-28 00:39:52 +02001417 unsigned long ident = PyThread_get_thread_ident();
1418 PyObject *str = PyUnicode_FromFormat("%lu", ident);
1419 if (str != NULL) {
1420 if (PyFile_WriteObject(str, file, Py_PRINT_RAW) < 0) {
1421 Py_DECREF(str);
1422 return -1;
1423 }
1424 Py_DECREF(str);
1425 }
1426 else {
1427 PyErr_Clear();
1428
1429 if (PyFile_WriteString("<failed to get thread name>", file) < 0) {
1430 return -1;
1431 }
1432 }
1433 }
1434
1435 if (PyFile_WriteString(":\n", file) < 0) {
1436 return -1;
1437 }
1438
1439 /* Display the traceback */
1440 _PyErr_Display(file, exc_type, exc_value, exc_traceback);
1441
1442 /* Call file.flush() */
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001443 PyObject *res = _PyObject_CallMethodIdNoArgs(file, &PyId_flush);
Victor Stinnercd590a72019-05-28 00:39:52 +02001444 if (!res) {
1445 return -1;
1446 }
1447 Py_DECREF(res);
1448
1449 return 0;
1450}
1451
1452
1453PyDoc_STRVAR(ExceptHookArgs__doc__,
1454"ExceptHookArgs\n\
1455\n\
1456Type used to pass arguments to threading.excepthook.");
1457
1458static PyTypeObject ExceptHookArgsType;
1459
1460static PyStructSequence_Field ExceptHookArgs_fields[] = {
1461 {"exc_type", "Exception type"},
1462 {"exc_value", "Exception value"},
1463 {"exc_traceback", "Exception traceback"},
1464 {"thread", "Thread"},
1465 {0}
1466};
1467
1468static PyStructSequence_Desc ExceptHookArgs_desc = {
Victor Stinner8203c732020-12-16 12:20:33 +01001469 .name = "_thread._ExceptHookArgs",
Victor Stinnercd590a72019-05-28 00:39:52 +02001470 .doc = ExceptHookArgs__doc__,
1471 .fields = ExceptHookArgs_fields,
1472 .n_in_sequence = 4
1473};
1474
1475
1476static PyObject *
1477thread_excepthook(PyObject *self, PyObject *args)
1478{
Andy Lester55728702020-03-06 16:53:17 -06001479 if (!Py_IS_TYPE(args, &ExceptHookArgsType)) {
Victor Stinnercd590a72019-05-28 00:39:52 +02001480 PyErr_SetString(PyExc_TypeError,
1481 "_thread.excepthook argument type "
1482 "must be ExceptHookArgs");
1483 return NULL;
1484 }
1485
1486 /* Borrowed reference */
1487 PyObject *exc_type = PyStructSequence_GET_ITEM(args, 0);
1488 if (exc_type == PyExc_SystemExit) {
1489 /* silently ignore SystemExit */
1490 Py_RETURN_NONE;
1491 }
1492
1493 /* Borrowed references */
1494 PyObject *exc_value = PyStructSequence_GET_ITEM(args, 1);
1495 PyObject *exc_tb = PyStructSequence_GET_ITEM(args, 2);
1496 PyObject *thread = PyStructSequence_GET_ITEM(args, 3);
1497
1498 PyObject *file = _PySys_GetObjectId(&PyId_stderr);
1499 if (file == NULL || file == Py_None) {
1500 if (thread == Py_None) {
1501 /* do nothing if sys.stderr is None and thread is None */
1502 Py_RETURN_NONE;
1503 }
1504
1505 file = PyObject_GetAttrString(thread, "_stderr");
1506 if (file == NULL) {
1507 return NULL;
1508 }
1509 if (file == Py_None) {
1510 Py_DECREF(file);
1511 /* do nothing if sys.stderr is None and sys.stderr was None
1512 when the thread was created */
1513 Py_RETURN_NONE;
1514 }
1515 }
1516 else {
1517 Py_INCREF(file);
1518 }
1519
1520 int res = thread_excepthook_file(file, exc_type, exc_value, exc_tb,
1521 thread);
1522 Py_DECREF(file);
1523 if (res < 0) {
1524 return NULL;
1525 }
1526
1527 Py_RETURN_NONE;
1528}
1529
1530PyDoc_STRVAR(excepthook_doc,
1531"excepthook(exc_type, exc_value, exc_traceback, thread)\n\
1532\n\
1533Handle uncaught Thread.run() exception.");
1534
Barry Warsawd0c10421996-12-17 00:05:22 +00001535static PyMethodDef thread_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001536 {"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread,
Victor Stinner754851f2011-04-19 23:58:51 +02001537 METH_VARARGS, start_new_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001538 {"start_new", (PyCFunction)thread_PyThread_start_new_thread,
Victor Stinner754851f2011-04-19 23:58:51 +02001539 METH_VARARGS, start_new_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301540 {"allocate_lock", thread_PyThread_allocate_lock,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001541 METH_NOARGS, allocate_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301542 {"allocate", thread_PyThread_allocate_lock,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001543 METH_NOARGS, allocate_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301544 {"exit_thread", thread_PyThread_exit_thread,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001545 METH_NOARGS, exit_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301546 {"exit", thread_PyThread_exit_thread,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001547 METH_NOARGS, exit_doc},
Antoine Pitrouba251c22021-03-11 23:35:45 +01001548 {"interrupt_main", (PyCFunction)thread_PyThread_interrupt_main,
1549 METH_VARARGS, interrupt_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301550 {"get_ident", thread_get_ident,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001551 METH_NOARGS, get_ident_doc},
Jake Teslerb121f632019-05-22 08:43:17 -07001552#ifdef PY_HAVE_THREAD_NATIVE_ID
1553 {"get_native_id", thread_get_native_id,
1554 METH_NOARGS, get_native_id_doc},
1555#endif
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301556 {"_count", thread__count,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001557 METH_NOARGS, _count_doc},
1558 {"stack_size", (PyCFunction)thread_stack_size,
Victor Stinner754851f2011-04-19 23:58:51 +02001559 METH_VARARGS, stack_size_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301560 {"_set_sentinel", thread__set_sentinel,
Antoine Pitrou7b476992013-09-07 23:38:37 +02001561 METH_NOARGS, _set_sentinel_doc},
Victor Stinnercd590a72019-05-28 00:39:52 +02001562 {"_excepthook", thread_excepthook,
1563 METH_O, excepthook_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001564 {NULL, NULL} /* sentinel */
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001565};
1566
1567
1568/* Initialization function */
1569
Victor Stinner8203c732020-12-16 12:20:33 +01001570static int
Victor Stinner61040132020-12-18 01:39:00 +01001571thread_module_exec(PyObject *module)
Victor Stinner8203c732020-12-16 12:20:33 +01001572{
Victor Stinner61040132020-12-18 01:39:00 +01001573 thread_module_state *state = get_thread_state(module);
1574 PyObject *d = PyModule_GetDict(module);
1575
Victor Stinner8203c732020-12-16 12:20:33 +01001576 // Initialize the C thread library
1577 PyThread_init_thread();
1578
Victor Stinner61040132020-12-18 01:39:00 +01001579 // Lock
1580 state->lock_type = (PyTypeObject *)PyType_FromSpec(&lock_type_spec);
1581 if (state->lock_type == NULL) {
Victor Stinner8203c732020-12-16 12:20:33 +01001582 return -1;
1583 }
Victor Stinner61040132020-12-18 01:39:00 +01001584 if (PyDict_SetItemString(d, "LockType", (PyObject *)state->lock_type) < 0) {
Victor Stinner8203c732020-12-16 12:20:33 +01001585 return -1;
1586 }
Victor Stinner61040132020-12-18 01:39:00 +01001587
1588 // RLock
1589 PyTypeObject *rlock_type = (PyTypeObject *)PyType_FromSpec(&rlock_type_spec);
1590 if (rlock_type == NULL) {
Victor Stinner8203c732020-12-16 12:20:33 +01001591 return -1;
1592 }
Victor Stinner61040132020-12-18 01:39:00 +01001593 if (PyModule_AddType(module, rlock_type) < 0) {
1594 Py_DECREF(rlock_type);
1595 return -1;
1596 }
1597 Py_DECREF(rlock_type);
1598
1599 // Local dummy
1600 state->local_dummy_type = (PyTypeObject *)PyType_FromSpec(&local_dummy_type_spec);
1601 if (state->local_dummy_type == NULL) {
1602 return -1;
1603 }
1604
1605 // Local
1606 state->local_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, &local_type_spec, NULL);
1607 if (state->local_type == NULL) {
1608 return -1;
1609 }
1610 if (PyModule_AddType(module, state->local_type) < 0) {
1611 return -1;
1612 }
1613
Victor Stinner8203c732020-12-16 12:20:33 +01001614 if (ExceptHookArgsType.tp_name == NULL) {
1615 if (PyStructSequence_InitType2(&ExceptHookArgsType,
1616 &ExceptHookArgs_desc) < 0) {
1617 return -1;
1618 }
1619 }
1620
1621 // Add module attributes
Victor Stinner8203c732020-12-16 12:20:33 +01001622 if (PyDict_SetItemString(d, "error", ThreadError) < 0) {
1623 return -1;
1624 }
Victor Stinner8203c732020-12-16 12:20:33 +01001625 if (PyModule_AddType(module, &ExceptHookArgsType) < 0) {
1626 return -1;
1627 }
1628
1629 // TIMEOUT_MAX
1630 double timeout_max = (_PyTime_t)PY_TIMEOUT_MAX * 1e-6;
1631 double time_max = _PyTime_AsSecondsDouble(_PyTime_MAX);
1632 timeout_max = Py_MIN(timeout_max, time_max);
1633 // Round towards minus infinity
1634 timeout_max = floor(timeout_max);
1635
1636 if (PyModule_AddObject(module, "TIMEOUT_MAX",
1637 PyFloat_FromDouble(timeout_max)) < 0) {
1638 return -1;
1639 }
1640
1641 return 0;
1642}
1643
1644
Victor Stinner61040132020-12-18 01:39:00 +01001645static int
1646thread_module_traverse(PyObject *module, visitproc visit, void *arg)
1647{
1648 thread_module_state *state = get_thread_state(module);
1649 Py_VISIT(state->lock_type);
1650 Py_VISIT(state->local_type);
1651 Py_VISIT(state->local_dummy_type);
1652 return 0;
1653}
1654
1655static int
1656thread_module_clear(PyObject *module)
1657{
1658 thread_module_state *state = get_thread_state(module);
1659 Py_CLEAR(state->lock_type);
1660 Py_CLEAR(state->local_type);
1661 Py_CLEAR(state->local_dummy_type);
1662 return 0;
1663}
1664
1665static void
1666thread_module_free(void *module)
1667{
1668 thread_module_clear((PyObject *)module);
1669}
1670
1671
1672
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001673PyDoc_STRVAR(thread_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001674"This module provides primitive operations to write multi-threaded programs.\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001675The 'threading' module provides a more convenient interface.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001676
Victor Stinner61040132020-12-18 01:39:00 +01001677static PyModuleDef_Slot thread_module_slots[] = {
1678 {Py_mod_exec, thread_module_exec},
1679 {0, NULL}
1680};
1681
1682static struct PyModuleDef thread_module = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001683 PyModuleDef_HEAD_INIT,
Victor Stinner8203c732020-12-16 12:20:33 +01001684 .m_name = "_thread",
1685 .m_doc = thread_doc,
Victor Stinner61040132020-12-18 01:39:00 +01001686 .m_size = sizeof(thread_module_state),
Victor Stinner8203c732020-12-16 12:20:33 +01001687 .m_methods = thread_methods,
Victor Stinner61040132020-12-18 01:39:00 +01001688 .m_traverse = thread_module_traverse,
1689 .m_clear = thread_module_clear,
1690 .m_free = thread_module_free,
1691 .m_slots = thread_module_slots,
Martin v. Löwis1a214512008-06-11 05:26:20 +00001692};
1693
Mark Hammondfe51c6d2002-08-02 02:27:13 +00001694PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00001695PyInit__thread(void)
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001696{
Victor Stinner61040132020-12-18 01:39:00 +01001697 return PyModuleDef_Init(&thread_module);
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001698}