blob: 0613dfd3070c5c3eb788fbbf06d336357c27f833 [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 Stinnercd590a72019-05-28 00:39:52 +02006#include "pycore_pylifecycle.h"
Victor Stinner4a21e572020-04-15 02:35:41 +02007#include "pycore_interp.h" // _PyInterpreterState.num_threads
8#include "pycore_pystate.h" // _PyThreadState_Init()
9#include <stddef.h> // offsetof()
Victor Stinner61040132020-12-18 01:39:00 +010010#include "structmember.h" // PyMemberDef
Guido van Rossum1984f1e1992-08-04 12:41:02 +000011
Antoine Pitrouba251c22021-03-11 23:35:45 +010012#ifdef HAVE_SIGNAL_H
13# include <signal.h> // SIGINT
14#endif
15
Victor Stinner8203c732020-12-16 12:20:33 +010016// ThreadError is just an alias to PyExc_RuntimeError
17#define ThreadError PyExc_RuntimeError
18
19_Py_IDENTIFIER(__dict__);
Guido van Rossum1984f1e1992-08-04 12:41:02 +000020
Victor Stinnerbd303c12013-11-07 23:07:29 +010021_Py_IDENTIFIER(stderr);
Victor Stinnercd590a72019-05-28 00:39:52 +020022_Py_IDENTIFIER(flush);
Victor Stinnerbd303c12013-11-07 23:07:29 +010023
Victor Stinner8203c732020-12-16 12:20:33 +010024
Victor Stinner61040132020-12-18 01:39:00 +010025// Forward declarations
26static struct PyModuleDef thread_module;
27
28
29typedef struct {
30 PyTypeObject *lock_type;
31 PyTypeObject *local_type;
32 PyTypeObject *local_dummy_type;
33} thread_module_state;
34
35static inline thread_module_state*
36get_thread_state(PyObject *module)
37{
38 void *state = PyModule_GetState(module);
39 assert(state != NULL);
40 return (thread_module_state *)state;
41}
42
43
Guido van Rossum1984f1e1992-08-04 12:41:02 +000044/* Lock objects */
45
46typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000047 PyObject_HEAD
48 PyThread_type_lock lock_lock;
49 PyObject *in_weakreflist;
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +000050 char locked; /* for sanity checking */
Guido van Rossum1984f1e1992-08-04 12:41:02 +000051} lockobject;
52
Victor Stinner61040132020-12-18 01:39:00 +010053static int
54lock_traverse(lockobject *self, visitproc visit, void *arg)
55{
56 Py_VISIT(Py_TYPE(self));
57 return 0;
58}
59
Guido van Rossum1984f1e1992-08-04 12:41:02 +000060static void
Peter Schneider-Kamp3707efe2000-07-10 10:03:58 +000061lock_dealloc(lockobject *self)
Guido van Rossum1984f1e1992-08-04 12:41:02 +000062{
Victor Stinner8203c732020-12-16 12:20:33 +010063 if (self->in_weakreflist != NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000064 PyObject_ClearWeakRefs((PyObject *) self);
Victor Stinner8203c732020-12-16 12:20:33 +010065 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000066 if (self->lock_lock != NULL) {
67 /* Unlock the lock so it's safe to free it */
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +000068 if (self->locked)
69 PyThread_release_lock(self->lock_lock);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000070 PyThread_free_lock(self->lock_lock);
71 }
Victor Stinner61040132020-12-18 01:39:00 +010072 PyTypeObject *tp = Py_TYPE(self);
73 tp->tp_free((PyObject*)self);
74 Py_DECREF(tp);
Guido van Rossum1984f1e1992-08-04 12:41:02 +000075}
76
Antoine Pitrou810023d2010-12-15 22:59:16 +000077/* Helper to acquire an interruptible lock with a timeout. If the lock acquire
78 * is interrupted, signal handlers are run, and if they raise an exception,
79 * PY_LOCK_INTR is returned. Otherwise, PY_LOCK_ACQUIRED or PY_LOCK_FAILURE
Raymond Hettinger15f44ab2016-08-30 10:47:49 -070080 * are returned, depending on whether the lock can be acquired within the
Antoine Pitrou810023d2010-12-15 22:59:16 +000081 * timeout.
82 */
83static PyLockStatus
Victor Stinnerf5faad22015-03-28 03:52:05 +010084acquire_timed(PyThread_type_lock lock, _PyTime_t timeout)
Antoine Pitrou810023d2010-12-15 22:59:16 +000085{
86 PyLockStatus r;
Victor Stinnerf5faad22015-03-28 03:52:05 +010087 _PyTime_t endtime = 0;
Antoine Pitrou810023d2010-12-15 22:59:16 +000088
Victor Stinner8203c732020-12-16 12:20:33 +010089 if (timeout > 0) {
Victor Stinnerf5faad22015-03-28 03:52:05 +010090 endtime = _PyTime_GetMonotonicClock() + timeout;
Victor Stinner8203c732020-12-16 12:20:33 +010091 }
Antoine Pitrou810023d2010-12-15 22:59:16 +000092
93 do {
Victor Stinner8203c732020-12-16 12:20:33 +010094 _PyTime_t microseconds;
Victor Stinner869e1772015-03-30 03:49:14 +020095 microseconds = _PyTime_AsMicroseconds(timeout, _PyTime_ROUND_CEILING);
Victor Stinnerf5faad22015-03-28 03:52:05 +010096
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +000097 /* first a simple non-blocking try without releasing the GIL */
98 r = PyThread_acquire_lock_timed(lock, 0, 0);
99 if (r == PY_LOCK_FAILURE && microseconds != 0) {
100 Py_BEGIN_ALLOW_THREADS
101 r = PyThread_acquire_lock_timed(lock, microseconds, 1);
102 Py_END_ALLOW_THREADS
Victor Stinner357f5152013-11-05 15:10:19 +0100103 }
Antoine Pitrou810023d2010-12-15 22:59:16 +0000104
105 if (r == PY_LOCK_INTR) {
106 /* Run signal handlers if we were interrupted. Propagate
107 * exceptions from signal handlers, such as KeyboardInterrupt, by
108 * passing up PY_LOCK_INTR. */
109 if (Py_MakePendingCalls() < 0) {
110 return PY_LOCK_INTR;
111 }
112
113 /* If we're using a timeout, recompute the timeout after processing
114 * signals, since those can take time. */
Victor Stinnerf5faad22015-03-28 03:52:05 +0100115 if (timeout > 0) {
116 timeout = endtime - _PyTime_GetMonotonicClock();
Antoine Pitrou810023d2010-12-15 22:59:16 +0000117
118 /* Check for negative values, since those mean block forever.
119 */
Victor Stinner6aa446c2015-03-30 21:33:51 +0200120 if (timeout < 0) {
Antoine Pitrou810023d2010-12-15 22:59:16 +0000121 r = PY_LOCK_FAILURE;
122 }
123 }
124 }
125 } while (r == PY_LOCK_INTR); /* Retry if we were interrupted. */
126
127 return r;
128}
129
Victor Stinnerf5faad22015-03-28 03:52:05 +0100130static int
131lock_acquire_parse_args(PyObject *args, PyObject *kwds,
132 _PyTime_t *timeout)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000133{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000134 char *kwlist[] = {"blocking", "timeout", NULL};
135 int blocking = 1;
Victor Stinnerf5faad22015-03-28 03:52:05 +0100136 PyObject *timeout_obj = NULL;
Victor Stinner13019fd2015-04-03 13:10:54 +0200137 const _PyTime_t unset_timeout = _PyTime_FromSeconds(-1);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000138
Victor Stinnerf5faad22015-03-28 03:52:05 +0100139 *timeout = unset_timeout ;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000140
Victor Stinnerf5faad22015-03-28 03:52:05 +0100141 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iO:acquire", kwlist,
142 &blocking, &timeout_obj))
143 return -1;
144
145 if (timeout_obj
Victor Stinner869e1772015-03-30 03:49:14 +0200146 && _PyTime_FromSecondsObject(timeout,
Pablo Galindo59af94f2017-10-18 08:13:09 +0100147 timeout_obj, _PyTime_ROUND_TIMEOUT) < 0)
Victor Stinnerf5faad22015-03-28 03:52:05 +0100148 return -1;
149
150 if (!blocking && *timeout != unset_timeout ) {
151 PyErr_SetString(PyExc_ValueError,
152 "can't specify a timeout for a non-blocking call");
153 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000154 }
Victor Stinnerf5faad22015-03-28 03:52:05 +0100155 if (*timeout < 0 && *timeout != unset_timeout) {
156 PyErr_SetString(PyExc_ValueError,
157 "timeout value must be positive");
158 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000159 }
160 if (!blocking)
Victor Stinnerf5faad22015-03-28 03:52:05 +0100161 *timeout = 0;
162 else if (*timeout != unset_timeout) {
163 _PyTime_t microseconds;
164
Pablo Galindo59af94f2017-10-18 08:13:09 +0100165 microseconds = _PyTime_AsMicroseconds(*timeout, _PyTime_ROUND_TIMEOUT);
Victor Stinnerf5faad22015-03-28 03:52:05 +0100166 if (microseconds >= PY_TIMEOUT_MAX) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000167 PyErr_SetString(PyExc_OverflowError,
168 "timeout value is too large");
Victor Stinnerf5faad22015-03-28 03:52:05 +0100169 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000170 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000171 }
Victor Stinnerf5faad22015-03-28 03:52:05 +0100172 return 0;
173}
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000174
Victor Stinnerf5faad22015-03-28 03:52:05 +0100175static PyObject *
176lock_PyThread_acquire_lock(lockobject *self, PyObject *args, PyObject *kwds)
177{
178 _PyTime_t timeout;
Victor Stinnerf5faad22015-03-28 03:52:05 +0100179 if (lock_acquire_parse_args(args, kwds, &timeout) < 0)
180 return NULL;
181
Victor Stinner8203c732020-12-16 12:20:33 +0100182 PyLockStatus r = acquire_timed(self->lock_lock, timeout);
Antoine Pitrou810023d2010-12-15 22:59:16 +0000183 if (r == PY_LOCK_INTR) {
184 return NULL;
185 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000186
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +0000187 if (r == PY_LOCK_ACQUIRED)
188 self->locked = 1;
Antoine Pitrou810023d2010-12-15 22:59:16 +0000189 return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000190}
191
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000192PyDoc_STRVAR(acquire_doc,
Berker Peksag720e6552016-05-02 12:25:35 +0300193"acquire(blocking=True, timeout=-1) -> bool\n\
Guido van Rossumf6694362006-03-10 02:28:35 +0000194(acquire_lock() is an obsolete synonym)\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000195\n\
196Lock the lock. Without argument, this blocks if the lock is already\n\
197locked (even by the same thread), waiting for another thread to release\n\
R David Murray95b71102013-02-04 10:15:58 -0500198the lock, and return True once the lock is acquired.\n\
Guido van Rossum8fdc75b2002-04-07 06:32:21 +0000199With an argument, this will only block if the argument is true,\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000200and the return value reflects whether the lock is acquired.\n\
Antoine Pitrou810023d2010-12-15 22:59:16 +0000201The blocking operation is interruptible.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000202
Barry Warsawd0c10421996-12-17 00:05:22 +0000203static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530204lock_PyThread_release_lock(lockobject *self, PyObject *Py_UNUSED(ignored))
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000205{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000206 /* Sanity check: the lock must be locked */
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +0000207 if (!self->locked) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000208 PyErr_SetString(ThreadError, "release unlocked lock");
209 return NULL;
210 }
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000211
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000212 PyThread_release_lock(self->lock_lock);
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +0000213 self->locked = 0;
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200214 Py_RETURN_NONE;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000215}
216
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000217PyDoc_STRVAR(release_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000218"release()\n\
Guido van Rossumf6694362006-03-10 02:28:35 +0000219(release_lock() is an obsolete synonym)\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000220\n\
221Release the lock, allowing another thread that is blocked waiting for\n\
222the lock to acquire the lock. The lock must be in the locked state,\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000223but it needn't be locked by the same thread that unlocks it.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000224
Barry Warsawd0c10421996-12-17 00:05:22 +0000225static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530226lock_locked_lock(lockobject *self, PyObject *Py_UNUSED(ignored))
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000227{
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +0000228 return PyBool_FromLong((long)self->locked);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000229}
230
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000231PyDoc_STRVAR(locked_doc,
Guido van Rossum8fdc75b2002-04-07 06:32:21 +0000232"locked() -> bool\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000233(locked_lock() is an obsolete synonym)\n\
234\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000235Return whether the lock is in the locked state.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000236
Raymond Hettinger62f4dad2014-05-25 18:22:35 -0700237static PyObject *
238lock_repr(lockobject *self)
239{
240 return PyUnicode_FromFormat("<%s %s object at %p>",
241 self->locked ? "locked" : "unlocked", Py_TYPE(self)->tp_name, self);
242}
243
Victor Stinner87255be2020-04-07 23:11:49 +0200244#ifdef HAVE_FORK
245static PyObject *
246lock__at_fork_reinit(lockobject *self, PyObject *Py_UNUSED(args))
247{
248 if (_PyThread_at_fork_reinit(&self->lock_lock) < 0) {
249 PyErr_SetString(ThreadError, "failed to reinitialize lock at fork");
250 return NULL;
251 }
252
253 self->locked = 0;
254
255 Py_RETURN_NONE;
256}
257#endif /* HAVE_FORK */
258
259
Barry Warsawd0c10421996-12-17 00:05:22 +0000260static PyMethodDef lock_methods[] = {
Serhiy Storchaka62be7422018-11-27 13:27:31 +0200261 {"acquire_lock", (PyCFunction)(void(*)(void))lock_PyThread_acquire_lock,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000262 METH_VARARGS | METH_KEYWORDS, acquire_doc},
Serhiy Storchaka62be7422018-11-27 13:27:31 +0200263 {"acquire", (PyCFunction)(void(*)(void))lock_PyThread_acquire_lock,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000264 METH_VARARGS | METH_KEYWORDS, acquire_doc},
265 {"release_lock", (PyCFunction)lock_PyThread_release_lock,
266 METH_NOARGS, release_doc},
267 {"release", (PyCFunction)lock_PyThread_release_lock,
268 METH_NOARGS, release_doc},
269 {"locked_lock", (PyCFunction)lock_locked_lock,
270 METH_NOARGS, locked_doc},
271 {"locked", (PyCFunction)lock_locked_lock,
272 METH_NOARGS, locked_doc},
Serhiy Storchaka62be7422018-11-27 13:27:31 +0200273 {"__enter__", (PyCFunction)(void(*)(void))lock_PyThread_acquire_lock,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000274 METH_VARARGS | METH_KEYWORDS, acquire_doc},
275 {"__exit__", (PyCFunction)lock_PyThread_release_lock,
276 METH_VARARGS, release_doc},
Victor Stinner87255be2020-04-07 23:11:49 +0200277#ifdef HAVE_FORK
278 {"_at_fork_reinit", (PyCFunction)lock__at_fork_reinit,
279 METH_NOARGS, NULL},
280#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000281 {NULL, NULL} /* sentinel */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000282};
283
Victor Stinner8203c732020-12-16 12:20:33 +0100284PyDoc_STRVAR(lock_doc,
285"A lock object is a synchronization primitive. To create a lock,\n\
286call threading.Lock(). Methods are:\n\
287\n\
288acquire() -- lock the lock, possibly blocking until it can be obtained\n\
289release() -- unlock of the lock\n\
290locked() -- test whether the lock is currently locked\n\
291\n\
292A lock is not owned by the thread that locked it; another thread may\n\
293unlock it. A thread attempting to lock a lock that it has already locked\n\
294will block until another thread unlocks it. Deadlocks may ensue.");
295
Victor Stinner61040132020-12-18 01:39:00 +0100296static PyMemberDef lock_type_members[] = {
297 {"__weaklistoffset__", T_PYSSIZET, offsetof(lockobject, in_weakreflist), READONLY},
298 {NULL},
299};
300
301static PyType_Slot lock_type_slots[] = {
302 {Py_tp_dealloc, (destructor)lock_dealloc},
303 {Py_tp_repr, (reprfunc)lock_repr},
304 {Py_tp_doc, (void *)lock_doc},
305 {Py_tp_methods, lock_methods},
306 {Py_tp_traverse, lock_traverse},
307 {Py_tp_members, lock_type_members},
308 {0, 0}
309};
310
311static PyType_Spec lock_type_spec = {
312 .name = "_thread.lock",
313 .basicsize = sizeof(lockobject),
314 .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
315 .slots = lock_type_slots,
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000316};
317
Antoine Pitrou434736a2009-11-10 18:46:01 +0000318/* Recursive lock objects */
319
320typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000321 PyObject_HEAD
322 PyThread_type_lock rlock_lock;
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200323 unsigned long rlock_owner;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000324 unsigned long rlock_count;
325 PyObject *in_weakreflist;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000326} rlockobject;
327
328static void
329rlock_dealloc(rlockobject *self)
330{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000331 if (self->in_weakreflist != NULL)
332 PyObject_ClearWeakRefs((PyObject *) self);
Victor Stinner357f5152013-11-05 15:10:19 +0100333 /* self->rlock_lock can be NULL if PyThread_allocate_lock() failed
334 in rlock_new() */
335 if (self->rlock_lock != NULL) {
336 /* Unlock the lock so it's safe to free it */
337 if (self->rlock_count > 0)
338 PyThread_release_lock(self->rlock_lock);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000339
Victor Stinner357f5152013-11-05 15:10:19 +0100340 PyThread_free_lock(self->rlock_lock);
341 }
Victor Stinner61040132020-12-18 01:39:00 +0100342 PyTypeObject *tp = Py_TYPE(self);
343 tp->tp_free(self);
344 Py_DECREF(tp);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000345}
346
347static PyObject *
348rlock_acquire(rlockobject *self, PyObject *args, PyObject *kwds)
349{
Victor Stinnerf5faad22015-03-28 03:52:05 +0100350 _PyTime_t timeout;
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200351 unsigned long tid;
Antoine Pitrou810023d2010-12-15 22:59:16 +0000352 PyLockStatus r = PY_LOCK_ACQUIRED;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000353
Victor Stinnerf5faad22015-03-28 03:52:05 +0100354 if (lock_acquire_parse_args(args, kwds, &timeout) < 0)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000355 return NULL;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000356
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000357 tid = PyThread_get_thread_ident();
358 if (self->rlock_count > 0 && tid == self->rlock_owner) {
359 unsigned long count = self->rlock_count + 1;
360 if (count <= self->rlock_count) {
361 PyErr_SetString(PyExc_OverflowError,
362 "Internal lock count overflowed");
363 return NULL;
364 }
365 self->rlock_count = count;
366 Py_RETURN_TRUE;
367 }
Victor Stinnerf5faad22015-03-28 03:52:05 +0100368 r = acquire_timed(self->rlock_lock, timeout);
Antoine Pitrou810023d2010-12-15 22:59:16 +0000369 if (r == PY_LOCK_ACQUIRED) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000370 assert(self->rlock_count == 0);
371 self->rlock_owner = tid;
372 self->rlock_count = 1;
373 }
Antoine Pitrou810023d2010-12-15 22:59:16 +0000374 else if (r == PY_LOCK_INTR) {
375 return NULL;
376 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000377
Antoine Pitrou810023d2010-12-15 22:59:16 +0000378 return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000379}
380
381PyDoc_STRVAR(rlock_acquire_doc,
382"acquire(blocking=True) -> bool\n\
383\n\
384Lock the lock. `blocking` indicates whether we should wait\n\
385for the lock to be available or not. If `blocking` is False\n\
386and another thread holds the lock, the method will return False\n\
387immediately. If `blocking` is True and another thread holds\n\
388the lock, the method will wait for the lock to be released,\n\
389take it and then return True.\n\
Antoine Pitrou810023d2010-12-15 22:59:16 +0000390(note: the blocking operation is interruptible.)\n\
Antoine Pitrou434736a2009-11-10 18:46:01 +0000391\n\
392In all other cases, the method will return True immediately.\n\
393Precisely, if the current thread already holds the lock, its\n\
394internal counter is simply incremented. If nobody holds the lock,\n\
395the lock is taken and its internal counter initialized to 1.");
396
397static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530398rlock_release(rlockobject *self, PyObject *Py_UNUSED(ignored))
Antoine Pitrou434736a2009-11-10 18:46:01 +0000399{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200400 unsigned long tid = PyThread_get_thread_ident();
Antoine Pitrou434736a2009-11-10 18:46:01 +0000401
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000402 if (self->rlock_count == 0 || self->rlock_owner != tid) {
403 PyErr_SetString(PyExc_RuntimeError,
404 "cannot release un-acquired lock");
405 return NULL;
406 }
407 if (--self->rlock_count == 0) {
408 self->rlock_owner = 0;
409 PyThread_release_lock(self->rlock_lock);
410 }
411 Py_RETURN_NONE;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000412}
413
414PyDoc_STRVAR(rlock_release_doc,
415"release()\n\
416\n\
417Release the lock, allowing another thread that is blocked waiting for\n\
418the lock to acquire the lock. The lock must be in the locked state,\n\
419and must be locked by the same thread that unlocks it; otherwise a\n\
420`RuntimeError` is raised.\n\
421\n\
422Do note that if the lock was acquire()d several times in a row by the\n\
423current thread, release() needs to be called as many times for the lock\n\
424to be available for other threads.");
425
426static PyObject *
Victor Stinnere8794522014-01-02 12:47:24 +0100427rlock_acquire_restore(rlockobject *self, PyObject *args)
Antoine Pitrou434736a2009-11-10 18:46:01 +0000428{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200429 unsigned long owner;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000430 unsigned long count;
431 int r = 1;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000432
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200433 if (!PyArg_ParseTuple(args, "(kk):_acquire_restore", &count, &owner))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000434 return NULL;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000435
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000436 if (!PyThread_acquire_lock(self->rlock_lock, 0)) {
437 Py_BEGIN_ALLOW_THREADS
438 r = PyThread_acquire_lock(self->rlock_lock, 1);
439 Py_END_ALLOW_THREADS
440 }
441 if (!r) {
442 PyErr_SetString(ThreadError, "couldn't acquire lock");
443 return NULL;
444 }
445 assert(self->rlock_count == 0);
446 self->rlock_owner = owner;
447 self->rlock_count = count;
448 Py_RETURN_NONE;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000449}
450
451PyDoc_STRVAR(rlock_acquire_restore_doc,
452"_acquire_restore(state) -> None\n\
453\n\
454For internal use by `threading.Condition`.");
455
456static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530457rlock_release_save(rlockobject *self, PyObject *Py_UNUSED(ignored))
Antoine Pitrou434736a2009-11-10 18:46:01 +0000458{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200459 unsigned long owner;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000460 unsigned long count;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000461
Victor Stinnerc2824d42011-04-24 23:41:33 +0200462 if (self->rlock_count == 0) {
463 PyErr_SetString(PyExc_RuntimeError,
464 "cannot release un-acquired lock");
465 return NULL;
466 }
467
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000468 owner = self->rlock_owner;
469 count = self->rlock_count;
470 self->rlock_count = 0;
471 self->rlock_owner = 0;
472 PyThread_release_lock(self->rlock_lock);
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200473 return Py_BuildValue("kk", count, owner);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000474}
475
476PyDoc_STRVAR(rlock_release_save_doc,
477"_release_save() -> tuple\n\
478\n\
479For internal use by `threading.Condition`.");
480
481
482static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530483rlock_is_owned(rlockobject *self, PyObject *Py_UNUSED(ignored))
Antoine Pitrou434736a2009-11-10 18:46:01 +0000484{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200485 unsigned long tid = PyThread_get_thread_ident();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000486
487 if (self->rlock_count > 0 && self->rlock_owner == tid) {
488 Py_RETURN_TRUE;
489 }
490 Py_RETURN_FALSE;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000491}
492
493PyDoc_STRVAR(rlock_is_owned_doc,
494"_is_owned() -> bool\n\
495\n\
496For internal use by `threading.Condition`.");
497
498static PyObject *
499rlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
500{
Victor Stinner87255be2020-04-07 23:11:49 +0200501 rlockobject *self = (rlockobject *) type->tp_alloc(type, 0);
502 if (self == NULL) {
503 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000504 }
Victor Stinner87255be2020-04-07 23:11:49 +0200505 self->in_weakreflist = NULL;
506 self->rlock_owner = 0;
507 self->rlock_count = 0;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000508
Victor Stinner87255be2020-04-07 23:11:49 +0200509 self->rlock_lock = PyThread_allocate_lock();
510 if (self->rlock_lock == NULL) {
511 Py_DECREF(self);
512 PyErr_SetString(ThreadError, "can't allocate lock");
513 return NULL;
514 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000515 return (PyObject *) self;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000516}
517
518static PyObject *
519rlock_repr(rlockobject *self)
520{
Raymond Hettinger62f4dad2014-05-25 18:22:35 -0700521 return PyUnicode_FromFormat("<%s %s object owner=%ld count=%lu at %p>",
522 self->rlock_count ? "locked" : "unlocked",
523 Py_TYPE(self)->tp_name, self->rlock_owner,
524 self->rlock_count, self);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000525}
526
527
Victor Stinner87255be2020-04-07 23:11:49 +0200528#ifdef HAVE_FORK
529static PyObject *
530rlock__at_fork_reinit(rlockobject *self, PyObject *Py_UNUSED(args))
531{
532 if (_PyThread_at_fork_reinit(&self->rlock_lock) < 0) {
533 PyErr_SetString(ThreadError, "failed to reinitialize lock at fork");
534 return NULL;
535 }
536
537 self->rlock_owner = 0;
538 self->rlock_count = 0;
539
540 Py_RETURN_NONE;
541}
542#endif /* HAVE_FORK */
543
544
Antoine Pitrou434736a2009-11-10 18:46:01 +0000545static PyMethodDef rlock_methods[] = {
Serhiy Storchaka62be7422018-11-27 13:27:31 +0200546 {"acquire", (PyCFunction)(void(*)(void))rlock_acquire,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000547 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
548 {"release", (PyCFunction)rlock_release,
549 METH_NOARGS, rlock_release_doc},
550 {"_is_owned", (PyCFunction)rlock_is_owned,
551 METH_NOARGS, rlock_is_owned_doc},
552 {"_acquire_restore", (PyCFunction)rlock_acquire_restore,
Victor Stinnere8794522014-01-02 12:47:24 +0100553 METH_VARARGS, rlock_acquire_restore_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000554 {"_release_save", (PyCFunction)rlock_release_save,
555 METH_NOARGS, rlock_release_save_doc},
Serhiy Storchaka62be7422018-11-27 13:27:31 +0200556 {"__enter__", (PyCFunction)(void(*)(void))rlock_acquire,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000557 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
558 {"__exit__", (PyCFunction)rlock_release,
559 METH_VARARGS, rlock_release_doc},
Victor Stinner87255be2020-04-07 23:11:49 +0200560#ifdef HAVE_FORK
561 {"_at_fork_reinit", (PyCFunction)rlock__at_fork_reinit,
562 METH_NOARGS, NULL},
563#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000564 {NULL, NULL} /* sentinel */
Antoine Pitrou434736a2009-11-10 18:46:01 +0000565};
566
567
Victor Stinner61040132020-12-18 01:39:00 +0100568static PyMemberDef rlock_type_members[] = {
569 {"__weaklistoffset__", T_PYSSIZET, offsetof(rlockobject, in_weakreflist), READONLY},
570 {NULL},
571};
572
573static PyType_Slot rlock_type_slots[] = {
574 {Py_tp_dealloc, (destructor)rlock_dealloc},
575 {Py_tp_repr, (reprfunc)rlock_repr},
576 {Py_tp_methods, rlock_methods},
577 {Py_tp_alloc, PyType_GenericAlloc},
578 {Py_tp_new, rlock_new},
579 {Py_tp_members, rlock_type_members},
580 {0, 0},
581};
582
583static PyType_Spec rlock_type_spec = {
584 .name = "_thread.RLock",
585 .basicsize = sizeof(rlockobject),
586 .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
587 .slots = rlock_type_slots,
Antoine Pitrou434736a2009-11-10 18:46:01 +0000588};
589
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000590static lockobject *
Victor Stinner61040132020-12-18 01:39:00 +0100591newlockobject(PyObject *module)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000592{
Victor Stinner61040132020-12-18 01:39:00 +0100593 thread_module_state *state = get_thread_state(module);
594
595 PyTypeObject *type = state->lock_type;
596 lockobject *self = (lockobject *)type->tp_alloc(type, 0);
Victor Stinner8203c732020-12-16 12:20:33 +0100597 if (self == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000598 return NULL;
Victor Stinner8203c732020-12-16 12:20:33 +0100599 }
600
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000601 self->lock_lock = PyThread_allocate_lock();
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +0000602 self->locked = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000603 self->in_weakreflist = NULL;
Victor Stinner8203c732020-12-16 12:20:33 +0100604
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000605 if (self->lock_lock == NULL) {
606 Py_DECREF(self);
607 PyErr_SetString(ThreadError, "can't allocate lock");
608 return NULL;
609 }
610 return self;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000611}
612
Jim Fultond15dc062004-07-14 19:11:50 +0000613/* Thread-local objects */
614
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000615/* Quick overview:
616
617 We need to be able to reclaim reference cycles as soon as possible
618 (both when a thread is being terminated, or a thread-local object
619 becomes unreachable from user data). Constraints:
620 - it must not be possible for thread-state dicts to be involved in
621 reference cycles (otherwise the cyclic GC will refuse to consider
622 objects referenced from a reachable thread-state dict, even though
623 local_dealloc would clear them)
624 - the death of a thread-state dict must still imply destruction of the
625 corresponding local dicts in all thread-local objects.
626
627 Our implementation uses small "localdummy" objects in order to break
628 the reference chain. These trivial objects are hashable (using the
629 default scheme of identity hashing) and weakrefable.
630 Each thread-state holds a separate localdummy for each local object
631 (as a /strong reference/),
632 and each thread-local object holds a dict mapping /weak references/
633 of localdummies to local dicts.
634
635 Therefore:
636 - only the thread-state dict holds a strong reference to the dummies
637 - only the thread-local object holds a strong reference to the local dicts
638 - only outside objects (application- or library-level) hold strong
639 references to the thread-local objects
640 - as soon as a thread-state dict is destroyed, the weakref callbacks of all
641 dummies attached to that thread are called, and destroy the corresponding
642 local dicts from thread-local objects
643 - as soon as a thread-local object is destroyed, its local dicts are
644 destroyed and its dummies are manually removed from all thread states
645 - the GC can do its work correctly when a thread-local object is dangling,
646 without any interference from the thread-state dicts
647
648 As an additional optimization, each localdummy holds a borrowed reference
649 to the corresponding localdict. This borrowed reference is only used
650 by the thread-local object which has created the localdummy, which should
651 guarantee that the localdict still exists when accessed.
652*/
653
654typedef struct {
655 PyObject_HEAD
656 PyObject *localdict; /* Borrowed reference! */
657 PyObject *weakreflist; /* List of weak references to self */
658} localdummyobject;
659
660static void
661localdummy_dealloc(localdummyobject *self)
662{
663 if (self->weakreflist != NULL)
664 PyObject_ClearWeakRefs((PyObject *) self);
Victor Stinner61040132020-12-18 01:39:00 +0100665 PyTypeObject *tp = Py_TYPE(self);
666 tp->tp_free((PyObject*)self);
667 Py_DECREF(tp);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000668}
669
Victor Stinner61040132020-12-18 01:39:00 +0100670static PyMemberDef local_dummy_type_members[] = {
671 {"__weaklistoffset__", T_PYSSIZET, offsetof(localdummyobject, weakreflist), READONLY},
672 {NULL},
673};
674
675static PyType_Slot local_dummy_type_slots[] = {
676 {Py_tp_dealloc, (destructor)localdummy_dealloc},
677 {Py_tp_doc, "Thread-local dummy"},
678 {Py_tp_members, local_dummy_type_members},
679 {0, 0}
680};
681
682static PyType_Spec local_dummy_type_spec = {
683 .name = "_thread._localdummy",
684 .basicsize = sizeof(localdummyobject),
685 .flags = Py_TPFLAGS_DEFAULT,
686 .slots = local_dummy_type_slots,
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000687};
688
689
Jim Fultond15dc062004-07-14 19:11:50 +0000690typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000691 PyObject_HEAD
692 PyObject *key;
693 PyObject *args;
694 PyObject *kw;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000695 PyObject *weakreflist; /* List of weak references to self */
696 /* A {localdummy weakref -> localdict} dict */
697 PyObject *dummies;
698 /* The callback for weakrefs to localdummies */
699 PyObject *wr_callback;
Jim Fultond15dc062004-07-14 19:11:50 +0000700} localobject;
701
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000702/* Forward declaration */
Victor Stinner61040132020-12-18 01:39:00 +0100703static PyObject *_ldict(localobject *self, thread_module_state *state);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000704static PyObject *_localdummy_destroyed(PyObject *meth_self, PyObject *dummyweakref);
705
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000706/* Create and register the dummy for the current thread.
707 Returns a borrowed reference of the corresponding local dict */
708static PyObject *
Victor Stinner61040132020-12-18 01:39:00 +0100709_local_create_dummy(localobject *self, thread_module_state *state)
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000710{
Victor Stinner8203c732020-12-16 12:20:33 +0100711 PyObject *ldict = NULL, *wr = NULL;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000712 localdummyobject *dummy = NULL;
Victor Stinner61040132020-12-18 01:39:00 +0100713 PyTypeObject *type = state->local_dummy_type;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000714
Victor Stinner8203c732020-12-16 12:20:33 +0100715 PyObject *tdict = PyThreadState_GetDict();
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000716 if (tdict == NULL) {
717 PyErr_SetString(PyExc_SystemError,
718 "Couldn't get thread-state dictionary");
719 goto err;
720 }
721
722 ldict = PyDict_New();
Victor Stinner8203c732020-12-16 12:20:33 +0100723 if (ldict == NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000724 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100725 }
Victor Stinner61040132020-12-18 01:39:00 +0100726 dummy = (localdummyobject *) type->tp_alloc(type, 0);
Victor Stinner8203c732020-12-16 12:20:33 +0100727 if (dummy == NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000728 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100729 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000730 dummy->localdict = ldict;
731 wr = PyWeakref_NewRef((PyObject *) dummy, self->wr_callback);
Victor Stinner8203c732020-12-16 12:20:33 +0100732 if (wr == NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000733 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100734 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000735
736 /* As a side-effect, this will cache the weakref's hash before the
737 dummy gets deleted */
Victor Stinner8203c732020-12-16 12:20:33 +0100738 int r = PyDict_SetItem(self->dummies, wr, ldict);
739 if (r < 0) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000740 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100741 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000742 Py_CLEAR(wr);
743 r = PyDict_SetItem(tdict, self->key, (PyObject *) dummy);
Victor Stinner8203c732020-12-16 12:20:33 +0100744 if (r < 0) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000745 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100746 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000747 Py_CLEAR(dummy);
748
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000749 Py_DECREF(ldict);
750 return ldict;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000751
752err:
753 Py_XDECREF(ldict);
754 Py_XDECREF(wr);
755 Py_XDECREF(dummy);
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000756 return NULL;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000757}
758
Jim Fultond15dc062004-07-14 19:11:50 +0000759static PyObject *
760local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
761{
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000762 static PyMethodDef wr_callback_def = {
763 "_localdummy_destroyed", (PyCFunction) _localdummy_destroyed, METH_O
764 };
Jim Fultond15dc062004-07-14 19:11:50 +0000765
Serhiy Storchakafa494fd2015-05-30 17:45:22 +0300766 if (type->tp_init == PyBaseObject_Type.tp_init) {
767 int rc = 0;
768 if (args != NULL)
769 rc = PyObject_IsTrue(args);
770 if (rc == 0 && kw != NULL)
771 rc = PyObject_IsTrue(kw);
772 if (rc != 0) {
Victor Stinner8203c732020-12-16 12:20:33 +0100773 if (rc > 0) {
Serhiy Storchakafa494fd2015-05-30 17:45:22 +0300774 PyErr_SetString(PyExc_TypeError,
775 "Initialization arguments are not supported");
Victor Stinner8203c732020-12-16 12:20:33 +0100776 }
Serhiy Storchakafa494fd2015-05-30 17:45:22 +0300777 return NULL;
778 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000779 }
Jim Fultond15dc062004-07-14 19:11:50 +0000780
Victor Stinner61040132020-12-18 01:39:00 +0100781 PyObject *module = _PyType_GetModuleByDef(type, &thread_module);
782 thread_module_state *state = get_thread_state(module);
783
784 localobject *self = (localobject *)type->tp_alloc(type, 0);
Victor Stinner8203c732020-12-16 12:20:33 +0100785 if (self == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000786 return NULL;
Victor Stinner8203c732020-12-16 12:20:33 +0100787 }
Jim Fultond15dc062004-07-14 19:11:50 +0000788
Victor Stinner8203c732020-12-16 12:20:33 +0100789 self->args = Py_XNewRef(args);
790 self->kw = Py_XNewRef(kw);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000791 self->key = PyUnicode_FromFormat("thread.local.%p", self);
Victor Stinner8203c732020-12-16 12:20:33 +0100792 if (self->key == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000793 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100794 }
Jim Fultond15dc062004-07-14 19:11:50 +0000795
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000796 self->dummies = PyDict_New();
Victor Stinner8203c732020-12-16 12:20:33 +0100797 if (self->dummies == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000798 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100799 }
Jim Fultond15dc062004-07-14 19:11:50 +0000800
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000801 /* We use a weak reference to self in the callback closure
802 in order to avoid spurious reference cycles */
Victor Stinner8203c732020-12-16 12:20:33 +0100803 PyObject *wr = PyWeakref_NewRef((PyObject *) self, NULL);
804 if (wr == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000805 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100806 }
Andrew Svetlov3ba3a3e2012-12-25 13:32:35 +0200807 self->wr_callback = PyCFunction_NewEx(&wr_callback_def, wr, NULL);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000808 Py_DECREF(wr);
Victor Stinner8203c732020-12-16 12:20:33 +0100809 if (self->wr_callback == NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000810 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100811 }
Victor Stinner61040132020-12-18 01:39:00 +0100812 if (_local_create_dummy(self, state) == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000813 goto err;
Victor Stinner8203c732020-12-16 12:20:33 +0100814 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000815 return (PyObject *)self;
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000816
817 err:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000818 Py_DECREF(self);
819 return NULL;
Jim Fultond15dc062004-07-14 19:11:50 +0000820}
821
822static int
823local_traverse(localobject *self, visitproc visit, void *arg)
824{
Victor Stinner61040132020-12-18 01:39:00 +0100825 Py_VISIT(Py_TYPE(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000826 Py_VISIT(self->args);
827 Py_VISIT(self->kw);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000828 Py_VISIT(self->dummies);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000829 return 0;
Jim Fultond15dc062004-07-14 19:11:50 +0000830}
831
832static int
833local_clear(localobject *self)
834{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000835 Py_CLEAR(self->args);
836 Py_CLEAR(self->kw);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000837 Py_CLEAR(self->dummies);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000838 Py_CLEAR(self->wr_callback);
839 /* Remove all strong references to dummies from the thread states */
Victor Stinner839184f2021-02-19 15:51:36 +0100840 if (self->key) {
841 PyInterpreterState *interp = _PyInterpreterState_GET();
842 PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
843 for(; tstate; tstate = PyThreadState_Next(tstate)) {
844 if (tstate->dict == NULL) {
845 continue;
Serhiy Storchaka8905fcc2018-12-11 08:38:03 +0200846 }
Victor Stinner839184f2021-02-19 15:51:36 +0100847 PyObject *v = _PyDict_Pop(tstate->dict, self->key, Py_None);
848 if (v != NULL) {
849 Py_DECREF(v);
850 }
851 else {
852 PyErr_Clear();
853 }
854 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000855 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000856 return 0;
857}
Jim Fultond15dc062004-07-14 19:11:50 +0000858
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000859static void
860local_dealloc(localobject *self)
861{
862 /* Weakrefs must be invalidated right now, otherwise they can be used
863 from code called below, which is very dangerous since Py_REFCNT(self) == 0 */
Victor Stinner8203c732020-12-16 12:20:33 +0100864 if (self->weakreflist != NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000865 PyObject_ClearWeakRefs((PyObject *) self);
Victor Stinner8203c732020-12-16 12:20:33 +0100866 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000867
868 PyObject_GC_UnTrack(self);
869
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000870 local_clear(self);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000871 Py_XDECREF(self->key);
Victor Stinner61040132020-12-18 01:39:00 +0100872
873 PyTypeObject *tp = Py_TYPE(self);
874 tp->tp_free((PyObject*)self);
875 Py_DECREF(tp);
Jim Fultond15dc062004-07-14 19:11:50 +0000876}
877
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000878/* Returns a borrowed reference to the local dict, creating it if necessary */
Jim Fultond15dc062004-07-14 19:11:50 +0000879static PyObject *
Victor Stinner61040132020-12-18 01:39:00 +0100880_ldict(localobject *self, thread_module_state *state)
Jim Fultond15dc062004-07-14 19:11:50 +0000881{
Victor Stinner8203c732020-12-16 12:20:33 +0100882 PyObject *tdict = PyThreadState_GetDict();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000883 if (tdict == NULL) {
884 PyErr_SetString(PyExc_SystemError,
885 "Couldn't get thread-state dictionary");
886 return NULL;
887 }
Jim Fultond15dc062004-07-14 19:11:50 +0000888
Victor Stinner8203c732020-12-16 12:20:33 +0100889 PyObject *ldict;
890 PyObject *dummy = PyDict_GetItemWithError(tdict, self->key);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000891 if (dummy == NULL) {
Serhiy Storchakaa24107b2019-02-25 17:59:46 +0200892 if (PyErr_Occurred()) {
893 return NULL;
894 }
Victor Stinner61040132020-12-18 01:39:00 +0100895 ldict = _local_create_dummy(self, state);
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000896 if (ldict == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000897 return NULL;
Jim Fultond15dc062004-07-14 19:11:50 +0000898
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000899 if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init &&
900 Py_TYPE(self)->tp_init((PyObject*)self,
901 self->args, self->kw) < 0) {
902 /* we need to get rid of ldict from thread so
903 we create a new one the next time we do an attr
Ezio Melotti42da6632011-03-15 05:18:48 +0200904 access */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000905 PyDict_DelItem(tdict, self->key);
906 return NULL;
907 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000908 }
909 else {
Victor Stinner61040132020-12-18 01:39:00 +0100910 assert(Py_IS_TYPE(dummy, state->local_dummy_type));
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000911 ldict = ((localdummyobject *) dummy)->localdict;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000912 }
Jim Fultond15dc062004-07-14 19:11:50 +0000913
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000914 return ldict;
Jim Fultond15dc062004-07-14 19:11:50 +0000915}
916
Jim Fultond15dc062004-07-14 19:11:50 +0000917static int
918local_setattro(localobject *self, PyObject *name, PyObject *v)
919{
Victor Stinner61040132020-12-18 01:39:00 +0100920 PyObject *module = _PyType_GetModuleByDef(Py_TYPE(self), &thread_module);
921 thread_module_state *state = get_thread_state(module);
922
923 PyObject *ldict = _ldict(self, state);
Victor Stinner8203c732020-12-16 12:20:33 +0100924 if (ldict == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000925 return -1;
Victor Stinner8203c732020-12-16 12:20:33 +0100926 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000927
Victor Stinner8203c732020-12-16 12:20:33 +0100928 PyObject *str_dict = _PyUnicode_FromId(&PyId___dict__); // borrowed ref
929 if (str_dict == NULL) {
930 return -1;
931 }
932
933 int r = PyObject_RichCompareBool(name, str_dict, Py_EQ);
934 if (r == -1) {
935 return -1;
936 }
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000937 if (r == 1) {
938 PyErr_Format(PyExc_AttributeError,
939 "'%.50s' object attribute '%U' is read-only",
940 Py_TYPE(self)->tp_name, name);
941 return -1;
942 }
Jim Fultond15dc062004-07-14 19:11:50 +0000943
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000944 return _PyObject_GenericSetAttrWithDict((PyObject *)self, name, v, ldict);
Jim Fultond15dc062004-07-14 19:11:50 +0000945}
946
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000947static PyObject *local_getattro(localobject *, PyObject *);
948
Victor Stinner61040132020-12-18 01:39:00 +0100949static PyMemberDef local_type_members[] = {
950 {"__weaklistoffset__", T_PYSSIZET, offsetof(localobject, weakreflist), READONLY},
951 {NULL},
952};
953
954static PyType_Slot local_type_slots[] = {
955 {Py_tp_dealloc, (destructor)local_dealloc},
956 {Py_tp_getattro, (getattrofunc)local_getattro},
957 {Py_tp_setattro, (setattrofunc)local_setattro},
958 {Py_tp_doc, "Thread-local data"},
959 {Py_tp_traverse, (traverseproc)local_traverse},
960 {Py_tp_clear, (inquiry)local_clear},
961 {Py_tp_new, local_new},
962 {Py_tp_members, local_type_members},
963 {0, 0}
964};
965
966static PyType_Spec local_type_spec = {
967 .name = "_thread._local",
968 .basicsize = sizeof(localobject),
969 .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
970 .slots = local_type_slots,
Jim Fultond15dc062004-07-14 19:11:50 +0000971};
972
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000973static PyObject *
974local_getattro(localobject *self, PyObject *name)
975{
Victor Stinner61040132020-12-18 01:39:00 +0100976 PyObject *module = _PyType_GetModuleByDef(Py_TYPE(self), &thread_module);
977 thread_module_state *state = get_thread_state(module);
978
979 PyObject *ldict = _ldict(self, state);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000980 if (ldict == NULL)
981 return NULL;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000982
Victor Stinner8203c732020-12-16 12:20:33 +0100983 PyObject *str_dict = _PyUnicode_FromId(&PyId___dict__); // borrowed ref
984 if (str_dict == NULL) {
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000985 return NULL;
Victor Stinner8203c732020-12-16 12:20:33 +0100986 }
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000987
Victor Stinner8203c732020-12-16 12:20:33 +0100988 int r = PyObject_RichCompareBool(name, str_dict, Py_EQ);
989 if (r == 1) {
990 return Py_NewRef(ldict);
991 }
992 if (r == -1) {
993 return NULL;
994 }
995
Victor Stinner61040132020-12-18 01:39:00 +0100996 if (!Py_IS_TYPE(self, state->local_type)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000997 /* use generic lookup for subtypes */
Victor Stinner8203c732020-12-16 12:20:33 +0100998 return _PyObject_GenericGetAttrWithDict((PyObject *)self, name,
999 ldict, 0);
1000 }
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001001
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001002 /* Optimization: just look in dict ourselves */
Victor Stinner8203c732020-12-16 12:20:33 +01001003 PyObject *value = PyDict_GetItemWithError(ldict, name);
Serhiy Storchakaa24107b2019-02-25 17:59:46 +02001004 if (value != NULL) {
Victor Stinner8203c732020-12-16 12:20:33 +01001005 return Py_NewRef(value);
Serhiy Storchakaa24107b2019-02-25 17:59:46 +02001006 }
Victor Stinner8203c732020-12-16 12:20:33 +01001007 if (PyErr_Occurred()) {
Serhiy Storchakaa24107b2019-02-25 17:59:46 +02001008 return NULL;
1009 }
Victor Stinner8203c732020-12-16 12:20:33 +01001010
Serhiy Storchakaa24107b2019-02-25 17:59:46 +02001011 /* Fall back on generic to get __class__ and __dict__ */
1012 return _PyObject_GenericGetAttrWithDict(
1013 (PyObject *)self, name, ldict, 0);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001014}
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001015
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001016/* Called when a dummy is destroyed. */
1017static PyObject *
1018_localdummy_destroyed(PyObject *localweakref, PyObject *dummyweakref)
1019{
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001020 assert(PyWeakref_CheckRef(localweakref));
Victor Stinner8203c732020-12-16 12:20:33 +01001021 PyObject *obj = PyWeakref_GET_OBJECT(localweakref);
1022 if (obj == Py_None) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001023 Py_RETURN_NONE;
Victor Stinner8203c732020-12-16 12:20:33 +01001024 }
1025
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001026 /* If the thread-local object is still alive and not being cleared,
1027 remove the corresponding local dict */
Victor Stinner8203c732020-12-16 12:20:33 +01001028 localobject *self = (localobject *)Py_NewRef(obj);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001029 if (self->dummies != NULL) {
1030 PyObject *ldict;
Serhiy Storchakaa24107b2019-02-25 17:59:46 +02001031 ldict = PyDict_GetItemWithError(self->dummies, dummyweakref);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001032 if (ldict != NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001033 PyDict_DelItem(self->dummies, dummyweakref);
1034 }
1035 if (PyErr_Occurred())
1036 PyErr_WriteUnraisable(obj);
1037 }
1038 Py_DECREF(obj);
1039 Py_RETURN_NONE;
1040}
1041
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001042/* Module functions */
1043
Guido van Rossuma027efa1997-05-05 20:56:21 +00001044struct bootstate {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001045 PyInterpreterState *interp;
1046 PyObject *func;
1047 PyObject *args;
Victor Stinner8203c732020-12-16 12:20:33 +01001048 PyObject *kwargs;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001049 PyThreadState *tstate;
Joannah Nanjekye2bc43cd2019-09-05 13:06:49 -03001050 _PyRuntimeState *runtime;
Guido van Rossuma027efa1997-05-05 20:56:21 +00001051};
1052
Victor Stinner8203c732020-12-16 12:20:33 +01001053
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001054static void
Victor Stinner8203c732020-12-16 12:20:33 +01001055thread_bootstate_free(struct bootstate *boot)
1056{
1057 Py_DECREF(boot->func);
1058 Py_DECREF(boot->args);
1059 Py_XDECREF(boot->kwargs);
1060 PyMem_Free(boot);
1061}
1062
1063
1064static void
1065thread_run(void *boot_raw)
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001066{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001067 struct bootstate *boot = (struct bootstate *) boot_raw;
1068 PyThreadState *tstate;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001069
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001070 tstate = boot->tstate;
1071 tstate->thread_id = PyThread_get_thread_ident();
Victor Stinner01b1cc12019-11-20 02:27:56 +01001072 _PyThreadState_Init(tstate);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001073 PyEval_AcquireThread(tstate);
Eric Snow2ebc5ce2017-09-07 23:51:28 -06001074 tstate->interp->num_threads++;
Victor Stinner8203c732020-12-16 12:20:33 +01001075
1076 PyObject *res = PyObject_Call(boot->func, boot->args, boot->kwargs);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001077 if (res == NULL) {
1078 if (PyErr_ExceptionMatches(PyExc_SystemExit))
Victor Stinner8b095002019-05-29 02:57:56 +02001079 /* SystemExit is ignored silently */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001080 PyErr_Clear();
1081 else {
Victor Stinner8b095002019-05-29 02:57:56 +02001082 _PyErr_WriteUnraisableMsg("in thread started by", boot->func);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001083 }
1084 }
Victor Stinner8b095002019-05-29 02:57:56 +02001085 else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001086 Py_DECREF(res);
Victor Stinner8b095002019-05-29 02:57:56 +02001087 }
Victor Stinner8203c732020-12-16 12:20:33 +01001088
1089 thread_bootstate_free(boot);
Eric Snow2ebc5ce2017-09-07 23:51:28 -06001090 tstate->interp->num_threads--;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001091 PyThreadState_Clear(tstate);
Victor Stinner23ef89d2020-03-18 02:26:04 +01001092 _PyThreadState_DeleteCurrent(tstate);
Victor Stinner8203c732020-12-16 12:20:33 +01001093
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001094 PyThread_exit_thread();
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001095}
1096
Barry Warsawd0c10421996-12-17 00:05:22 +00001097static PyObject *
Peter Schneider-Kamp3707efe2000-07-10 10:03:58 +00001098thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001099{
Joannah Nanjekye2bc43cd2019-09-05 13:06:49 -03001100 _PyRuntimeState *runtime = &_PyRuntime;
Victor Stinner8203c732020-12-16 12:20:33 +01001101 PyObject *func, *args, *kwargs = NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001102
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001103 if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3,
Victor Stinner8203c732020-12-16 12:20:33 +01001104 &func, &args, &kwargs))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001105 return NULL;
1106 if (!PyCallable_Check(func)) {
1107 PyErr_SetString(PyExc_TypeError,
1108 "first arg must be callable");
1109 return NULL;
1110 }
1111 if (!PyTuple_Check(args)) {
1112 PyErr_SetString(PyExc_TypeError,
1113 "2nd arg must be a tuple");
1114 return NULL;
1115 }
Victor Stinner8203c732020-12-16 12:20:33 +01001116 if (kwargs != NULL && !PyDict_Check(kwargs)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001117 PyErr_SetString(PyExc_TypeError,
1118 "optional 3rd arg must be a dictionary");
1119 return NULL;
1120 }
Victor Stinner252346a2020-05-01 11:33:44 +02001121
1122 PyInterpreterState *interp = _PyInterpreterState_GET();
1123 if (interp->config._isolated_interpreter) {
1124 PyErr_SetString(PyExc_RuntimeError,
1125 "thread is not supported for isolated subinterpreters");
1126 return NULL;
1127 }
1128
Victor Stinner8203c732020-12-16 12:20:33 +01001129 struct bootstate *boot = PyMem_NEW(struct bootstate, 1);
1130 if (boot == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001131 return PyErr_NoMemory();
Victor Stinner8203c732020-12-16 12:20:33 +01001132 }
Victor Stinner81a7be32020-04-14 15:14:01 +02001133 boot->interp = _PyInterpreterState_GET();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001134 boot->tstate = _PyThreadState_Prealloc(boot->interp);
1135 if (boot->tstate == NULL) {
Victor Stinner00d7abd2020-12-01 09:56:42 +01001136 PyMem_Free(boot);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001137 return PyErr_NoMemory();
1138 }
Victor Stinner8203c732020-12-16 12:20:33 +01001139 boot->runtime = runtime;
1140 boot->func = Py_NewRef(func);
1141 boot->args = Py_NewRef(args);
1142 boot->kwargs = Py_XNewRef(kwargs);
Victor Stinner3225b9f2020-03-09 20:56:57 +01001143
Victor Stinner8203c732020-12-16 12:20:33 +01001144 unsigned long ident = PyThread_start_new_thread(thread_run, (void*) boot);
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001145 if (ident == PYTHREAD_INVALID_THREAD_ID) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001146 PyErr_SetString(ThreadError, "can't start new thread");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001147 PyThreadState_Clear(boot->tstate);
Victor Stinner8203c732020-12-16 12:20:33 +01001148 thread_bootstate_free(boot);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001149 return NULL;
1150 }
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001151 return PyLong_FromUnsignedLong(ident);
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001152}
1153
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001154PyDoc_STRVAR(start_new_doc,
Andrew M. Kuchling38300c62001-10-05 12:24:15 +00001155"start_new_thread(function, args[, kwargs])\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001156(start_new() is an obsolete synonym)\n\
1157\n\
Guido van Rossum3c288632001-10-16 21:13:49 +00001158Start a new thread and return its identifier. The thread will call the\n\
1159function with positional arguments from the tuple args and keyword arguments\n\
1160taken from the optional dictionary kwargs. The thread exits when the\n\
1161function returns; the return value is ignored. The thread will also exit\n\
1162when the function raises an unhandled exception; a stack trace will be\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001163printed unless the exception is SystemExit.\n");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001164
Barry Warsawd0c10421996-12-17 00:05:22 +00001165static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301166thread_PyThread_exit_thread(PyObject *self, PyObject *Py_UNUSED(ignored))
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001167{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001168 PyErr_SetNone(PyExc_SystemExit);
1169 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001170}
1171
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001172PyDoc_STRVAR(exit_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001173"exit()\n\
Éric Araujo9bcf8bf2011-05-31 14:08:26 +02001174(exit_thread() is an obsolete synonym)\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001175\n\
1176This is synonymous to ``raise SystemExit''. It will cause the current\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001177thread to exit silently unless the exception is caught.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001178
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001179static PyObject *
Antoine Pitrouba251c22021-03-11 23:35:45 +01001180thread_PyThread_interrupt_main(PyObject *self, PyObject *args)
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001181{
Antoine Pitrouba251c22021-03-11 23:35:45 +01001182 int signum = SIGINT;
1183 if (!PyArg_ParseTuple(args, "|i:signum", &signum)) {
1184 return NULL;
1185 }
1186
1187 if (PyErr_SetInterruptEx(signum)) {
1188 PyErr_SetString(PyExc_ValueError, "signal number out of range");
1189 return NULL;
1190 }
Serhiy Storchaka228b12e2017-01-23 09:47:21 +02001191 Py_RETURN_NONE;
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001192}
1193
1194PyDoc_STRVAR(interrupt_doc,
Antoine Pitrouba251c22021-03-11 23:35:45 +01001195"interrupt_main(signum=signal.SIGINT, /)\n\
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001196\n\
Antoine Pitrouba251c22021-03-11 23:35:45 +01001197Simulate the arrival of the given signal in the main thread,\n\
1198where the corresponding signal handler will be executed.\n\
1199If *signum* is omitted, SIGINT is assumed.\n\
1200A subthread can use this function to interrupt the main thread.\n\
1201\n\
1202Note: the default signal hander for SIGINT raises ``KeyboardInterrupt``."
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001203);
1204
Victor Stinner61040132020-12-18 01:39:00 +01001205static lockobject *newlockobject(PyObject *module);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001206
Barry Warsawd0c10421996-12-17 00:05:22 +00001207static PyObject *
Victor Stinner8203c732020-12-16 12:20:33 +01001208thread_PyThread_allocate_lock(PyObject *module, PyObject *Py_UNUSED(ignored))
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001209{
Victor Stinner61040132020-12-18 01:39:00 +01001210 return (PyObject *) newlockobject(module);
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001211}
1212
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001213PyDoc_STRVAR(allocate_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001214"allocate_lock() -> lock object\n\
1215(allocate() is an obsolete synonym)\n\
1216\n\
Berker Peksag720e6552016-05-02 12:25:35 +03001217Create a new lock object. See help(type(threading.Lock())) for\n\
1218information about locks.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001219
Barry Warsawd0c10421996-12-17 00:05:22 +00001220static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301221thread_get_ident(PyObject *self, PyObject *Py_UNUSED(ignored))
Guido van Rossumb6775db1994-08-01 11:34:53 +00001222{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001223 unsigned long ident = PyThread_get_thread_ident();
1224 if (ident == PYTHREAD_INVALID_THREAD_ID) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001225 PyErr_SetString(ThreadError, "no current thread ident");
1226 return NULL;
1227 }
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001228 return PyLong_FromUnsignedLong(ident);
Guido van Rossumb6775db1994-08-01 11:34:53 +00001229}
1230
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001231PyDoc_STRVAR(get_ident_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001232"get_ident() -> integer\n\
1233\n\
1234Return a non-zero integer that uniquely identifies the current thread\n\
1235amongst other threads that exist simultaneously.\n\
1236This may be used to identify per-thread resources.\n\
1237Even though on some platforms threads identities may appear to be\n\
1238allocated consecutive numbers starting at 1, this behavior should not\n\
1239be relied upon, and the number should be seen purely as a magic cookie.\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001240A thread's identity may be reused for another thread after it exits.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001241
Jake Teslerb121f632019-05-22 08:43:17 -07001242#ifdef PY_HAVE_THREAD_NATIVE_ID
1243static PyObject *
1244thread_get_native_id(PyObject *self, PyObject *Py_UNUSED(ignored))
1245{
1246 unsigned long native_id = PyThread_get_thread_native_id();
1247 return PyLong_FromUnsignedLong(native_id);
1248}
1249
1250PyDoc_STRVAR(get_native_id_doc,
1251"get_native_id() -> integer\n\
1252\n\
1253Return a non-negative integer identifying the thread as reported\n\
1254by the OS (kernel). This may be used to uniquely identify a\n\
1255particular thread within a system.");
1256#endif
1257
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001258static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301259thread__count(PyObject *self, PyObject *Py_UNUSED(ignored))
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001260{
Victor Stinner81a7be32020-04-14 15:14:01 +02001261 PyInterpreterState *interp = _PyInterpreterState_GET();
Victor Stinnercaba55b2018-08-03 15:33:52 +02001262 return PyLong_FromLong(interp->num_threads);
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001263}
1264
1265PyDoc_STRVAR(_count_doc,
1266"_count() -> integer\n\
1267\n\
Antoine Pitrou9257f5e2009-10-30 22:23:02 +00001268\
oldkaa0735f2018-02-02 16:52:55 +08001269Return the number of currently running Python threads, excluding\n\
Antoine Pitrou9257f5e2009-10-30 22:23:02 +00001270the main thread. The returned number comprises all threads created\n\
1271through `start_new_thread()` as well as `threading.Thread`, and not\n\
1272yet finished.\n\
1273\n\
1274This function is meant for internal and specialized purposes only.\n\
1275In most applications `threading.enumerate()` should be used instead.");
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001276
Antoine Pitrou7b476992013-09-07 23:38:37 +02001277static void
Victor Stinnera42de742018-11-22 10:25:22 +01001278release_sentinel(void *wr_raw)
Antoine Pitrou7b476992013-09-07 23:38:37 +02001279{
Victor Stinnera42de742018-11-22 10:25:22 +01001280 PyObject *wr = _PyObject_CAST(wr_raw);
Antoine Pitrou7b476992013-09-07 23:38:37 +02001281 /* Tricky: this function is called when the current thread state
1282 is being deleted. Therefore, only simple C code can safely
1283 execute here. */
1284 PyObject *obj = PyWeakref_GET_OBJECT(wr);
1285 lockobject *lock;
1286 if (obj != Py_None) {
Antoine Pitrou7b476992013-09-07 23:38:37 +02001287 lock = (lockobject *) obj;
1288 if (lock->locked) {
1289 PyThread_release_lock(lock->lock_lock);
1290 lock->locked = 0;
1291 }
1292 }
1293 /* Deallocating a weakref with a NULL callback only calls
1294 PyObject_GC_Del(), which can't call any Python code. */
1295 Py_DECREF(wr);
1296}
1297
1298static PyObject *
Victor Stinner8203c732020-12-16 12:20:33 +01001299thread__set_sentinel(PyObject *module, PyObject *Py_UNUSED(ignored))
Antoine Pitrou7b476992013-09-07 23:38:37 +02001300{
1301 PyObject *wr;
1302 PyThreadState *tstate = PyThreadState_Get();
1303 lockobject *lock;
1304
1305 if (tstate->on_delete_data != NULL) {
1306 /* We must support the re-creation of the lock from a
1307 fork()ed child. */
1308 assert(tstate->on_delete == &release_sentinel);
1309 wr = (PyObject *) tstate->on_delete_data;
1310 tstate->on_delete = NULL;
1311 tstate->on_delete_data = NULL;
1312 Py_DECREF(wr);
1313 }
Victor Stinner61040132020-12-18 01:39:00 +01001314 lock = newlockobject(module);
Antoine Pitrou7b476992013-09-07 23:38:37 +02001315 if (lock == NULL)
1316 return NULL;
1317 /* The lock is owned by whoever called _set_sentinel(), but the weakref
1318 hangs to the thread state. */
1319 wr = PyWeakref_NewRef((PyObject *) lock, NULL);
1320 if (wr == NULL) {
1321 Py_DECREF(lock);
1322 return NULL;
1323 }
1324 tstate->on_delete_data = (void *) wr;
1325 tstate->on_delete = &release_sentinel;
1326 return (PyObject *) lock;
1327}
1328
1329PyDoc_STRVAR(_set_sentinel_doc,
1330"_set_sentinel() -> lock\n\
1331\n\
1332Set a sentinel lock that will be released when the current thread\n\
1333state is finalized (after it is untied from the interpreter).\n\
1334\n\
1335This is a private API for the threading module.");
1336
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001337static PyObject *
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001338thread_stack_size(PyObject *self, PyObject *args)
1339{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001340 size_t old_size;
1341 Py_ssize_t new_size = 0;
1342 int rc;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001343
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001344 if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size))
1345 return NULL;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001346
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001347 if (new_size < 0) {
1348 PyErr_SetString(PyExc_ValueError,
1349 "size must be 0 or a positive value");
1350 return NULL;
1351 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001352
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001353 old_size = PyThread_get_stacksize();
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001354
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001355 rc = PyThread_set_stacksize((size_t) new_size);
1356 if (rc == -1) {
1357 PyErr_Format(PyExc_ValueError,
1358 "size not valid: %zd bytes",
1359 new_size);
1360 return NULL;
1361 }
1362 if (rc == -2) {
1363 PyErr_SetString(ThreadError,
1364 "setting stack size not supported");
1365 return NULL;
1366 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001367
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001368 return PyLong_FromSsize_t((Py_ssize_t) old_size);
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001369}
1370
1371PyDoc_STRVAR(stack_size_doc,
1372"stack_size([size]) -> size\n\
1373\n\
1374Return the thread stack size used when creating new threads. The\n\
1375optional size argument specifies the stack size (in bytes) to be used\n\
1376for subsequently created threads, and must be 0 (use platform or\n\
1377configured default) or a positive integer value of at least 32,768 (32k).\n\
1378If changing the thread stack size is unsupported, a ThreadError\n\
1379exception is raised. If the specified size is invalid, a ValueError\n\
1380exception is raised, and the stack size is unmodified. 32k bytes\n\
1381 currently the minimum supported stack size value to guarantee\n\
1382sufficient stack space for the interpreter itself.\n\
1383\n\
1384Note that some platforms may have particular restrictions on values for\n\
Victor Stinner8c663fd2017-11-08 14:44:44 -08001385the stack size, such as requiring a minimum stack size larger than 32 KiB or\n\
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001386requiring allocation in multiples of the system memory page size\n\
1387- platform documentation should be referred to for more information\n\
Victor Stinner8c663fd2017-11-08 14:44:44 -08001388(4 KiB pages are common; using multiples of 4096 for the stack size is\n\
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001389the suggested approach in the absence of more specific information).");
1390
Victor Stinnercd590a72019-05-28 00:39:52 +02001391static int
1392thread_excepthook_file(PyObject *file, PyObject *exc_type, PyObject *exc_value,
1393 PyObject *exc_traceback, PyObject *thread)
1394{
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001395 _Py_IDENTIFIER(name);
Victor Stinnercd590a72019-05-28 00:39:52 +02001396 /* print(f"Exception in thread {thread.name}:", file=file) */
1397 if (PyFile_WriteString("Exception in thread ", file) < 0) {
1398 return -1;
1399 }
1400
1401 PyObject *name = NULL;
1402 if (thread != Py_None) {
Serhiy Storchaka41c57b32019-09-01 12:03:39 +03001403 if (_PyObject_LookupAttrId(thread, &PyId_name, &name) < 0) {
1404 return -1;
1405 }
Victor Stinnercd590a72019-05-28 00:39:52 +02001406 }
1407 if (name != NULL) {
1408 if (PyFile_WriteObject(name, file, Py_PRINT_RAW) < 0) {
1409 Py_DECREF(name);
1410 return -1;
1411 }
1412 Py_DECREF(name);
1413 }
1414 else {
Victor Stinnercd590a72019-05-28 00:39:52 +02001415 unsigned long ident = PyThread_get_thread_ident();
1416 PyObject *str = PyUnicode_FromFormat("%lu", ident);
1417 if (str != NULL) {
1418 if (PyFile_WriteObject(str, file, Py_PRINT_RAW) < 0) {
1419 Py_DECREF(str);
1420 return -1;
1421 }
1422 Py_DECREF(str);
1423 }
1424 else {
1425 PyErr_Clear();
1426
1427 if (PyFile_WriteString("<failed to get thread name>", file) < 0) {
1428 return -1;
1429 }
1430 }
1431 }
1432
1433 if (PyFile_WriteString(":\n", file) < 0) {
1434 return -1;
1435 }
1436
1437 /* Display the traceback */
1438 _PyErr_Display(file, exc_type, exc_value, exc_traceback);
1439
1440 /* Call file.flush() */
Jeroen Demeyer762f93f2019-07-08 10:19:25 +02001441 PyObject *res = _PyObject_CallMethodIdNoArgs(file, &PyId_flush);
Victor Stinnercd590a72019-05-28 00:39:52 +02001442 if (!res) {
1443 return -1;
1444 }
1445 Py_DECREF(res);
1446
1447 return 0;
1448}
1449
1450
1451PyDoc_STRVAR(ExceptHookArgs__doc__,
1452"ExceptHookArgs\n\
1453\n\
1454Type used to pass arguments to threading.excepthook.");
1455
1456static PyTypeObject ExceptHookArgsType;
1457
1458static PyStructSequence_Field ExceptHookArgs_fields[] = {
1459 {"exc_type", "Exception type"},
1460 {"exc_value", "Exception value"},
1461 {"exc_traceback", "Exception traceback"},
1462 {"thread", "Thread"},
1463 {0}
1464};
1465
1466static PyStructSequence_Desc ExceptHookArgs_desc = {
Victor Stinner8203c732020-12-16 12:20:33 +01001467 .name = "_thread._ExceptHookArgs",
Victor Stinnercd590a72019-05-28 00:39:52 +02001468 .doc = ExceptHookArgs__doc__,
1469 .fields = ExceptHookArgs_fields,
1470 .n_in_sequence = 4
1471};
1472
1473
1474static PyObject *
1475thread_excepthook(PyObject *self, PyObject *args)
1476{
Andy Lester55728702020-03-06 16:53:17 -06001477 if (!Py_IS_TYPE(args, &ExceptHookArgsType)) {
Victor Stinnercd590a72019-05-28 00:39:52 +02001478 PyErr_SetString(PyExc_TypeError,
1479 "_thread.excepthook argument type "
1480 "must be ExceptHookArgs");
1481 return NULL;
1482 }
1483
1484 /* Borrowed reference */
1485 PyObject *exc_type = PyStructSequence_GET_ITEM(args, 0);
1486 if (exc_type == PyExc_SystemExit) {
1487 /* silently ignore SystemExit */
1488 Py_RETURN_NONE;
1489 }
1490
1491 /* Borrowed references */
1492 PyObject *exc_value = PyStructSequence_GET_ITEM(args, 1);
1493 PyObject *exc_tb = PyStructSequence_GET_ITEM(args, 2);
1494 PyObject *thread = PyStructSequence_GET_ITEM(args, 3);
1495
1496 PyObject *file = _PySys_GetObjectId(&PyId_stderr);
1497 if (file == NULL || file == Py_None) {
1498 if (thread == Py_None) {
1499 /* do nothing if sys.stderr is None and thread is None */
1500 Py_RETURN_NONE;
1501 }
1502
1503 file = PyObject_GetAttrString(thread, "_stderr");
1504 if (file == NULL) {
1505 return NULL;
1506 }
1507 if (file == Py_None) {
1508 Py_DECREF(file);
1509 /* do nothing if sys.stderr is None and sys.stderr was None
1510 when the thread was created */
1511 Py_RETURN_NONE;
1512 }
1513 }
1514 else {
1515 Py_INCREF(file);
1516 }
1517
1518 int res = thread_excepthook_file(file, exc_type, exc_value, exc_tb,
1519 thread);
1520 Py_DECREF(file);
1521 if (res < 0) {
1522 return NULL;
1523 }
1524
1525 Py_RETURN_NONE;
1526}
1527
1528PyDoc_STRVAR(excepthook_doc,
1529"excepthook(exc_type, exc_value, exc_traceback, thread)\n\
1530\n\
1531Handle uncaught Thread.run() exception.");
1532
Barry Warsawd0c10421996-12-17 00:05:22 +00001533static PyMethodDef thread_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001534 {"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread,
Victor Stinner754851f2011-04-19 23:58:51 +02001535 METH_VARARGS, start_new_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001536 {"start_new", (PyCFunction)thread_PyThread_start_new_thread,
Victor Stinner754851f2011-04-19 23:58:51 +02001537 METH_VARARGS, start_new_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301538 {"allocate_lock", thread_PyThread_allocate_lock,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001539 METH_NOARGS, allocate_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301540 {"allocate", thread_PyThread_allocate_lock,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001541 METH_NOARGS, allocate_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301542 {"exit_thread", thread_PyThread_exit_thread,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001543 METH_NOARGS, exit_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301544 {"exit", thread_PyThread_exit_thread,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001545 METH_NOARGS, exit_doc},
Antoine Pitrouba251c22021-03-11 23:35:45 +01001546 {"interrupt_main", (PyCFunction)thread_PyThread_interrupt_main,
1547 METH_VARARGS, interrupt_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301548 {"get_ident", thread_get_ident,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001549 METH_NOARGS, get_ident_doc},
Jake Teslerb121f632019-05-22 08:43:17 -07001550#ifdef PY_HAVE_THREAD_NATIVE_ID
1551 {"get_native_id", thread_get_native_id,
1552 METH_NOARGS, get_native_id_doc},
1553#endif
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301554 {"_count", thread__count,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001555 METH_NOARGS, _count_doc},
1556 {"stack_size", (PyCFunction)thread_stack_size,
Victor Stinner754851f2011-04-19 23:58:51 +02001557 METH_VARARGS, stack_size_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301558 {"_set_sentinel", thread__set_sentinel,
Antoine Pitrou7b476992013-09-07 23:38:37 +02001559 METH_NOARGS, _set_sentinel_doc},
Victor Stinnercd590a72019-05-28 00:39:52 +02001560 {"_excepthook", thread_excepthook,
1561 METH_O, excepthook_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001562 {NULL, NULL} /* sentinel */
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001563};
1564
1565
1566/* Initialization function */
1567
Victor Stinner8203c732020-12-16 12:20:33 +01001568static int
Victor Stinner61040132020-12-18 01:39:00 +01001569thread_module_exec(PyObject *module)
Victor Stinner8203c732020-12-16 12:20:33 +01001570{
Victor Stinner61040132020-12-18 01:39:00 +01001571 thread_module_state *state = get_thread_state(module);
1572 PyObject *d = PyModule_GetDict(module);
1573
Victor Stinner8203c732020-12-16 12:20:33 +01001574 // Initialize the C thread library
1575 PyThread_init_thread();
1576
Victor Stinner61040132020-12-18 01:39:00 +01001577 // Lock
1578 state->lock_type = (PyTypeObject *)PyType_FromSpec(&lock_type_spec);
1579 if (state->lock_type == NULL) {
Victor Stinner8203c732020-12-16 12:20:33 +01001580 return -1;
1581 }
Victor Stinner61040132020-12-18 01:39:00 +01001582 if (PyDict_SetItemString(d, "LockType", (PyObject *)state->lock_type) < 0) {
Victor Stinner8203c732020-12-16 12:20:33 +01001583 return -1;
1584 }
Victor Stinner61040132020-12-18 01:39:00 +01001585
1586 // RLock
1587 PyTypeObject *rlock_type = (PyTypeObject *)PyType_FromSpec(&rlock_type_spec);
1588 if (rlock_type == NULL) {
Victor Stinner8203c732020-12-16 12:20:33 +01001589 return -1;
1590 }
Victor Stinner61040132020-12-18 01:39:00 +01001591 if (PyModule_AddType(module, rlock_type) < 0) {
1592 Py_DECREF(rlock_type);
1593 return -1;
1594 }
1595 Py_DECREF(rlock_type);
1596
1597 // Local dummy
1598 state->local_dummy_type = (PyTypeObject *)PyType_FromSpec(&local_dummy_type_spec);
1599 if (state->local_dummy_type == NULL) {
1600 return -1;
1601 }
1602
1603 // Local
1604 state->local_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, &local_type_spec, NULL);
1605 if (state->local_type == NULL) {
1606 return -1;
1607 }
1608 if (PyModule_AddType(module, state->local_type) < 0) {
1609 return -1;
1610 }
1611
Victor Stinner8203c732020-12-16 12:20:33 +01001612 if (ExceptHookArgsType.tp_name == NULL) {
1613 if (PyStructSequence_InitType2(&ExceptHookArgsType,
1614 &ExceptHookArgs_desc) < 0) {
1615 return -1;
1616 }
1617 }
1618
1619 // Add module attributes
Victor Stinner8203c732020-12-16 12:20:33 +01001620 if (PyDict_SetItemString(d, "error", ThreadError) < 0) {
1621 return -1;
1622 }
Victor Stinner8203c732020-12-16 12:20:33 +01001623 if (PyModule_AddType(module, &ExceptHookArgsType) < 0) {
1624 return -1;
1625 }
1626
1627 // TIMEOUT_MAX
1628 double timeout_max = (_PyTime_t)PY_TIMEOUT_MAX * 1e-6;
1629 double time_max = _PyTime_AsSecondsDouble(_PyTime_MAX);
1630 timeout_max = Py_MIN(timeout_max, time_max);
1631 // Round towards minus infinity
1632 timeout_max = floor(timeout_max);
1633
1634 if (PyModule_AddObject(module, "TIMEOUT_MAX",
1635 PyFloat_FromDouble(timeout_max)) < 0) {
1636 return -1;
1637 }
1638
1639 return 0;
1640}
1641
1642
Victor Stinner61040132020-12-18 01:39:00 +01001643static int
1644thread_module_traverse(PyObject *module, visitproc visit, void *arg)
1645{
1646 thread_module_state *state = get_thread_state(module);
1647 Py_VISIT(state->lock_type);
1648 Py_VISIT(state->local_type);
1649 Py_VISIT(state->local_dummy_type);
1650 return 0;
1651}
1652
1653static int
1654thread_module_clear(PyObject *module)
1655{
1656 thread_module_state *state = get_thread_state(module);
1657 Py_CLEAR(state->lock_type);
1658 Py_CLEAR(state->local_type);
1659 Py_CLEAR(state->local_dummy_type);
1660 return 0;
1661}
1662
1663static void
1664thread_module_free(void *module)
1665{
1666 thread_module_clear((PyObject *)module);
1667}
1668
1669
1670
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001671PyDoc_STRVAR(thread_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001672"This module provides primitive operations to write multi-threaded programs.\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001673The 'threading' module provides a more convenient interface.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001674
Victor Stinner61040132020-12-18 01:39:00 +01001675static PyModuleDef_Slot thread_module_slots[] = {
1676 {Py_mod_exec, thread_module_exec},
1677 {0, NULL}
1678};
1679
1680static struct PyModuleDef thread_module = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001681 PyModuleDef_HEAD_INIT,
Victor Stinner8203c732020-12-16 12:20:33 +01001682 .m_name = "_thread",
1683 .m_doc = thread_doc,
Victor Stinner61040132020-12-18 01:39:00 +01001684 .m_size = sizeof(thread_module_state),
Victor Stinner8203c732020-12-16 12:20:33 +01001685 .m_methods = thread_methods,
Victor Stinner61040132020-12-18 01:39:00 +01001686 .m_traverse = thread_module_traverse,
1687 .m_clear = thread_module_clear,
1688 .m_free = thread_module_free,
1689 .m_slots = thread_module_slots,
Martin v. Löwis1a214512008-06-11 05:26:20 +00001690};
1691
Mark Hammondfe51c6d2002-08-02 02:27:13 +00001692PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00001693PyInit__thread(void)
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001694{
Victor Stinner61040132020-12-18 01:39:00 +01001695 return PyModuleDef_Init(&thread_module);
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001696}