blob: 2b1a98f81b1a4e9f10408c152710a20ee40b2d78 [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 Stinner621cebe2018-11-12 16:53:38 +01007#include "pycore_pystate.h"
Benjamin Petersonbec4d572009-10-10 01:16:07 +00008#include "structmember.h" /* offsetof */
Guido van Rossum49b56061998-10-01 20:42:43 +00009#include "pythread.h"
Guido van Rossum1984f1e1992-08-04 12:41:02 +000010
Barry Warsawd0c10421996-12-17 00:05:22 +000011static PyObject *ThreadError;
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +000012static PyObject *str_dict;
Guido van Rossum1984f1e1992-08-04 12:41:02 +000013
Victor Stinnerbd303c12013-11-07 23:07:29 +010014_Py_IDENTIFIER(stderr);
Victor Stinnercd590a72019-05-28 00:39:52 +020015_Py_IDENTIFIER(flush);
Victor Stinnerbd303c12013-11-07 23:07:29 +010016
Guido van Rossum1984f1e1992-08-04 12:41:02 +000017/* Lock objects */
18
19typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000020 PyObject_HEAD
21 PyThread_type_lock lock_lock;
22 PyObject *in_weakreflist;
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +000023 char locked; /* for sanity checking */
Guido van Rossum1984f1e1992-08-04 12:41:02 +000024} lockobject;
25
Guido van Rossum1984f1e1992-08-04 12:41:02 +000026static void
Peter Schneider-Kamp3707efe2000-07-10 10:03:58 +000027lock_dealloc(lockobject *self)
Guido van Rossum1984f1e1992-08-04 12:41:02 +000028{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000029 if (self->in_weakreflist != NULL)
30 PyObject_ClearWeakRefs((PyObject *) self);
31 if (self->lock_lock != NULL) {
32 /* Unlock the lock so it's safe to free it */
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +000033 if (self->locked)
34 PyThread_release_lock(self->lock_lock);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000035 PyThread_free_lock(self->lock_lock);
36 }
37 PyObject_Del(self);
Guido van Rossum1984f1e1992-08-04 12:41:02 +000038}
39
Antoine Pitrou810023d2010-12-15 22:59:16 +000040/* Helper to acquire an interruptible lock with a timeout. If the lock acquire
41 * is interrupted, signal handlers are run, and if they raise an exception,
42 * PY_LOCK_INTR is returned. Otherwise, PY_LOCK_ACQUIRED or PY_LOCK_FAILURE
Raymond Hettinger15f44ab2016-08-30 10:47:49 -070043 * are returned, depending on whether the lock can be acquired within the
Antoine Pitrou810023d2010-12-15 22:59:16 +000044 * timeout.
45 */
46static PyLockStatus
Victor Stinnerf5faad22015-03-28 03:52:05 +010047acquire_timed(PyThread_type_lock lock, _PyTime_t timeout)
Antoine Pitrou810023d2010-12-15 22:59:16 +000048{
49 PyLockStatus r;
Victor Stinnerf5faad22015-03-28 03:52:05 +010050 _PyTime_t endtime = 0;
51 _PyTime_t microseconds;
Antoine Pitrou810023d2010-12-15 22:59:16 +000052
Victor Stinnerf5faad22015-03-28 03:52:05 +010053 if (timeout > 0)
54 endtime = _PyTime_GetMonotonicClock() + timeout;
Antoine Pitrou810023d2010-12-15 22:59:16 +000055
56 do {
Victor Stinner869e1772015-03-30 03:49:14 +020057 microseconds = _PyTime_AsMicroseconds(timeout, _PyTime_ROUND_CEILING);
Victor Stinnerf5faad22015-03-28 03:52:05 +010058
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +000059 /* first a simple non-blocking try without releasing the GIL */
60 r = PyThread_acquire_lock_timed(lock, 0, 0);
61 if (r == PY_LOCK_FAILURE && microseconds != 0) {
62 Py_BEGIN_ALLOW_THREADS
63 r = PyThread_acquire_lock_timed(lock, microseconds, 1);
64 Py_END_ALLOW_THREADS
Victor Stinner357f5152013-11-05 15:10:19 +010065 }
Antoine Pitrou810023d2010-12-15 22:59:16 +000066
67 if (r == PY_LOCK_INTR) {
68 /* Run signal handlers if we were interrupted. Propagate
69 * exceptions from signal handlers, such as KeyboardInterrupt, by
70 * passing up PY_LOCK_INTR. */
71 if (Py_MakePendingCalls() < 0) {
72 return PY_LOCK_INTR;
73 }
74
75 /* If we're using a timeout, recompute the timeout after processing
76 * signals, since those can take time. */
Victor Stinnerf5faad22015-03-28 03:52:05 +010077 if (timeout > 0) {
78 timeout = endtime - _PyTime_GetMonotonicClock();
Antoine Pitrou810023d2010-12-15 22:59:16 +000079
80 /* Check for negative values, since those mean block forever.
81 */
Victor Stinner6aa446c2015-03-30 21:33:51 +020082 if (timeout < 0) {
Antoine Pitrou810023d2010-12-15 22:59:16 +000083 r = PY_LOCK_FAILURE;
84 }
85 }
86 }
87 } while (r == PY_LOCK_INTR); /* Retry if we were interrupted. */
88
89 return r;
90}
91
Victor Stinnerf5faad22015-03-28 03:52:05 +010092static int
93lock_acquire_parse_args(PyObject *args, PyObject *kwds,
94 _PyTime_t *timeout)
Guido van Rossum1984f1e1992-08-04 12:41:02 +000095{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000096 char *kwlist[] = {"blocking", "timeout", NULL};
97 int blocking = 1;
Victor Stinnerf5faad22015-03-28 03:52:05 +010098 PyObject *timeout_obj = NULL;
Victor Stinner13019fd2015-04-03 13:10:54 +020099 const _PyTime_t unset_timeout = _PyTime_FromSeconds(-1);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000100
Victor Stinnerf5faad22015-03-28 03:52:05 +0100101 *timeout = unset_timeout ;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000102
Victor Stinnerf5faad22015-03-28 03:52:05 +0100103 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iO:acquire", kwlist,
104 &blocking, &timeout_obj))
105 return -1;
106
107 if (timeout_obj
Victor Stinner869e1772015-03-30 03:49:14 +0200108 && _PyTime_FromSecondsObject(timeout,
Pablo Galindo59af94f2017-10-18 08:13:09 +0100109 timeout_obj, _PyTime_ROUND_TIMEOUT) < 0)
Victor Stinnerf5faad22015-03-28 03:52:05 +0100110 return -1;
111
112 if (!blocking && *timeout != unset_timeout ) {
113 PyErr_SetString(PyExc_ValueError,
114 "can't specify a timeout for a non-blocking call");
115 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000116 }
Victor Stinnerf5faad22015-03-28 03:52:05 +0100117 if (*timeout < 0 && *timeout != unset_timeout) {
118 PyErr_SetString(PyExc_ValueError,
119 "timeout value must be positive");
120 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000121 }
122 if (!blocking)
Victor Stinnerf5faad22015-03-28 03:52:05 +0100123 *timeout = 0;
124 else if (*timeout != unset_timeout) {
125 _PyTime_t microseconds;
126
Pablo Galindo59af94f2017-10-18 08:13:09 +0100127 microseconds = _PyTime_AsMicroseconds(*timeout, _PyTime_ROUND_TIMEOUT);
Victor Stinnerf5faad22015-03-28 03:52:05 +0100128 if (microseconds >= PY_TIMEOUT_MAX) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000129 PyErr_SetString(PyExc_OverflowError,
130 "timeout value is too large");
Victor Stinnerf5faad22015-03-28 03:52:05 +0100131 return -1;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000132 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000133 }
Victor Stinnerf5faad22015-03-28 03:52:05 +0100134 return 0;
135}
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000136
Victor Stinnerf5faad22015-03-28 03:52:05 +0100137static PyObject *
138lock_PyThread_acquire_lock(lockobject *self, PyObject *args, PyObject *kwds)
139{
140 _PyTime_t timeout;
141 PyLockStatus r;
142
143 if (lock_acquire_parse_args(args, kwds, &timeout) < 0)
144 return NULL;
145
146 r = acquire_timed(self->lock_lock, timeout);
Antoine Pitrou810023d2010-12-15 22:59:16 +0000147 if (r == PY_LOCK_INTR) {
148 return NULL;
149 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000150
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +0000151 if (r == PY_LOCK_ACQUIRED)
152 self->locked = 1;
Antoine Pitrou810023d2010-12-15 22:59:16 +0000153 return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000154}
155
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000156PyDoc_STRVAR(acquire_doc,
Berker Peksag720e6552016-05-02 12:25:35 +0300157"acquire(blocking=True, timeout=-1) -> bool\n\
Guido van Rossumf6694362006-03-10 02:28:35 +0000158(acquire_lock() is an obsolete synonym)\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000159\n\
160Lock the lock. Without argument, this blocks if the lock is already\n\
161locked (even by the same thread), waiting for another thread to release\n\
R David Murray95b71102013-02-04 10:15:58 -0500162the lock, and return True once the lock is acquired.\n\
Guido van Rossum8fdc75b2002-04-07 06:32:21 +0000163With an argument, this will only block if the argument is true,\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000164and the return value reflects whether the lock is acquired.\n\
Antoine Pitrou810023d2010-12-15 22:59:16 +0000165The blocking operation is interruptible.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000166
Barry Warsawd0c10421996-12-17 00:05:22 +0000167static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530168lock_PyThread_release_lock(lockobject *self, PyObject *Py_UNUSED(ignored))
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000169{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000170 /* Sanity check: the lock must be locked */
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +0000171 if (!self->locked) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000172 PyErr_SetString(ThreadError, "release unlocked lock");
173 return NULL;
174 }
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000175
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000176 PyThread_release_lock(self->lock_lock);
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +0000177 self->locked = 0;
Serhiy Storchaka228b12e2017-01-23 09:47:21 +0200178 Py_RETURN_NONE;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000179}
180
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000181PyDoc_STRVAR(release_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000182"release()\n\
Guido van Rossumf6694362006-03-10 02:28:35 +0000183(release_lock() is an obsolete synonym)\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000184\n\
185Release the lock, allowing another thread that is blocked waiting for\n\
186the lock to acquire the lock. The lock must be in the locked state,\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000187but it needn't be locked by the same thread that unlocks it.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000188
Barry Warsawd0c10421996-12-17 00:05:22 +0000189static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530190lock_locked_lock(lockobject *self, PyObject *Py_UNUSED(ignored))
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000191{
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +0000192 return PyBool_FromLong((long)self->locked);
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000193}
194
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000195PyDoc_STRVAR(locked_doc,
Guido van Rossum8fdc75b2002-04-07 06:32:21 +0000196"locked() -> bool\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000197(locked_lock() is an obsolete synonym)\n\
198\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000199Return whether the lock is in the locked state.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +0000200
Raymond Hettinger62f4dad2014-05-25 18:22:35 -0700201static PyObject *
202lock_repr(lockobject *self)
203{
204 return PyUnicode_FromFormat("<%s %s object at %p>",
205 self->locked ? "locked" : "unlocked", Py_TYPE(self)->tp_name, self);
206}
207
Barry Warsawd0c10421996-12-17 00:05:22 +0000208static PyMethodDef lock_methods[] = {
Serhiy Storchaka62be7422018-11-27 13:27:31 +0200209 {"acquire_lock", (PyCFunction)(void(*)(void))lock_PyThread_acquire_lock,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000210 METH_VARARGS | METH_KEYWORDS, acquire_doc},
Serhiy Storchaka62be7422018-11-27 13:27:31 +0200211 {"acquire", (PyCFunction)(void(*)(void))lock_PyThread_acquire_lock,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000212 METH_VARARGS | METH_KEYWORDS, acquire_doc},
213 {"release_lock", (PyCFunction)lock_PyThread_release_lock,
214 METH_NOARGS, release_doc},
215 {"release", (PyCFunction)lock_PyThread_release_lock,
216 METH_NOARGS, release_doc},
217 {"locked_lock", (PyCFunction)lock_locked_lock,
218 METH_NOARGS, locked_doc},
219 {"locked", (PyCFunction)lock_locked_lock,
220 METH_NOARGS, locked_doc},
Serhiy Storchaka62be7422018-11-27 13:27:31 +0200221 {"__enter__", (PyCFunction)(void(*)(void))lock_PyThread_acquire_lock,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000222 METH_VARARGS | METH_KEYWORDS, acquire_doc},
223 {"__exit__", (PyCFunction)lock_PyThread_release_lock,
224 METH_VARARGS, release_doc},
225 {NULL, NULL} /* sentinel */
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000226};
227
Barry Warsawd0c10421996-12-17 00:05:22 +0000228static PyTypeObject Locktype = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000229 PyVarObject_HEAD_INIT(&PyType_Type, 0)
230 "_thread.lock", /*tp_name*/
Peter Eisentraut0e0bc4e2018-09-10 18:46:08 +0200231 sizeof(lockobject), /*tp_basicsize*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000232 0, /*tp_itemsize*/
233 /* methods */
234 (destructor)lock_dealloc, /*tp_dealloc*/
235 0, /*tp_print*/
236 0, /*tp_getattr*/
237 0, /*tp_setattr*/
238 0, /*tp_reserved*/
Raymond Hettinger62f4dad2014-05-25 18:22:35 -0700239 (reprfunc)lock_repr, /*tp_repr*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000240 0, /*tp_as_number*/
241 0, /*tp_as_sequence*/
242 0, /*tp_as_mapping*/
243 0, /*tp_hash*/
244 0, /*tp_call*/
245 0, /*tp_str*/
246 0, /*tp_getattro*/
247 0, /*tp_setattro*/
248 0, /*tp_as_buffer*/
249 Py_TPFLAGS_DEFAULT, /*tp_flags*/
250 0, /*tp_doc*/
251 0, /*tp_traverse*/
252 0, /*tp_clear*/
253 0, /*tp_richcompare*/
254 offsetof(lockobject, in_weakreflist), /*tp_weaklistoffset*/
255 0, /*tp_iter*/
256 0, /*tp_iternext*/
257 lock_methods, /*tp_methods*/
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000258};
259
Antoine Pitrou434736a2009-11-10 18:46:01 +0000260/* Recursive lock objects */
261
262typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000263 PyObject_HEAD
264 PyThread_type_lock rlock_lock;
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200265 unsigned long rlock_owner;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000266 unsigned long rlock_count;
267 PyObject *in_weakreflist;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000268} rlockobject;
269
270static void
271rlock_dealloc(rlockobject *self)
272{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000273 if (self->in_weakreflist != NULL)
274 PyObject_ClearWeakRefs((PyObject *) self);
Victor Stinner357f5152013-11-05 15:10:19 +0100275 /* self->rlock_lock can be NULL if PyThread_allocate_lock() failed
276 in rlock_new() */
277 if (self->rlock_lock != NULL) {
278 /* Unlock the lock so it's safe to free it */
279 if (self->rlock_count > 0)
280 PyThread_release_lock(self->rlock_lock);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000281
Victor Stinner357f5152013-11-05 15:10:19 +0100282 PyThread_free_lock(self->rlock_lock);
283 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000284 Py_TYPE(self)->tp_free(self);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000285}
286
287static PyObject *
288rlock_acquire(rlockobject *self, PyObject *args, PyObject *kwds)
289{
Victor Stinnerf5faad22015-03-28 03:52:05 +0100290 _PyTime_t timeout;
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200291 unsigned long tid;
Antoine Pitrou810023d2010-12-15 22:59:16 +0000292 PyLockStatus r = PY_LOCK_ACQUIRED;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000293
Victor Stinnerf5faad22015-03-28 03:52:05 +0100294 if (lock_acquire_parse_args(args, kwds, &timeout) < 0)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000295 return NULL;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000296
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000297 tid = PyThread_get_thread_ident();
298 if (self->rlock_count > 0 && tid == self->rlock_owner) {
299 unsigned long count = self->rlock_count + 1;
300 if (count <= self->rlock_count) {
301 PyErr_SetString(PyExc_OverflowError,
302 "Internal lock count overflowed");
303 return NULL;
304 }
305 self->rlock_count = count;
306 Py_RETURN_TRUE;
307 }
Victor Stinnerf5faad22015-03-28 03:52:05 +0100308 r = acquire_timed(self->rlock_lock, timeout);
Antoine Pitrou810023d2010-12-15 22:59:16 +0000309 if (r == PY_LOCK_ACQUIRED) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000310 assert(self->rlock_count == 0);
311 self->rlock_owner = tid;
312 self->rlock_count = 1;
313 }
Antoine Pitrou810023d2010-12-15 22:59:16 +0000314 else if (r == PY_LOCK_INTR) {
315 return NULL;
316 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000317
Antoine Pitrou810023d2010-12-15 22:59:16 +0000318 return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000319}
320
321PyDoc_STRVAR(rlock_acquire_doc,
322"acquire(blocking=True) -> bool\n\
323\n\
324Lock the lock. `blocking` indicates whether we should wait\n\
325for the lock to be available or not. If `blocking` is False\n\
326and another thread holds the lock, the method will return False\n\
327immediately. If `blocking` is True and another thread holds\n\
328the lock, the method will wait for the lock to be released,\n\
329take it and then return True.\n\
Antoine Pitrou810023d2010-12-15 22:59:16 +0000330(note: the blocking operation is interruptible.)\n\
Antoine Pitrou434736a2009-11-10 18:46:01 +0000331\n\
332In all other cases, the method will return True immediately.\n\
333Precisely, if the current thread already holds the lock, its\n\
334internal counter is simply incremented. If nobody holds the lock,\n\
335the lock is taken and its internal counter initialized to 1.");
336
337static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530338rlock_release(rlockobject *self, PyObject *Py_UNUSED(ignored))
Antoine Pitrou434736a2009-11-10 18:46:01 +0000339{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200340 unsigned long tid = PyThread_get_thread_ident();
Antoine Pitrou434736a2009-11-10 18:46:01 +0000341
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000342 if (self->rlock_count == 0 || self->rlock_owner != tid) {
343 PyErr_SetString(PyExc_RuntimeError,
344 "cannot release un-acquired lock");
345 return NULL;
346 }
347 if (--self->rlock_count == 0) {
348 self->rlock_owner = 0;
349 PyThread_release_lock(self->rlock_lock);
350 }
351 Py_RETURN_NONE;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000352}
353
354PyDoc_STRVAR(rlock_release_doc,
355"release()\n\
356\n\
357Release the lock, allowing another thread that is blocked waiting for\n\
358the lock to acquire the lock. The lock must be in the locked state,\n\
359and must be locked by the same thread that unlocks it; otherwise a\n\
360`RuntimeError` is raised.\n\
361\n\
362Do note that if the lock was acquire()d several times in a row by the\n\
363current thread, release() needs to be called as many times for the lock\n\
364to be available for other threads.");
365
366static PyObject *
Victor Stinnere8794522014-01-02 12:47:24 +0100367rlock_acquire_restore(rlockobject *self, PyObject *args)
Antoine Pitrou434736a2009-11-10 18:46:01 +0000368{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200369 unsigned long owner;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000370 unsigned long count;
371 int r = 1;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000372
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200373 if (!PyArg_ParseTuple(args, "(kk):_acquire_restore", &count, &owner))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000374 return NULL;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000375
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000376 if (!PyThread_acquire_lock(self->rlock_lock, 0)) {
377 Py_BEGIN_ALLOW_THREADS
378 r = PyThread_acquire_lock(self->rlock_lock, 1);
379 Py_END_ALLOW_THREADS
380 }
381 if (!r) {
382 PyErr_SetString(ThreadError, "couldn't acquire lock");
383 return NULL;
384 }
385 assert(self->rlock_count == 0);
386 self->rlock_owner = owner;
387 self->rlock_count = count;
388 Py_RETURN_NONE;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000389}
390
391PyDoc_STRVAR(rlock_acquire_restore_doc,
392"_acquire_restore(state) -> None\n\
393\n\
394For internal use by `threading.Condition`.");
395
396static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530397rlock_release_save(rlockobject *self, PyObject *Py_UNUSED(ignored))
Antoine Pitrou434736a2009-11-10 18:46:01 +0000398{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200399 unsigned long owner;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000400 unsigned long count;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000401
Victor Stinnerc2824d42011-04-24 23:41:33 +0200402 if (self->rlock_count == 0) {
403 PyErr_SetString(PyExc_RuntimeError,
404 "cannot release un-acquired lock");
405 return NULL;
406 }
407
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000408 owner = self->rlock_owner;
409 count = self->rlock_count;
410 self->rlock_count = 0;
411 self->rlock_owner = 0;
412 PyThread_release_lock(self->rlock_lock);
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200413 return Py_BuildValue("kk", count, owner);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000414}
415
416PyDoc_STRVAR(rlock_release_save_doc,
417"_release_save() -> tuple\n\
418\n\
419For internal use by `threading.Condition`.");
420
421
422static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +0530423rlock_is_owned(rlockobject *self, PyObject *Py_UNUSED(ignored))
Antoine Pitrou434736a2009-11-10 18:46:01 +0000424{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +0200425 unsigned long tid = PyThread_get_thread_ident();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000426
427 if (self->rlock_count > 0 && self->rlock_owner == tid) {
428 Py_RETURN_TRUE;
429 }
430 Py_RETURN_FALSE;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000431}
432
433PyDoc_STRVAR(rlock_is_owned_doc,
434"_is_owned() -> bool\n\
435\n\
436For internal use by `threading.Condition`.");
437
438static PyObject *
439rlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
440{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000441 rlockobject *self;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000442
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000443 self = (rlockobject *) type->tp_alloc(type, 0);
444 if (self != NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000445 self->in_weakreflist = NULL;
446 self->rlock_owner = 0;
447 self->rlock_count = 0;
Victor Stinner357f5152013-11-05 15:10:19 +0100448
449 self->rlock_lock = PyThread_allocate_lock();
450 if (self->rlock_lock == NULL) {
451 Py_DECREF(self);
452 PyErr_SetString(ThreadError, "can't allocate lock");
453 return NULL;
454 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000455 }
Antoine Pitrou434736a2009-11-10 18:46:01 +0000456
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000457 return (PyObject *) self;
Antoine Pitrou434736a2009-11-10 18:46:01 +0000458}
459
460static PyObject *
461rlock_repr(rlockobject *self)
462{
Raymond Hettinger62f4dad2014-05-25 18:22:35 -0700463 return PyUnicode_FromFormat("<%s %s object owner=%ld count=%lu at %p>",
464 self->rlock_count ? "locked" : "unlocked",
465 Py_TYPE(self)->tp_name, self->rlock_owner,
466 self->rlock_count, self);
Antoine Pitrou434736a2009-11-10 18:46:01 +0000467}
468
469
470static PyMethodDef rlock_methods[] = {
Serhiy Storchaka62be7422018-11-27 13:27:31 +0200471 {"acquire", (PyCFunction)(void(*)(void))rlock_acquire,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000472 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
473 {"release", (PyCFunction)rlock_release,
474 METH_NOARGS, rlock_release_doc},
475 {"_is_owned", (PyCFunction)rlock_is_owned,
476 METH_NOARGS, rlock_is_owned_doc},
477 {"_acquire_restore", (PyCFunction)rlock_acquire_restore,
Victor Stinnere8794522014-01-02 12:47:24 +0100478 METH_VARARGS, rlock_acquire_restore_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000479 {"_release_save", (PyCFunction)rlock_release_save,
480 METH_NOARGS, rlock_release_save_doc},
Serhiy Storchaka62be7422018-11-27 13:27:31 +0200481 {"__enter__", (PyCFunction)(void(*)(void))rlock_acquire,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000482 METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
483 {"__exit__", (PyCFunction)rlock_release,
484 METH_VARARGS, rlock_release_doc},
485 {NULL, NULL} /* sentinel */
Antoine Pitrou434736a2009-11-10 18:46:01 +0000486};
487
488
489static PyTypeObject RLocktype = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000490 PyVarObject_HEAD_INIT(&PyType_Type, 0)
491 "_thread.RLock", /*tp_name*/
Peter Eisentraut0e0bc4e2018-09-10 18:46:08 +0200492 sizeof(rlockobject), /*tp_basicsize*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000493 0, /*tp_itemsize*/
494 /* methods */
495 (destructor)rlock_dealloc, /*tp_dealloc*/
496 0, /*tp_print*/
497 0, /*tp_getattr*/
498 0, /*tp_setattr*/
499 0, /*tp_reserved*/
500 (reprfunc)rlock_repr, /*tp_repr*/
501 0, /*tp_as_number*/
502 0, /*tp_as_sequence*/
503 0, /*tp_as_mapping*/
504 0, /*tp_hash*/
505 0, /*tp_call*/
506 0, /*tp_str*/
507 0, /*tp_getattro*/
508 0, /*tp_setattro*/
509 0, /*tp_as_buffer*/
510 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
511 0, /*tp_doc*/
512 0, /*tp_traverse*/
513 0, /*tp_clear*/
514 0, /*tp_richcompare*/
515 offsetof(rlockobject, in_weakreflist), /*tp_weaklistoffset*/
516 0, /*tp_iter*/
517 0, /*tp_iternext*/
518 rlock_methods, /*tp_methods*/
519 0, /* tp_members */
520 0, /* tp_getset */
521 0, /* tp_base */
522 0, /* tp_dict */
523 0, /* tp_descr_get */
524 0, /* tp_descr_set */
525 0, /* tp_dictoffset */
526 0, /* tp_init */
527 PyType_GenericAlloc, /* tp_alloc */
528 rlock_new /* tp_new */
Antoine Pitrou434736a2009-11-10 18:46:01 +0000529};
530
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000531static lockobject *
532newlockobject(void)
533{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000534 lockobject *self;
535 self = PyObject_New(lockobject, &Locktype);
536 if (self == NULL)
537 return NULL;
538 self->lock_lock = PyThread_allocate_lock();
Kristjan Valur Jonsson69cf9132012-06-22 18:40:02 +0000539 self->locked = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000540 self->in_weakreflist = NULL;
541 if (self->lock_lock == NULL) {
542 Py_DECREF(self);
543 PyErr_SetString(ThreadError, "can't allocate lock");
544 return NULL;
545 }
546 return self;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000547}
548
Jim Fultond15dc062004-07-14 19:11:50 +0000549/* Thread-local objects */
550
551#include "structmember.h"
552
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000553/* Quick overview:
554
555 We need to be able to reclaim reference cycles as soon as possible
556 (both when a thread is being terminated, or a thread-local object
557 becomes unreachable from user data). Constraints:
558 - it must not be possible for thread-state dicts to be involved in
559 reference cycles (otherwise the cyclic GC will refuse to consider
560 objects referenced from a reachable thread-state dict, even though
561 local_dealloc would clear them)
562 - the death of a thread-state dict must still imply destruction of the
563 corresponding local dicts in all thread-local objects.
564
565 Our implementation uses small "localdummy" objects in order to break
566 the reference chain. These trivial objects are hashable (using the
567 default scheme of identity hashing) and weakrefable.
568 Each thread-state holds a separate localdummy for each local object
569 (as a /strong reference/),
570 and each thread-local object holds a dict mapping /weak references/
571 of localdummies to local dicts.
572
573 Therefore:
574 - only the thread-state dict holds a strong reference to the dummies
575 - only the thread-local object holds a strong reference to the local dicts
576 - only outside objects (application- or library-level) hold strong
577 references to the thread-local objects
578 - as soon as a thread-state dict is destroyed, the weakref callbacks of all
579 dummies attached to that thread are called, and destroy the corresponding
580 local dicts from thread-local objects
581 - as soon as a thread-local object is destroyed, its local dicts are
582 destroyed and its dummies are manually removed from all thread states
583 - the GC can do its work correctly when a thread-local object is dangling,
584 without any interference from the thread-state dicts
585
586 As an additional optimization, each localdummy holds a borrowed reference
587 to the corresponding localdict. This borrowed reference is only used
588 by the thread-local object which has created the localdummy, which should
589 guarantee that the localdict still exists when accessed.
590*/
591
592typedef struct {
593 PyObject_HEAD
594 PyObject *localdict; /* Borrowed reference! */
595 PyObject *weakreflist; /* List of weak references to self */
596} localdummyobject;
597
598static void
599localdummy_dealloc(localdummyobject *self)
600{
601 if (self->weakreflist != NULL)
602 PyObject_ClearWeakRefs((PyObject *) self);
603 Py_TYPE(self)->tp_free((PyObject*)self);
604}
605
606static PyTypeObject localdummytype = {
607 PyVarObject_HEAD_INIT(NULL, 0)
608 /* tp_name */ "_thread._localdummy",
609 /* tp_basicsize */ sizeof(localdummyobject),
610 /* tp_itemsize */ 0,
611 /* tp_dealloc */ (destructor)localdummy_dealloc,
612 /* tp_print */ 0,
613 /* tp_getattr */ 0,
614 /* tp_setattr */ 0,
615 /* tp_reserved */ 0,
616 /* tp_repr */ 0,
617 /* tp_as_number */ 0,
618 /* tp_as_sequence */ 0,
619 /* tp_as_mapping */ 0,
620 /* tp_hash */ 0,
621 /* tp_call */ 0,
622 /* tp_str */ 0,
623 /* tp_getattro */ 0,
624 /* tp_setattro */ 0,
625 /* tp_as_buffer */ 0,
626 /* tp_flags */ Py_TPFLAGS_DEFAULT,
627 /* tp_doc */ "Thread-local dummy",
628 /* tp_traverse */ 0,
629 /* tp_clear */ 0,
630 /* tp_richcompare */ 0,
631 /* tp_weaklistoffset */ offsetof(localdummyobject, weakreflist)
632};
633
634
Jim Fultond15dc062004-07-14 19:11:50 +0000635typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000636 PyObject_HEAD
637 PyObject *key;
638 PyObject *args;
639 PyObject *kw;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000640 PyObject *weakreflist; /* List of weak references to self */
641 /* A {localdummy weakref -> localdict} dict */
642 PyObject *dummies;
643 /* The callback for weakrefs to localdummies */
644 PyObject *wr_callback;
Jim Fultond15dc062004-07-14 19:11:50 +0000645} localobject;
646
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000647/* Forward declaration */
648static PyObject *_ldict(localobject *self);
649static PyObject *_localdummy_destroyed(PyObject *meth_self, PyObject *dummyweakref);
650
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000651/* Create and register the dummy for the current thread.
652 Returns a borrowed reference of the corresponding local dict */
653static PyObject *
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000654_local_create_dummy(localobject *self)
655{
656 PyObject *tdict, *ldict = NULL, *wr = NULL;
657 localdummyobject *dummy = NULL;
658 int r;
659
660 tdict = PyThreadState_GetDict();
661 if (tdict == NULL) {
662 PyErr_SetString(PyExc_SystemError,
663 "Couldn't get thread-state dictionary");
664 goto err;
665 }
666
667 ldict = PyDict_New();
668 if (ldict == NULL)
669 goto err;
670 dummy = (localdummyobject *) localdummytype.tp_alloc(&localdummytype, 0);
671 if (dummy == NULL)
672 goto err;
673 dummy->localdict = ldict;
674 wr = PyWeakref_NewRef((PyObject *) dummy, self->wr_callback);
675 if (wr == NULL)
676 goto err;
677
678 /* As a side-effect, this will cache the weakref's hash before the
679 dummy gets deleted */
680 r = PyDict_SetItem(self->dummies, wr, ldict);
681 if (r < 0)
682 goto err;
683 Py_CLEAR(wr);
684 r = PyDict_SetItem(tdict, self->key, (PyObject *) dummy);
685 if (r < 0)
686 goto err;
687 Py_CLEAR(dummy);
688
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000689 Py_DECREF(ldict);
690 return ldict;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000691
692err:
693 Py_XDECREF(ldict);
694 Py_XDECREF(wr);
695 Py_XDECREF(dummy);
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000696 return NULL;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000697}
698
Jim Fultond15dc062004-07-14 19:11:50 +0000699static PyObject *
700local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
701{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000702 localobject *self;
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000703 PyObject *wr;
704 static PyMethodDef wr_callback_def = {
705 "_localdummy_destroyed", (PyCFunction) _localdummy_destroyed, METH_O
706 };
Jim Fultond15dc062004-07-14 19:11:50 +0000707
Serhiy Storchakafa494fd2015-05-30 17:45:22 +0300708 if (type->tp_init == PyBaseObject_Type.tp_init) {
709 int rc = 0;
710 if (args != NULL)
711 rc = PyObject_IsTrue(args);
712 if (rc == 0 && kw != NULL)
713 rc = PyObject_IsTrue(kw);
714 if (rc != 0) {
715 if (rc > 0)
716 PyErr_SetString(PyExc_TypeError,
717 "Initialization arguments are not supported");
718 return NULL;
719 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000720 }
Jim Fultond15dc062004-07-14 19:11:50 +0000721
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000722 self = (localobject *)type->tp_alloc(type, 0);
723 if (self == NULL)
724 return NULL;
Jim Fultond15dc062004-07-14 19:11:50 +0000725
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000726 Py_XINCREF(args);
727 self->args = args;
728 Py_XINCREF(kw);
729 self->kw = kw;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000730 self->key = PyUnicode_FromFormat("thread.local.%p", self);
731 if (self->key == NULL)
732 goto err;
Jim Fultond15dc062004-07-14 19:11:50 +0000733
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000734 self->dummies = PyDict_New();
735 if (self->dummies == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000736 goto err;
Jim Fultond15dc062004-07-14 19:11:50 +0000737
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000738 /* We use a weak reference to self in the callback closure
739 in order to avoid spurious reference cycles */
740 wr = PyWeakref_NewRef((PyObject *) self, NULL);
741 if (wr == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000742 goto err;
Andrew Svetlov3ba3a3e2012-12-25 13:32:35 +0200743 self->wr_callback = PyCFunction_NewEx(&wr_callback_def, wr, NULL);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000744 Py_DECREF(wr);
745 if (self->wr_callback == NULL)
746 goto err;
Jim Fultond15dc062004-07-14 19:11:50 +0000747
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000748 if (_local_create_dummy(self) == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000749 goto err;
Jim Fultond15dc062004-07-14 19:11:50 +0000750
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000751 return (PyObject *)self;
Michael W. Hudson2368b3c2005-06-15 12:48:40 +0000752
753 err:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000754 Py_DECREF(self);
755 return NULL;
Jim Fultond15dc062004-07-14 19:11:50 +0000756}
757
758static int
759local_traverse(localobject *self, visitproc visit, void *arg)
760{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000761 Py_VISIT(self->args);
762 Py_VISIT(self->kw);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000763 Py_VISIT(self->dummies);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000764 return 0;
Jim Fultond15dc062004-07-14 19:11:50 +0000765}
766
767static int
768local_clear(localobject *self)
769{
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000770 PyThreadState *tstate;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000771 Py_CLEAR(self->args);
772 Py_CLEAR(self->kw);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000773 Py_CLEAR(self->dummies);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000774 Py_CLEAR(self->wr_callback);
775 /* Remove all strong references to dummies from the thread states */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000776 if (self->key
777 && (tstate = PyThreadState_Get())
778 && tstate->interp) {
779 for(tstate = PyInterpreterState_ThreadHead(tstate->interp);
780 tstate;
781 tstate = PyThreadState_Next(tstate))
Serhiy Storchaka8905fcc2018-12-11 08:38:03 +0200782 if (tstate->dict && PyDict_GetItem(tstate->dict, self->key)) {
783 if (PyDict_DelItem(tstate->dict, self->key)) {
784 PyErr_Clear();
785 }
786 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000787 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000788 return 0;
789}
Jim Fultond15dc062004-07-14 19:11:50 +0000790
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000791static void
792local_dealloc(localobject *self)
793{
794 /* Weakrefs must be invalidated right now, otherwise they can be used
795 from code called below, which is very dangerous since Py_REFCNT(self) == 0 */
796 if (self->weakreflist != NULL)
797 PyObject_ClearWeakRefs((PyObject *) self);
798
799 PyObject_GC_UnTrack(self);
800
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000801 local_clear(self);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000802 Py_XDECREF(self->key);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000803 Py_TYPE(self)->tp_free((PyObject*)self);
Jim Fultond15dc062004-07-14 19:11:50 +0000804}
805
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000806/* Returns a borrowed reference to the local dict, creating it if necessary */
Jim Fultond15dc062004-07-14 19:11:50 +0000807static PyObject *
808_ldict(localobject *self)
809{
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000810 PyObject *tdict, *ldict, *dummy;
Jim Fultond15dc062004-07-14 19:11:50 +0000811
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000812 tdict = PyThreadState_GetDict();
813 if (tdict == NULL) {
814 PyErr_SetString(PyExc_SystemError,
815 "Couldn't get thread-state dictionary");
816 return NULL;
817 }
Jim Fultond15dc062004-07-14 19:11:50 +0000818
Serhiy Storchakaa24107b2019-02-25 17:59:46 +0200819 dummy = PyDict_GetItemWithError(tdict, self->key);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000820 if (dummy == NULL) {
Serhiy Storchakaa24107b2019-02-25 17:59:46 +0200821 if (PyErr_Occurred()) {
822 return NULL;
823 }
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000824 ldict = _local_create_dummy(self);
825 if (ldict == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000826 return NULL;
Jim Fultond15dc062004-07-14 19:11:50 +0000827
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000828 if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init &&
829 Py_TYPE(self)->tp_init((PyObject*)self,
830 self->args, self->kw) < 0) {
831 /* we need to get rid of ldict from thread so
832 we create a new one the next time we do an attr
Ezio Melotti42da6632011-03-15 05:18:48 +0200833 access */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000834 PyDict_DelItem(tdict, self->key);
835 return NULL;
836 }
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000837 }
838 else {
839 assert(Py_TYPE(dummy) == &localdummytype);
840 ldict = ((localdummyobject *) dummy)->localdict;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000841 }
Jim Fultond15dc062004-07-14 19:11:50 +0000842
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000843 return ldict;
Jim Fultond15dc062004-07-14 19:11:50 +0000844}
845
Jim Fultond15dc062004-07-14 19:11:50 +0000846static int
847local_setattro(localobject *self, PyObject *name, PyObject *v)
848{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000849 PyObject *ldict;
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000850 int r;
Jim Fultond15dc062004-07-14 19:11:50 +0000851
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000852 ldict = _ldict(self);
853 if (ldict == NULL)
854 return -1;
855
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000856 r = PyObject_RichCompareBool(name, str_dict, Py_EQ);
857 if (r == 1) {
858 PyErr_Format(PyExc_AttributeError,
859 "'%.50s' object attribute '%U' is read-only",
860 Py_TYPE(self)->tp_name, name);
861 return -1;
862 }
863 if (r == -1)
864 return -1;
Jim Fultond15dc062004-07-14 19:11:50 +0000865
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000866 return _PyObject_GenericSetAttrWithDict((PyObject *)self, name, v, ldict);
Jim Fultond15dc062004-07-14 19:11:50 +0000867}
868
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000869static PyObject *local_getattro(localobject *, PyObject *);
870
Jim Fultond15dc062004-07-14 19:11:50 +0000871static PyTypeObject localtype = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000872 PyVarObject_HEAD_INIT(NULL, 0)
873 /* tp_name */ "_thread._local",
874 /* tp_basicsize */ sizeof(localobject),
875 /* tp_itemsize */ 0,
876 /* tp_dealloc */ (destructor)local_dealloc,
877 /* tp_print */ 0,
878 /* tp_getattr */ 0,
879 /* tp_setattr */ 0,
880 /* tp_reserved */ 0,
881 /* tp_repr */ 0,
882 /* tp_as_number */ 0,
883 /* tp_as_sequence */ 0,
884 /* tp_as_mapping */ 0,
885 /* tp_hash */ 0,
886 /* tp_call */ 0,
887 /* tp_str */ 0,
888 /* tp_getattro */ (getattrofunc)local_getattro,
889 /* tp_setattro */ (setattrofunc)local_setattro,
890 /* tp_as_buffer */ 0,
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000891 /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
892 | Py_TPFLAGS_HAVE_GC,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000893 /* tp_doc */ "Thread-local data",
894 /* tp_traverse */ (traverseproc)local_traverse,
895 /* tp_clear */ (inquiry)local_clear,
896 /* tp_richcompare */ 0,
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000897 /* tp_weaklistoffset */ offsetof(localobject, weakreflist),
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000898 /* tp_iter */ 0,
899 /* tp_iternext */ 0,
900 /* tp_methods */ 0,
901 /* tp_members */ 0,
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000902 /* tp_getset */ 0,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000903 /* tp_base */ 0,
904 /* tp_dict */ 0, /* internal use */
905 /* tp_descr_get */ 0,
906 /* tp_descr_set */ 0,
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000907 /* tp_dictoffset */ 0,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000908 /* tp_init */ 0,
909 /* tp_alloc */ 0,
910 /* tp_new */ local_new,
911 /* tp_free */ 0, /* Low-level free-mem routine */
912 /* tp_is_gc */ 0, /* For PyObject_IS_GC */
Jim Fultond15dc062004-07-14 19:11:50 +0000913};
914
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000915static PyObject *
916local_getattro(localobject *self, PyObject *name)
917{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000918 PyObject *ldict, *value;
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000919 int r;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000920
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000921 ldict = _ldict(self);
922 if (ldict == NULL)
923 return NULL;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000924
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +0000925 r = PyObject_RichCompareBool(name, str_dict, Py_EQ);
926 if (r == 1) {
927 Py_INCREF(ldict);
928 return ldict;
929 }
930 if (r == -1)
931 return NULL;
932
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000933 if (Py_TYPE(self) != &localtype)
934 /* use generic lookup for subtypes */
INADA Naoki378edee2018-01-16 20:52:41 +0900935 return _PyObject_GenericGetAttrWithDict(
936 (PyObject *)self, name, ldict, 0);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000937
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000938 /* Optimization: just look in dict ourselves */
Serhiy Storchakaa24107b2019-02-25 17:59:46 +0200939 value = PyDict_GetItemWithError(ldict, name);
940 if (value != NULL) {
941 Py_INCREF(value);
942 return value;
943 }
944 else if (PyErr_Occurred()) {
945 return NULL;
946 }
947 /* Fall back on generic to get __class__ and __dict__ */
948 return _PyObject_GenericGetAttrWithDict(
949 (PyObject *)self, name, ldict, 0);
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000950}
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000951
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000952/* Called when a dummy is destroyed. */
953static PyObject *
954_localdummy_destroyed(PyObject *localweakref, PyObject *dummyweakref)
955{
956 PyObject *obj;
957 localobject *self;
958 assert(PyWeakref_CheckRef(localweakref));
959 obj = PyWeakref_GET_OBJECT(localweakref);
960 if (obj == Py_None)
961 Py_RETURN_NONE;
962 Py_INCREF(obj);
963 assert(PyObject_TypeCheck(obj, &localtype));
964 /* If the thread-local object is still alive and not being cleared,
965 remove the corresponding local dict */
966 self = (localobject *) obj;
967 if (self->dummies != NULL) {
968 PyObject *ldict;
Serhiy Storchakaa24107b2019-02-25 17:59:46 +0200969 ldict = PyDict_GetItemWithError(self->dummies, dummyweakref);
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000970 if (ldict != NULL) {
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +0000971 PyDict_DelItem(self->dummies, dummyweakref);
972 }
973 if (PyErr_Occurred())
974 PyErr_WriteUnraisable(obj);
975 }
976 Py_DECREF(obj);
977 Py_RETURN_NONE;
978}
979
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000980/* Module functions */
981
Guido van Rossuma027efa1997-05-05 20:56:21 +0000982struct bootstate {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000983 PyInterpreterState *interp;
984 PyObject *func;
985 PyObject *args;
986 PyObject *keyw;
987 PyThreadState *tstate;
Guido van Rossuma027efa1997-05-05 20:56:21 +0000988};
989
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000990static void
Peter Schneider-Kamp3707efe2000-07-10 10:03:58 +0000991t_bootstrap(void *boot_raw)
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000992{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000993 struct bootstate *boot = (struct bootstate *) boot_raw;
994 PyThreadState *tstate;
995 PyObject *res;
Guido van Rossum1984f1e1992-08-04 12:41:02 +0000996
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000997 tstate = boot->tstate;
998 tstate->thread_id = PyThread_get_thread_ident();
Victor Stinner8bb32302019-04-24 16:47:40 +0200999 _PyThreadState_Init(&_PyRuntime, tstate);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001000 PyEval_AcquireThread(tstate);
Eric Snow2ebc5ce2017-09-07 23:51:28 -06001001 tstate->interp->num_threads++;
INADA Naoki72dccde2017-02-16 09:26:01 +09001002 res = PyObject_Call(boot->func, boot->args, boot->keyw);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001003 if (res == NULL) {
1004 if (PyErr_ExceptionMatches(PyExc_SystemExit))
Victor Stinner8b095002019-05-29 02:57:56 +02001005 /* SystemExit is ignored silently */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001006 PyErr_Clear();
1007 else {
Victor Stinner8b095002019-05-29 02:57:56 +02001008 _PyErr_WriteUnraisableMsg("in thread started by", boot->func);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001009 }
1010 }
Victor Stinner8b095002019-05-29 02:57:56 +02001011 else {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001012 Py_DECREF(res);
Victor Stinner8b095002019-05-29 02:57:56 +02001013 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001014 Py_DECREF(boot->func);
1015 Py_DECREF(boot->args);
1016 Py_XDECREF(boot->keyw);
1017 PyMem_DEL(boot_raw);
Eric Snow2ebc5ce2017-09-07 23:51:28 -06001018 tstate->interp->num_threads--;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001019 PyThreadState_Clear(tstate);
1020 PyThreadState_DeleteCurrent();
1021 PyThread_exit_thread();
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001022}
1023
Barry Warsawd0c10421996-12-17 00:05:22 +00001024static PyObject *
Peter Schneider-Kamp3707efe2000-07-10 10:03:58 +00001025thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001026{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001027 PyObject *func, *args, *keyw = NULL;
1028 struct bootstate *boot;
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001029 unsigned long ident;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001030
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001031 if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3,
1032 &func, &args, &keyw))
1033 return NULL;
1034 if (!PyCallable_Check(func)) {
1035 PyErr_SetString(PyExc_TypeError,
1036 "first arg must be callable");
1037 return NULL;
1038 }
1039 if (!PyTuple_Check(args)) {
1040 PyErr_SetString(PyExc_TypeError,
1041 "2nd arg must be a tuple");
1042 return NULL;
1043 }
1044 if (keyw != NULL && !PyDict_Check(keyw)) {
1045 PyErr_SetString(PyExc_TypeError,
1046 "optional 3rd arg must be a dictionary");
1047 return NULL;
1048 }
1049 boot = PyMem_NEW(struct bootstate, 1);
1050 if (boot == NULL)
1051 return PyErr_NoMemory();
Victor Stinnercaba55b2018-08-03 15:33:52 +02001052 boot->interp = _PyInterpreterState_Get();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001053 boot->func = func;
1054 boot->args = args;
1055 boot->keyw = keyw;
1056 boot->tstate = _PyThreadState_Prealloc(boot->interp);
1057 if (boot->tstate == NULL) {
1058 PyMem_DEL(boot);
1059 return PyErr_NoMemory();
1060 }
1061 Py_INCREF(func);
1062 Py_INCREF(args);
1063 Py_XINCREF(keyw);
1064 PyEval_InitThreads(); /* Start the interpreter's thread-awareness */
1065 ident = PyThread_start_new_thread(t_bootstrap, (void*) boot);
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001066 if (ident == PYTHREAD_INVALID_THREAD_ID) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001067 PyErr_SetString(ThreadError, "can't start new thread");
1068 Py_DECREF(func);
1069 Py_DECREF(args);
1070 Py_XDECREF(keyw);
1071 PyThreadState_Clear(boot->tstate);
1072 PyMem_DEL(boot);
1073 return NULL;
1074 }
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001075 return PyLong_FromUnsignedLong(ident);
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001076}
1077
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001078PyDoc_STRVAR(start_new_doc,
Andrew M. Kuchling38300c62001-10-05 12:24:15 +00001079"start_new_thread(function, args[, kwargs])\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001080(start_new() is an obsolete synonym)\n\
1081\n\
Guido van Rossum3c288632001-10-16 21:13:49 +00001082Start a new thread and return its identifier. The thread will call the\n\
1083function with positional arguments from the tuple args and keyword arguments\n\
1084taken from the optional dictionary kwargs. The thread exits when the\n\
1085function returns; the return value is ignored. The thread will also exit\n\
1086when the function raises an unhandled exception; a stack trace will be\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001087printed unless the exception is SystemExit.\n");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001088
Barry Warsawd0c10421996-12-17 00:05:22 +00001089static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301090thread_PyThread_exit_thread(PyObject *self, PyObject *Py_UNUSED(ignored))
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001091{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001092 PyErr_SetNone(PyExc_SystemExit);
1093 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001094}
1095
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001096PyDoc_STRVAR(exit_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001097"exit()\n\
Éric Araujo9bcf8bf2011-05-31 14:08:26 +02001098(exit_thread() is an obsolete synonym)\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001099\n\
1100This is synonymous to ``raise SystemExit''. It will cause the current\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001101thread to exit silently unless the exception is caught.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001102
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001103static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301104thread_PyThread_interrupt_main(PyObject * self, PyObject *Py_UNUSED(ignored))
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001105{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001106 PyErr_SetInterrupt();
Serhiy Storchaka228b12e2017-01-23 09:47:21 +02001107 Py_RETURN_NONE;
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001108}
1109
1110PyDoc_STRVAR(interrupt_doc,
1111"interrupt_main()\n\
1112\n\
1113Raise a KeyboardInterrupt in the main thread.\n\
Kurt B. Kaisera1ad5f62003-06-16 18:51:28 +00001114A subthread can use this function to interrupt the main thread."
Kurt B. Kaisera11e8462003-06-13 21:59:45 +00001115);
1116
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001117static lockobject *newlockobject(void);
1118
Barry Warsawd0c10421996-12-17 00:05:22 +00001119static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301120thread_PyThread_allocate_lock(PyObject *self, PyObject *Py_UNUSED(ignored))
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001121{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001122 return (PyObject *) newlockobject();
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001123}
1124
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001125PyDoc_STRVAR(allocate_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001126"allocate_lock() -> lock object\n\
1127(allocate() is an obsolete synonym)\n\
1128\n\
Berker Peksag720e6552016-05-02 12:25:35 +03001129Create a new lock object. See help(type(threading.Lock())) for\n\
1130information about locks.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001131
Barry Warsawd0c10421996-12-17 00:05:22 +00001132static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301133thread_get_ident(PyObject *self, PyObject *Py_UNUSED(ignored))
Guido van Rossumb6775db1994-08-01 11:34:53 +00001134{
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001135 unsigned long ident = PyThread_get_thread_ident();
1136 if (ident == PYTHREAD_INVALID_THREAD_ID) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001137 PyErr_SetString(ThreadError, "no current thread ident");
1138 return NULL;
1139 }
Serhiy Storchakaaefa7eb2017-03-23 15:48:39 +02001140 return PyLong_FromUnsignedLong(ident);
Guido van Rossumb6775db1994-08-01 11:34:53 +00001141}
1142
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001143PyDoc_STRVAR(get_ident_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001144"get_ident() -> integer\n\
1145\n\
1146Return a non-zero integer that uniquely identifies the current thread\n\
1147amongst other threads that exist simultaneously.\n\
1148This may be used to identify per-thread resources.\n\
1149Even though on some platforms threads identities may appear to be\n\
1150allocated consecutive numbers starting at 1, this behavior should not\n\
1151be relied upon, and the number should be seen purely as a magic cookie.\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001152A thread's identity may be reused for another thread after it exits.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001153
Jake Teslerb121f632019-05-22 08:43:17 -07001154#ifdef PY_HAVE_THREAD_NATIVE_ID
1155static PyObject *
1156thread_get_native_id(PyObject *self, PyObject *Py_UNUSED(ignored))
1157{
1158 unsigned long native_id = PyThread_get_thread_native_id();
1159 return PyLong_FromUnsignedLong(native_id);
1160}
1161
1162PyDoc_STRVAR(get_native_id_doc,
1163"get_native_id() -> integer\n\
1164\n\
1165Return a non-negative integer identifying the thread as reported\n\
1166by the OS (kernel). This may be used to uniquely identify a\n\
1167particular thread within a system.");
1168#endif
1169
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001170static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301171thread__count(PyObject *self, PyObject *Py_UNUSED(ignored))
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001172{
Victor Stinnercaba55b2018-08-03 15:33:52 +02001173 PyInterpreterState *interp = _PyInterpreterState_Get();
1174 return PyLong_FromLong(interp->num_threads);
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001175}
1176
1177PyDoc_STRVAR(_count_doc,
1178"_count() -> integer\n\
1179\n\
Antoine Pitrou9257f5e2009-10-30 22:23:02 +00001180\
oldkaa0735f2018-02-02 16:52:55 +08001181Return the number of currently running Python threads, excluding\n\
Antoine Pitrou9257f5e2009-10-30 22:23:02 +00001182the main thread. The returned number comprises all threads created\n\
1183through `start_new_thread()` as well as `threading.Thread`, and not\n\
1184yet finished.\n\
1185\n\
1186This function is meant for internal and specialized purposes only.\n\
1187In most applications `threading.enumerate()` should be used instead.");
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001188
Antoine Pitrou7b476992013-09-07 23:38:37 +02001189static void
Victor Stinnera42de742018-11-22 10:25:22 +01001190release_sentinel(void *wr_raw)
Antoine Pitrou7b476992013-09-07 23:38:37 +02001191{
Victor Stinnera42de742018-11-22 10:25:22 +01001192 PyObject *wr = _PyObject_CAST(wr_raw);
Antoine Pitrou7b476992013-09-07 23:38:37 +02001193 /* Tricky: this function is called when the current thread state
1194 is being deleted. Therefore, only simple C code can safely
1195 execute here. */
1196 PyObject *obj = PyWeakref_GET_OBJECT(wr);
1197 lockobject *lock;
1198 if (obj != Py_None) {
1199 assert(Py_TYPE(obj) == &Locktype);
1200 lock = (lockobject *) obj;
1201 if (lock->locked) {
1202 PyThread_release_lock(lock->lock_lock);
1203 lock->locked = 0;
1204 }
1205 }
1206 /* Deallocating a weakref with a NULL callback only calls
1207 PyObject_GC_Del(), which can't call any Python code. */
1208 Py_DECREF(wr);
1209}
1210
1211static PyObject *
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301212thread__set_sentinel(PyObject *self, PyObject *Py_UNUSED(ignored))
Antoine Pitrou7b476992013-09-07 23:38:37 +02001213{
1214 PyObject *wr;
1215 PyThreadState *tstate = PyThreadState_Get();
1216 lockobject *lock;
1217
1218 if (tstate->on_delete_data != NULL) {
1219 /* We must support the re-creation of the lock from a
1220 fork()ed child. */
1221 assert(tstate->on_delete == &release_sentinel);
1222 wr = (PyObject *) tstate->on_delete_data;
1223 tstate->on_delete = NULL;
1224 tstate->on_delete_data = NULL;
1225 Py_DECREF(wr);
1226 }
1227 lock = newlockobject();
1228 if (lock == NULL)
1229 return NULL;
1230 /* The lock is owned by whoever called _set_sentinel(), but the weakref
1231 hangs to the thread state. */
1232 wr = PyWeakref_NewRef((PyObject *) lock, NULL);
1233 if (wr == NULL) {
1234 Py_DECREF(lock);
1235 return NULL;
1236 }
1237 tstate->on_delete_data = (void *) wr;
1238 tstate->on_delete = &release_sentinel;
1239 return (PyObject *) lock;
1240}
1241
1242PyDoc_STRVAR(_set_sentinel_doc,
1243"_set_sentinel() -> lock\n\
1244\n\
1245Set a sentinel lock that will be released when the current thread\n\
1246state is finalized (after it is untied from the interpreter).\n\
1247\n\
1248This is a private API for the threading module.");
1249
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001250static PyObject *
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001251thread_stack_size(PyObject *self, PyObject *args)
1252{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001253 size_t old_size;
1254 Py_ssize_t new_size = 0;
1255 int rc;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001256
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001257 if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size))
1258 return NULL;
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001259
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001260 if (new_size < 0) {
1261 PyErr_SetString(PyExc_ValueError,
1262 "size must be 0 or a positive value");
1263 return NULL;
1264 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001265
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001266 old_size = PyThread_get_stacksize();
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001267
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001268 rc = PyThread_set_stacksize((size_t) new_size);
1269 if (rc == -1) {
1270 PyErr_Format(PyExc_ValueError,
1271 "size not valid: %zd bytes",
1272 new_size);
1273 return NULL;
1274 }
1275 if (rc == -2) {
1276 PyErr_SetString(ThreadError,
1277 "setting stack size not supported");
1278 return NULL;
1279 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001280
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001281 return PyLong_FromSsize_t((Py_ssize_t) old_size);
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001282}
1283
1284PyDoc_STRVAR(stack_size_doc,
1285"stack_size([size]) -> size\n\
1286\n\
1287Return the thread stack size used when creating new threads. The\n\
1288optional size argument specifies the stack size (in bytes) to be used\n\
1289for subsequently created threads, and must be 0 (use platform or\n\
1290configured default) or a positive integer value of at least 32,768 (32k).\n\
1291If changing the thread stack size is unsupported, a ThreadError\n\
1292exception is raised. If the specified size is invalid, a ValueError\n\
1293exception is raised, and the stack size is unmodified. 32k bytes\n\
1294 currently the minimum supported stack size value to guarantee\n\
1295sufficient stack space for the interpreter itself.\n\
1296\n\
1297Note that some platforms may have particular restrictions on values for\n\
Victor Stinner8c663fd2017-11-08 14:44:44 -08001298the stack size, such as requiring a minimum stack size larger than 32 KiB or\n\
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001299requiring allocation in multiples of the system memory page size\n\
1300- platform documentation should be referred to for more information\n\
Victor Stinner8c663fd2017-11-08 14:44:44 -08001301(4 KiB pages are common; using multiples of 4096 for the stack size is\n\
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001302the suggested approach in the absence of more specific information).");
1303
Victor Stinnercd590a72019-05-28 00:39:52 +02001304static int
1305thread_excepthook_file(PyObject *file, PyObject *exc_type, PyObject *exc_value,
1306 PyObject *exc_traceback, PyObject *thread)
1307{
1308 /* print(f"Exception in thread {thread.name}:", file=file) */
1309 if (PyFile_WriteString("Exception in thread ", file) < 0) {
1310 return -1;
1311 }
1312
1313 PyObject *name = NULL;
1314 if (thread != Py_None) {
1315 name = PyObject_GetAttrString(thread, "name");
1316 }
1317 if (name != NULL) {
1318 if (PyFile_WriteObject(name, file, Py_PRINT_RAW) < 0) {
1319 Py_DECREF(name);
1320 return -1;
1321 }
1322 Py_DECREF(name);
1323 }
1324 else {
1325 PyErr_Clear();
1326
1327 unsigned long ident = PyThread_get_thread_ident();
1328 PyObject *str = PyUnicode_FromFormat("%lu", ident);
1329 if (str != NULL) {
1330 if (PyFile_WriteObject(str, file, Py_PRINT_RAW) < 0) {
1331 Py_DECREF(str);
1332 return -1;
1333 }
1334 Py_DECREF(str);
1335 }
1336 else {
1337 PyErr_Clear();
1338
1339 if (PyFile_WriteString("<failed to get thread name>", file) < 0) {
1340 return -1;
1341 }
1342 }
1343 }
1344
1345 if (PyFile_WriteString(":\n", file) < 0) {
1346 return -1;
1347 }
1348
1349 /* Display the traceback */
1350 _PyErr_Display(file, exc_type, exc_value, exc_traceback);
1351
1352 /* Call file.flush() */
1353 PyObject *res = _PyObject_CallMethodId(file, &PyId_flush, NULL);
1354 if (!res) {
1355 return -1;
1356 }
1357 Py_DECREF(res);
1358
1359 return 0;
1360}
1361
1362
1363PyDoc_STRVAR(ExceptHookArgs__doc__,
1364"ExceptHookArgs\n\
1365\n\
1366Type used to pass arguments to threading.excepthook.");
1367
1368static PyTypeObject ExceptHookArgsType;
1369
1370static PyStructSequence_Field ExceptHookArgs_fields[] = {
1371 {"exc_type", "Exception type"},
1372 {"exc_value", "Exception value"},
1373 {"exc_traceback", "Exception traceback"},
1374 {"thread", "Thread"},
1375 {0}
1376};
1377
1378static PyStructSequence_Desc ExceptHookArgs_desc = {
1379 .name = "_thread.ExceptHookArgs",
1380 .doc = ExceptHookArgs__doc__,
1381 .fields = ExceptHookArgs_fields,
1382 .n_in_sequence = 4
1383};
1384
1385
1386static PyObject *
1387thread_excepthook(PyObject *self, PyObject *args)
1388{
1389 if (Py_TYPE(args) != &ExceptHookArgsType) {
1390 PyErr_SetString(PyExc_TypeError,
1391 "_thread.excepthook argument type "
1392 "must be ExceptHookArgs");
1393 return NULL;
1394 }
1395
1396 /* Borrowed reference */
1397 PyObject *exc_type = PyStructSequence_GET_ITEM(args, 0);
1398 if (exc_type == PyExc_SystemExit) {
1399 /* silently ignore SystemExit */
1400 Py_RETURN_NONE;
1401 }
1402
1403 /* Borrowed references */
1404 PyObject *exc_value = PyStructSequence_GET_ITEM(args, 1);
1405 PyObject *exc_tb = PyStructSequence_GET_ITEM(args, 2);
1406 PyObject *thread = PyStructSequence_GET_ITEM(args, 3);
1407
1408 PyObject *file = _PySys_GetObjectId(&PyId_stderr);
1409 if (file == NULL || file == Py_None) {
1410 if (thread == Py_None) {
1411 /* do nothing if sys.stderr is None and thread is None */
1412 Py_RETURN_NONE;
1413 }
1414
1415 file = PyObject_GetAttrString(thread, "_stderr");
1416 if (file == NULL) {
1417 return NULL;
1418 }
1419 if (file == Py_None) {
1420 Py_DECREF(file);
1421 /* do nothing if sys.stderr is None and sys.stderr was None
1422 when the thread was created */
1423 Py_RETURN_NONE;
1424 }
1425 }
1426 else {
1427 Py_INCREF(file);
1428 }
1429
1430 int res = thread_excepthook_file(file, exc_type, exc_value, exc_tb,
1431 thread);
1432 Py_DECREF(file);
1433 if (res < 0) {
1434 return NULL;
1435 }
1436
1437 Py_RETURN_NONE;
1438}
1439
1440PyDoc_STRVAR(excepthook_doc,
1441"excepthook(exc_type, exc_value, exc_traceback, thread)\n\
1442\n\
1443Handle uncaught Thread.run() exception.");
1444
Barry Warsawd0c10421996-12-17 00:05:22 +00001445static PyMethodDef thread_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001446 {"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread,
Victor Stinner754851f2011-04-19 23:58:51 +02001447 METH_VARARGS, start_new_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001448 {"start_new", (PyCFunction)thread_PyThread_start_new_thread,
Victor Stinner754851f2011-04-19 23:58:51 +02001449 METH_VARARGS, start_new_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301450 {"allocate_lock", thread_PyThread_allocate_lock,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001451 METH_NOARGS, allocate_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301452 {"allocate", thread_PyThread_allocate_lock,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001453 METH_NOARGS, allocate_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301454 {"exit_thread", thread_PyThread_exit_thread,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001455 METH_NOARGS, exit_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301456 {"exit", thread_PyThread_exit_thread,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001457 METH_NOARGS, exit_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301458 {"interrupt_main", thread_PyThread_interrupt_main,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001459 METH_NOARGS, interrupt_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301460 {"get_ident", thread_get_ident,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001461 METH_NOARGS, get_ident_doc},
Jake Teslerb121f632019-05-22 08:43:17 -07001462#ifdef PY_HAVE_THREAD_NATIVE_ID
1463 {"get_native_id", thread_get_native_id,
1464 METH_NOARGS, get_native_id_doc},
1465#endif
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301466 {"_count", thread__count,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001467 METH_NOARGS, _count_doc},
1468 {"stack_size", (PyCFunction)thread_stack_size,
Victor Stinner754851f2011-04-19 23:58:51 +02001469 METH_VARARGS, stack_size_doc},
Siddhesh Poyarekar55edd0c2018-04-30 00:29:33 +05301470 {"_set_sentinel", thread__set_sentinel,
Antoine Pitrou7b476992013-09-07 23:38:37 +02001471 METH_NOARGS, _set_sentinel_doc},
Victor Stinnercd590a72019-05-28 00:39:52 +02001472 {"_excepthook", thread_excepthook,
1473 METH_O, excepthook_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001474 {NULL, NULL} /* sentinel */
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001475};
1476
1477
1478/* Initialization function */
1479
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001480PyDoc_STRVAR(thread_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001481"This module provides primitive operations to write multi-threaded programs.\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001482The 'threading' module provides a more convenient interface.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001483
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001484PyDoc_STRVAR(lock_doc,
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001485"A lock object is a synchronization primitive. To create a lock,\n\
Berker Peksag720e6552016-05-02 12:25:35 +03001486call threading.Lock(). Methods are:\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001487\n\
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001488acquire() -- lock the lock, possibly blocking until it can be obtained\n\
1489release() -- unlock of the lock\n\
1490locked() -- test whether the lock is currently locked\n\
1491\n\
1492A lock is not owned by the thread that locked it; another thread may\n\
1493unlock it. A thread attempting to lock a lock that it has already locked\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +00001494will block until another thread unlocks it. Deadlocks may ensue.");
Guido van Rossum75e9fc31998-06-27 18:21:06 +00001495
Martin v. Löwis1a214512008-06-11 05:26:20 +00001496static struct PyModuleDef threadmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001497 PyModuleDef_HEAD_INIT,
1498 "_thread",
1499 thread_doc,
1500 -1,
1501 thread_methods,
1502 NULL,
1503 NULL,
1504 NULL,
1505 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00001506};
1507
1508
Mark Hammondfe51c6d2002-08-02 02:27:13 +00001509PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00001510PyInit__thread(void)
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001511{
Victor Stinnerf5faad22015-03-28 03:52:05 +01001512 PyObject *m, *d, *v;
1513 double time_max;
1514 double timeout_max;
Victor Stinnercaba55b2018-08-03 15:33:52 +02001515 PyInterpreterState *interp = _PyInterpreterState_Get();
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001516
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001517 /* Initialize types: */
Antoine Pitrou5af4f4b2010-08-09 22:38:19 +00001518 if (PyType_Ready(&localdummytype) < 0)
1519 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001520 if (PyType_Ready(&localtype) < 0)
1521 return NULL;
1522 if (PyType_Ready(&Locktype) < 0)
1523 return NULL;
1524 if (PyType_Ready(&RLocktype) < 0)
1525 return NULL;
Victor Stinnercd590a72019-05-28 00:39:52 +02001526 if (ExceptHookArgsType.tp_name == NULL) {
1527 if (PyStructSequence_InitType2(&ExceptHookArgsType,
1528 &ExceptHookArgs_desc) < 0) {
1529 return NULL;
1530 }
1531 }
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001532
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001533 /* Create the module and add the functions */
1534 m = PyModule_Create(&threadmodule);
1535 if (m == NULL)
1536 return NULL;
Antoine Pitrou7c3e5772010-04-14 15:44:10 +00001537
Victor Stinnerc319eee2017-11-30 23:03:47 +01001538 timeout_max = (_PyTime_t)PY_TIMEOUT_MAX * 1e-6;
Victor Stinner850a18e2017-10-24 16:53:32 -07001539 time_max = _PyTime_AsSecondsDouble(_PyTime_MAX);
Victor Stinnerf5faad22015-03-28 03:52:05 +01001540 timeout_max = Py_MIN(timeout_max, time_max);
Victor Stinner850a18e2017-10-24 16:53:32 -07001541 /* Round towards minus infinity */
1542 timeout_max = floor(timeout_max);
Victor Stinnerf5faad22015-03-28 03:52:05 +01001543
1544 v = PyFloat_FromDouble(timeout_max);
1545 if (!v)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001546 return NULL;
Victor Stinnerf5faad22015-03-28 03:52:05 +01001547 if (PyModule_AddObject(m, "TIMEOUT_MAX", v) < 0)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001548 return NULL;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001549
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001550 /* Add a symbolic constant */
1551 d = PyModule_GetDict(m);
Antoine Pitroufcf81fd2011-02-28 22:03:34 +00001552 ThreadError = PyExc_RuntimeError;
1553 Py_INCREF(ThreadError);
Victor Stinner754851f2011-04-19 23:58:51 +02001554
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001555 PyDict_SetItemString(d, "error", ThreadError);
1556 Locktype.tp_doc = lock_doc;
1557 Py_INCREF(&Locktype);
1558 PyDict_SetItemString(d, "LockType", (PyObject *)&Locktype);
Antoine Pitrou434736a2009-11-10 18:46:01 +00001559
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001560 Py_INCREF(&RLocktype);
1561 if (PyModule_AddObject(m, "RLock", (PyObject *)&RLocktype) < 0)
1562 return NULL;
Jim Fultond15dc062004-07-14 19:11:50 +00001563
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001564 Py_INCREF(&localtype);
1565 if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0)
1566 return NULL;
Antoine Pitrou65c9c642009-10-30 17:25:12 +00001567
Victor Stinnercd590a72019-05-28 00:39:52 +02001568 Py_INCREF(&ExceptHookArgsType);
1569 if (PyModule_AddObject(m, "_ExceptHookArgs",
1570 (PyObject *)&ExceptHookArgsType) < 0)
1571 return NULL;
1572
Victor Stinnercaba55b2018-08-03 15:33:52 +02001573 interp->num_threads = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001574
Antoine Pitrou1a9a9d52010-08-28 18:17:03 +00001575 str_dict = PyUnicode_InternFromString("__dict__");
1576 if (str_dict == NULL)
1577 return NULL;
1578
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001579 /* Initialize the C thread library */
1580 PyThread_init_thread();
1581 return m;
Guido van Rossum1984f1e1992-08-04 12:41:02 +00001582}