Coverage Report

Created: 2026-04-12 06:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython3/Modules/_threadmodule.c
Line
Count
Source
1
/* Thread module */
2
/* Interface to Sjoerd's portable C thread library */
3
4
#include "Python.h"
5
#include "pycore_fileutils.h"     // _PyFile_Flush
6
#include "pycore_interp.h"        // _PyInterpreterState.threads.count
7
#include "pycore_lock.h"
8
#include "pycore_modsupport.h"    // _PyArg_NoKeywords()
9
#include "pycore_moduleobject.h"  // _PyModule_GetState()
10
#include "pycore_object_deferred.h" // _PyObject_SetDeferredRefcount()
11
#include "pycore_pylifecycle.h"
12
#include "pycore_pystate.h"       // _PyThreadState_SetCurrent()
13
#include "pycore_time.h"          // _PyTime_FromSeconds()
14
#include "pycore_tuple.h"         // _PyTuple_FromPairSteal
15
#include "pycore_weakref.h"       // _PyWeakref_GET_REF()
16
17
#include <stddef.h>               // offsetof()
18
#ifdef HAVE_SIGNAL_H
19
#  include <signal.h>             // SIGINT
20
#endif
21
22
// ThreadError is just an alias to PyExc_RuntimeError
23
22
#define ThreadError PyExc_RuntimeError
24
25
// Forward declarations
26
static struct PyModuleDef thread_module;
27
28
// Module state
29
typedef struct {
30
    PyTypeObject *excepthook_type;
31
    PyTypeObject *lock_type;
32
    PyTypeObject *rlock_type;
33
    PyTypeObject *local_type;
34
    PyTypeObject *local_dummy_type;
35
    PyTypeObject *thread_handle_type;
36
37
    // Linked list of handles to all non-daemon threads created by the
38
    // threading module. We wait for these to finish at shutdown.
39
    struct llist_node shutdown_handles;
40
} thread_module_state;
41
42
typedef struct {
43
    PyObject_HEAD
44
    PyMutex lock;
45
} lockobject;
46
47
0
#define lockobject_CAST(op) ((lockobject *)(op))
48
49
typedef struct {
50
    PyObject_HEAD
51
    _PyRecursiveMutex lock;
52
} rlockobject;
53
54
0
#define rlockobject_CAST(op)    ((rlockobject *)(op))
55
56
static inline thread_module_state*
57
get_thread_state(PyObject *module)
58
2.99k
{
59
2.99k
    void *state = _PyModule_GetState(module);
60
2.99k
    assert(state != NULL);
61
2.99k
    return (thread_module_state *)state;
62
2.99k
}
63
64
static inline thread_module_state*
65
get_thread_state_by_cls(PyTypeObject *cls)
66
1.27k
{
67
    // Use PyType_GetModuleByDef() to handle (R)Lock subclasses.
68
1.27k
    PyObject *module = PyType_GetModuleByDef(cls, &thread_module);
69
1.27k
    if (module == NULL) {
70
0
        return NULL;
71
0
    }
72
1.27k
    return get_thread_state(module);
73
1.27k
}
74
75
76
#ifdef MS_WINDOWS
77
typedef HRESULT (WINAPI *PF_GET_THREAD_DESCRIPTION)(HANDLE, PCWSTR*);
78
typedef HRESULT (WINAPI *PF_SET_THREAD_DESCRIPTION)(HANDLE, PCWSTR);
79
static PF_GET_THREAD_DESCRIPTION pGetThreadDescription = NULL;
80
static PF_SET_THREAD_DESCRIPTION pSetThreadDescription = NULL;
81
#endif
82
83
84
/*[clinic input]
85
module _thread
86
class _thread.lock "lockobject *" "clinic_state()->lock_type"
87
class _thread.RLock "rlockobject *" "clinic_state()->rlock_type"
88
[clinic start generated code]*/
89
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c5a0f8c492a0c263]*/
90
91
1.27k
#define clinic_state() get_thread_state_by_cls(type)
92
#include "clinic/_threadmodule.c.h"
93
#undef clinic_state
94
95
// _ThreadHandle type
96
97
// Handles state transitions according to the following diagram:
98
//
99
//     NOT_STARTED -> STARTING -> RUNNING -> DONE
100
//                       |                    ^
101
//                       |                    |
102
//                       +----- error --------+
103
typedef enum {
104
    THREAD_HANDLE_NOT_STARTED = 1,
105
    THREAD_HANDLE_STARTING = 2,
106
    THREAD_HANDLE_RUNNING = 3,
107
    THREAD_HANDLE_DONE = 4,
108
} ThreadHandleState;
109
110
// A handle to wait for thread completion.
111
//
112
// This may be used to wait for threads that were spawned by the threading
113
// module as well as for the "main" thread of the threading module. In the
114
// former case an OS thread, identified by the `os_handle` field, will be
115
// associated with the handle. The handle "owns" this thread and ensures that
116
// the thread is either joined or detached after the handle is destroyed.
117
//
118
// Joining the handle is idempotent; the underlying OS thread, if any, is
119
// joined or detached only once. Concurrent join operations are serialized
120
// until it is their turn to execute or an earlier operation completes
121
// successfully. Once a join has completed successfully all future joins
122
// complete immediately.
123
//
124
// This must be separately reference counted because it may be destroyed
125
// in `thread_run()` after the PyThreadState has been destroyed.
126
typedef struct {
127
    struct llist_node node;  // linked list node (see _pythread_runtime_state)
128
129
    // linked list node (see thread_module_state)
130
    struct llist_node shutdown_node;
131
132
    // The `ident`, `os_handle`, `has_os_handle`, and `state` fields are
133
    // protected by `mutex`.
134
    PyThread_ident_t ident;
135
    PyThread_handle_t os_handle;
136
    int has_os_handle;
137
138
    // Holds a value from the `ThreadHandleState` enum.
139
    int state;
140
141
    PyMutex mutex;
142
143
    // Set immediately before `thread_run` returns to indicate that the OS
144
    // thread is about to exit. This is used to avoid false positives when
145
    // detecting self-join attempts. See the comment in `ThreadHandle_join()`
146
    // for a more detailed explanation.
147
    PyEvent thread_is_exiting;
148
149
    // Serializes calls to `join` and `set_done`.
150
    _PyOnceFlag once;
151
152
    Py_ssize_t refcount;
153
} ThreadHandle;
154
155
static inline int
156
get_thread_handle_state(ThreadHandle *handle)
157
0
{
158
0
    PyMutex_Lock(&handle->mutex);
159
0
    int state = handle->state;
160
0
    PyMutex_Unlock(&handle->mutex);
161
0
    return state;
162
0
}
163
164
static inline void
165
set_thread_handle_state(ThreadHandle *handle, ThreadHandleState state)
166
0
{
167
0
    PyMutex_Lock(&handle->mutex);
168
0
    handle->state = state;
169
0
    PyMutex_Unlock(&handle->mutex);
170
0
}
171
172
static PyThread_ident_t
173
ThreadHandle_ident(ThreadHandle *handle)
174
0
{
175
0
    PyMutex_Lock(&handle->mutex);
176
0
    PyThread_ident_t ident = handle->ident;
177
0
    PyMutex_Unlock(&handle->mutex);
178
0
    return ident;
179
0
}
180
181
static int
182
ThreadHandle_get_os_handle(ThreadHandle *handle, PyThread_handle_t *os_handle)
183
0
{
184
0
    PyMutex_Lock(&handle->mutex);
185
0
    int has_os_handle = handle->has_os_handle;
186
0
    if (has_os_handle) {
187
0
        *os_handle = handle->os_handle;
188
0
    }
189
0
    PyMutex_Unlock(&handle->mutex);
190
0
    return has_os_handle;
191
0
}
192
193
static void
194
add_to_shutdown_handles(thread_module_state *state, ThreadHandle *handle)
195
0
{
196
0
    HEAD_LOCK(&_PyRuntime);
197
0
    llist_insert_tail(&state->shutdown_handles, &handle->shutdown_node);
198
0
    HEAD_UNLOCK(&_PyRuntime);
199
0
}
200
201
static void
202
clear_shutdown_handles(thread_module_state *state)
203
0
{
204
0
    HEAD_LOCK(&_PyRuntime);
205
0
    struct llist_node *node;
206
0
    llist_for_each_safe(node, &state->shutdown_handles) {
207
0
        llist_remove(node);
208
0
    }
209
0
    HEAD_UNLOCK(&_PyRuntime);
210
0
}
211
212
static void
213
remove_from_shutdown_handles(ThreadHandle *handle)
214
0
{
215
0
    HEAD_LOCK(&_PyRuntime);
216
0
    if (handle->shutdown_node.next != NULL) {
217
0
        llist_remove(&handle->shutdown_node);
218
0
    }
219
0
    HEAD_UNLOCK(&_PyRuntime);
220
0
}
221
222
static ThreadHandle *
223
ThreadHandle_new(void)
224
0
{
225
0
    ThreadHandle *self =
226
0
        (ThreadHandle *)PyMem_RawCalloc(1, sizeof(ThreadHandle));
227
0
    if (self == NULL) {
228
0
        PyErr_NoMemory();
229
0
        return NULL;
230
0
    }
231
0
    self->ident = 0;
232
0
    self->os_handle = 0;
233
0
    self->has_os_handle = 0;
234
0
    self->thread_is_exiting = (PyEvent){0};
235
0
    self->mutex = (PyMutex){_Py_UNLOCKED};
236
0
    self->once = (_PyOnceFlag){0};
237
0
    self->state = THREAD_HANDLE_NOT_STARTED;
238
0
    self->refcount = 1;
239
240
0
    HEAD_LOCK(&_PyRuntime);
241
0
    llist_insert_tail(&_PyRuntime.threads.handles, &self->node);
242
0
    HEAD_UNLOCK(&_PyRuntime);
243
244
0
    return self;
245
0
}
246
247
static void
248
ThreadHandle_incref(ThreadHandle *self)
249
0
{
250
0
    _Py_atomic_add_ssize(&self->refcount, 1);
251
0
}
252
253
static int
254
detach_thread(ThreadHandle *self)
255
0
{
256
0
    if (!self->has_os_handle) {
257
0
        return 0;
258
0
    }
259
    // This is typically short so no need to release the GIL
260
0
    if (PyThread_detach_thread(self->os_handle)) {
261
0
        fprintf(stderr, "detach_thread: failed detaching thread\n");
262
0
        return -1;
263
0
    }
264
0
    return 0;
265
0
}
266
267
// NB: This may be called after the PyThreadState in `thread_run` has been
268
// deleted; it cannot call anything that relies on a valid PyThreadState
269
// existing.
270
static void
271
ThreadHandle_decref(ThreadHandle *self)
272
0
{
273
0
    if (_Py_atomic_add_ssize(&self->refcount, -1) > 1) {
274
0
        return;
275
0
    }
276
277
    // Remove ourself from the global list of handles
278
0
    HEAD_LOCK(&_PyRuntime);
279
0
    if (self->node.next != NULL) {
280
0
        llist_remove(&self->node);
281
0
    }
282
0
    HEAD_UNLOCK(&_PyRuntime);
283
284
0
    assert(self->shutdown_node.next == NULL);
285
286
    // It's safe to access state non-atomically:
287
    //   1. This is the destructor; nothing else holds a reference.
288
    //   2. The refcount going to zero is a "synchronizes-with" event; all
289
    //      changes from other threads are visible.
290
0
    if (self->state == THREAD_HANDLE_RUNNING && !detach_thread(self)) {
291
0
        self->state = THREAD_HANDLE_DONE;
292
0
    }
293
294
0
    PyMem_RawFree(self);
295
0
}
296
297
void
298
_PyThread_AfterFork(struct _pythread_runtime_state *state)
299
0
{
300
    // gh-115035: We mark ThreadHandles as not joinable early in the child's
301
    // after-fork handler. We do this before calling any Python code to ensure
302
    // that it happens before any ThreadHandles are deallocated, such as by a
303
    // GC cycle.
304
0
    PyThread_ident_t current = PyThread_get_thread_ident_ex();
305
306
0
    struct llist_node *node;
307
0
    llist_for_each_safe(node, &state->handles) {
308
0
        ThreadHandle *handle = llist_data(node, ThreadHandle, node);
309
0
        if (handle->ident == current) {
310
0
            continue;
311
0
        }
312
313
        // Keep handles for threads that have not been started yet. They are
314
        // safe to start in the child process.
315
0
        if (handle->state == THREAD_HANDLE_NOT_STARTED) {
316
0
            continue;
317
0
        }
318
319
        // Mark all threads as done. Any attempts to join or detach the
320
        // underlying OS thread (if any) could crash. We are the only thread;
321
        // it's safe to set this non-atomically.
322
0
        handle->state = THREAD_HANDLE_DONE;
323
0
        handle->once = (_PyOnceFlag){_Py_ONCE_INITIALIZED};
324
0
        handle->mutex = (PyMutex){_Py_UNLOCKED};
325
0
        _PyEvent_Notify(&handle->thread_is_exiting);
326
0
        llist_remove(node);
327
0
        remove_from_shutdown_handles(handle);
328
0
    }
329
0
}
330
331
// bootstate is used to "bootstrap" new threads. Any arguments needed by
332
// `thread_run()`, which can only take a single argument due to platform
333
// limitations, are contained in bootstate.
334
struct bootstate {
335
    PyThreadState *tstate;
336
    PyObject *func;
337
    PyObject *args;
338
    PyObject *kwargs;
339
    ThreadHandle *handle;
340
    PyEvent handle_ready;
341
};
342
343
static void
344
thread_bootstate_free(struct bootstate *boot, int decref)
345
0
{
346
0
    if (decref) {
347
0
        Py_DECREF(boot->func);
348
0
        Py_DECREF(boot->args);
349
0
        Py_XDECREF(boot->kwargs);
350
0
    }
351
0
    ThreadHandle_decref(boot->handle);
352
0
    PyMem_RawFree(boot);
353
0
}
354
355
static void
356
thread_run(void *boot_raw)
357
0
{
358
0
    struct bootstate *boot = (struct bootstate *) boot_raw;
359
0
    PyThreadState *tstate = boot->tstate;
360
361
    // Wait until the handle is marked as running
362
0
    PyEvent_Wait(&boot->handle_ready);
363
364
    // `handle` needs to be manipulated after bootstate has been freed
365
0
    ThreadHandle *handle = boot->handle;
366
0
    ThreadHandle_incref(handle);
367
368
    // gh-108987: If _thread.start_new_thread() is called before or while
369
    // Python is being finalized, thread_run() can called *after*.
370
    // _PyRuntimeState_SetFinalizing() is called. At this point, all Python
371
    // threads must exit, except of the thread calling Py_Finalize() which
372
    // holds the GIL and must not exit.
373
0
    if (_PyThreadState_MustExit(tstate)) {
374
        // Don't call PyThreadState_Clear() nor _PyThreadState_DeleteCurrent().
375
        // These functions are called on tstate indirectly by Py_Finalize()
376
        // which calls _PyInterpreterState_Clear().
377
        //
378
        // Py_DECREF() cannot be called because the GIL is not held: leak
379
        // references on purpose. Python is being finalized anyway.
380
0
        thread_bootstate_free(boot, 0);
381
0
        goto exit;
382
0
    }
383
384
0
    _PyThreadState_Bind(tstate);
385
0
    PyEval_AcquireThread(tstate);
386
0
    _Py_atomic_add_ssize(&tstate->interp->threads.count, 1);
387
388
0
    PyObject *res = PyObject_Call(boot->func, boot->args, boot->kwargs);
389
0
    if (res == NULL) {
390
0
        if (PyErr_ExceptionMatches(PyExc_SystemExit))
391
            /* SystemExit is ignored silently */
392
0
            PyErr_Clear();
393
0
        else {
394
0
            PyErr_FormatUnraisable(
395
0
                "Exception ignored in thread started by %R", boot->func);
396
0
        }
397
0
    }
398
0
    else {
399
0
        Py_DECREF(res);
400
0
    }
401
402
0
    thread_bootstate_free(boot, 1);
403
404
0
    _Py_atomic_add_ssize(&tstate->interp->threads.count, -1);
405
0
    PyThreadState_Clear(tstate);
406
0
    _PyThreadState_DeleteCurrent(tstate);
407
408
0
exit:
409
    // Don't need to wait for this thread anymore
410
0
    remove_from_shutdown_handles(handle);
411
412
0
    _PyEvent_Notify(&handle->thread_is_exiting);
413
0
    ThreadHandle_decref(handle);
414
415
    // bpo-44434: Don't call explicitly PyThread_exit_thread(). On Linux with
416
    // the glibc, pthread_exit() can abort the whole process if dlopen() fails
417
    // to open the libgcc_s.so library (ex: EMFILE error).
418
0
    return;
419
0
}
420
421
static int
422
force_done(void *arg)
423
0
{
424
0
    ThreadHandle *handle = (ThreadHandle *)arg;
425
0
    assert(get_thread_handle_state(handle) == THREAD_HANDLE_STARTING);
426
0
    _PyEvent_Notify(&handle->thread_is_exiting);
427
0
    set_thread_handle_state(handle, THREAD_HANDLE_DONE);
428
0
    return 0;
429
0
}
430
431
static int
432
ThreadHandle_start(ThreadHandle *self, PyObject *func, PyObject *args,
433
                   PyObject *kwargs, int daemon)
434
0
{
435
    // Mark the handle as starting to prevent any other threads from doing so
436
0
    PyMutex_Lock(&self->mutex);
437
0
    if (self->state != THREAD_HANDLE_NOT_STARTED) {
438
0
        PyMutex_Unlock(&self->mutex);
439
0
        PyErr_SetString(ThreadError, "thread already started");
440
0
        return -1;
441
0
    }
442
0
    self->state = THREAD_HANDLE_STARTING;
443
0
    PyMutex_Unlock(&self->mutex);
444
445
    // Do all the heavy lifting outside of the mutex. All other operations on
446
    // the handle should fail since the handle is in the starting state.
447
448
    // gh-109795: Use PyMem_RawMalloc() instead of PyMem_Malloc(),
449
    // because it should be possible to call thread_bootstate_free()
450
    // without holding the GIL.
451
0
    struct bootstate *boot = PyMem_RawMalloc(sizeof(struct bootstate));
452
0
    if (boot == NULL) {
453
0
        PyErr_NoMemory();
454
0
        goto start_failed;
455
0
    }
456
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
457
0
    uint8_t whence = daemon ? _PyThreadState_WHENCE_THREADING_DAEMON : _PyThreadState_WHENCE_THREADING;
458
0
    boot->tstate = _PyThreadState_New(interp, whence);
459
0
    if (boot->tstate == NULL) {
460
0
        PyMem_RawFree(boot);
461
0
        if (!PyErr_Occurred()) {
462
0
            PyErr_NoMemory();
463
0
        }
464
0
        goto start_failed;
465
0
    }
466
0
    boot->func = Py_NewRef(func);
467
0
    boot->args = Py_NewRef(args);
468
0
    boot->kwargs = Py_XNewRef(kwargs);
469
0
    boot->handle = self;
470
0
    ThreadHandle_incref(self);
471
0
    boot->handle_ready = (PyEvent){0};
472
473
0
    PyThread_ident_t ident;
474
0
    PyThread_handle_t os_handle;
475
0
    if (PyThread_start_joinable_thread(thread_run, boot, &ident, &os_handle)) {
476
0
        PyThreadState_Clear(boot->tstate);
477
0
        PyThreadState_Delete(boot->tstate);
478
0
        thread_bootstate_free(boot, 1);
479
0
        PyErr_SetString(ThreadError, "can't start new thread");
480
0
        goto start_failed;
481
0
    }
482
483
    // Mark the handle running
484
0
    PyMutex_Lock(&self->mutex);
485
0
    assert(self->state == THREAD_HANDLE_STARTING);
486
0
    self->ident = ident;
487
0
    self->has_os_handle = 1;
488
0
    self->os_handle = os_handle;
489
0
    self->state = THREAD_HANDLE_RUNNING;
490
0
    PyMutex_Unlock(&self->mutex);
491
492
    // Unblock the thread
493
0
    _PyEvent_Notify(&boot->handle_ready);
494
495
0
    return 0;
496
497
0
start_failed:
498
0
    _PyOnceFlag_CallOnce(&self->once, force_done, self);
499
0
    return -1;
500
0
}
501
502
static int
503
join_thread(void *arg)
504
0
{
505
0
    ThreadHandle *handle = (ThreadHandle*)arg;
506
0
    assert(get_thread_handle_state(handle) == THREAD_HANDLE_RUNNING);
507
0
    PyThread_handle_t os_handle;
508
0
    if (ThreadHandle_get_os_handle(handle, &os_handle)) {
509
0
        int err = 0;
510
0
        Py_BEGIN_ALLOW_THREADS
511
0
        err = PyThread_join_thread(os_handle);
512
0
        Py_END_ALLOW_THREADS
513
0
        if (err) {
514
0
            PyErr_SetString(ThreadError, "Failed joining thread");
515
0
            return -1;
516
0
        }
517
0
    }
518
0
    set_thread_handle_state(handle, THREAD_HANDLE_DONE);
519
0
    return 0;
520
0
}
521
522
static int
523
check_started(ThreadHandle *self)
524
0
{
525
0
    ThreadHandleState state = get_thread_handle_state(self);
526
0
    if (state < THREAD_HANDLE_RUNNING) {
527
0
        PyErr_SetString(ThreadError, "thread not started");
528
0
        return -1;
529
0
    }
530
0
    return 0;
531
0
}
532
533
static int
534
ThreadHandle_join(ThreadHandle *self, PyTime_t timeout_ns)
535
0
{
536
0
    if (check_started(self) < 0) {
537
0
        return -1;
538
0
    }
539
540
    // We want to perform this check outside of the `_PyOnceFlag` to prevent
541
    // deadlock in the scenario where another thread joins us and we then
542
    // attempt to join ourselves. However, it's not safe to check thread
543
    // identity once the handle's os thread has finished. We may end up reusing
544
    // the identity stored in the handle and erroneously think we are
545
    // attempting to join ourselves.
546
    //
547
    // To work around this, we set `thread_is_exiting` immediately before
548
    // `thread_run` returns.  We can be sure that we are not attempting to join
549
    // ourselves if the handle's thread is about to exit.
550
0
    if (!_PyEvent_IsSet(&self->thread_is_exiting)) {
551
0
        if (ThreadHandle_ident(self) == PyThread_get_thread_ident_ex()) {
552
            // PyThread_join_thread() would deadlock or error out.
553
0
            PyErr_SetString(ThreadError, "Cannot join current thread");
554
0
            return -1;
555
0
        }
556
0
        if (Py_IsFinalizing()) {
557
            // gh-123940: On finalization, other threads are prevented from
558
            // running Python code. They cannot finalize themselves,
559
            // so join() would hang forever (or until timeout).
560
            // We raise instead.
561
0
            PyErr_SetString(PyExc_PythonFinalizationError,
562
0
                            "cannot join thread at interpreter shutdown");
563
0
            return -1;
564
0
        }
565
0
    }
566
567
    // Wait until the deadline for the thread to exit.
568
0
    PyTime_t deadline = timeout_ns != -1 ? _PyDeadline_Init(timeout_ns) : 0;
569
0
    int detach = 1;
570
0
    while (!PyEvent_WaitTimed(&self->thread_is_exiting, timeout_ns, detach)) {
571
0
        if (deadline) {
572
            // _PyDeadline_Get will return a negative value if the deadline has
573
            // been exceeded.
574
0
            timeout_ns = Py_MAX(_PyDeadline_Get(deadline), 0);
575
0
        }
576
577
0
        if (timeout_ns) {
578
            // Interrupted
579
0
            if (Py_MakePendingCalls() < 0) {
580
0
                return -1;
581
0
            }
582
0
        }
583
0
        else {
584
            // Timed out
585
0
            return 0;
586
0
        }
587
0
    }
588
589
0
    if (_PyOnceFlag_CallOnce(&self->once, join_thread, self) == -1) {
590
0
        return -1;
591
0
    }
592
0
    assert(get_thread_handle_state(self) == THREAD_HANDLE_DONE);
593
0
    return 0;
594
0
}
595
596
static int
597
set_done(void *arg)
598
0
{
599
0
    ThreadHandle *handle = (ThreadHandle*)arg;
600
0
    assert(get_thread_handle_state(handle) == THREAD_HANDLE_RUNNING);
601
0
    if (detach_thread(handle) < 0) {
602
0
        PyErr_SetString(ThreadError, "failed detaching handle");
603
0
        return -1;
604
0
    }
605
0
    _PyEvent_Notify(&handle->thread_is_exiting);
606
0
    set_thread_handle_state(handle, THREAD_HANDLE_DONE);
607
0
    return 0;
608
0
}
609
610
static int
611
ThreadHandle_set_done(ThreadHandle *self)
612
0
{
613
0
    if (check_started(self) < 0) {
614
0
        return -1;
615
0
    }
616
617
0
    if (_PyOnceFlag_CallOnce(&self->once, set_done, self) ==
618
0
        -1) {
619
0
        return -1;
620
0
    }
621
0
    assert(get_thread_handle_state(self) == THREAD_HANDLE_DONE);
622
0
    return 0;
623
0
}
624
625
// A wrapper around a ThreadHandle.
626
typedef struct {
627
    PyObject_HEAD
628
629
    ThreadHandle *handle;
630
} PyThreadHandleObject;
631
632
0
#define PyThreadHandleObject_CAST(op)   ((PyThreadHandleObject *)(op))
633
634
static PyThreadHandleObject *
635
PyThreadHandleObject_new(PyTypeObject *type)
636
0
{
637
0
    ThreadHandle *handle = ThreadHandle_new();
638
0
    if (handle == NULL) {
639
0
        return NULL;
640
0
    }
641
642
0
    PyThreadHandleObject *self =
643
0
        (PyThreadHandleObject *)type->tp_alloc(type, 0);
644
0
    if (self == NULL) {
645
0
        ThreadHandle_decref(handle);
646
0
        return NULL;
647
0
    }
648
649
0
    self->handle = handle;
650
651
0
    return self;
652
0
}
653
654
static PyObject *
655
PyThreadHandleObject_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
656
0
{
657
0
    return (PyObject *)PyThreadHandleObject_new(type);
658
0
}
659
660
static void
661
PyThreadHandleObject_dealloc(PyObject *op)
662
0
{
663
0
    PyThreadHandleObject *self = PyThreadHandleObject_CAST(op);
664
0
    PyObject_GC_UnTrack(self);
665
0
    PyTypeObject *tp = Py_TYPE(self);
666
0
    ThreadHandle_decref(self->handle);
667
0
    tp->tp_free(self);
668
0
    Py_DECREF(tp);
669
0
}
670
671
static PyObject *
672
PyThreadHandleObject_repr(PyObject *op)
673
0
{
674
0
    PyThreadHandleObject *self = PyThreadHandleObject_CAST(op);
675
0
    PyThread_ident_t ident = ThreadHandle_ident(self->handle);
676
0
    return PyUnicode_FromFormat("<%s object: ident=%" PY_FORMAT_THREAD_IDENT_T ">",
677
0
                                Py_TYPE(self)->tp_name, ident);
678
0
}
679
680
static PyObject *
681
PyThreadHandleObject_get_ident(PyObject *op, void *Py_UNUSED(closure))
682
0
{
683
0
    PyThreadHandleObject *self = PyThreadHandleObject_CAST(op);
684
0
    return PyLong_FromUnsignedLongLong(ThreadHandle_ident(self->handle));
685
0
}
686
687
static PyObject *
688
PyThreadHandleObject_join(PyObject *op, PyObject *args)
689
0
{
690
0
    PyThreadHandleObject *self = PyThreadHandleObject_CAST(op);
691
692
0
    PyObject *timeout_obj = NULL;
693
0
    if (!PyArg_ParseTuple(args, "|O:join", &timeout_obj)) {
694
0
        return NULL;
695
0
    }
696
697
0
    PyTime_t timeout_ns = -1;
698
0
    if (timeout_obj != NULL && timeout_obj != Py_None) {
699
0
        if (_PyTime_FromSecondsObject(&timeout_ns, timeout_obj,
700
0
                                      _PyTime_ROUND_TIMEOUT) < 0) {
701
0
            return NULL;
702
0
        }
703
0
    }
704
705
0
    if (ThreadHandle_join(self->handle, timeout_ns) < 0) {
706
0
        return NULL;
707
0
    }
708
0
    Py_RETURN_NONE;
709
0
}
710
711
static PyObject *
712
PyThreadHandleObject_is_done(PyObject *op, PyObject *Py_UNUSED(dummy))
713
0
{
714
0
    PyThreadHandleObject *self = PyThreadHandleObject_CAST(op);
715
0
    if (_PyEvent_IsSet(&self->handle->thread_is_exiting)) {
716
0
        if (_PyOnceFlag_CallOnce(&self->handle->once, join_thread, self->handle) == -1) {
717
0
            return NULL;
718
0
        }
719
0
        Py_RETURN_TRUE;
720
0
    }
721
0
    else {
722
0
        Py_RETURN_FALSE;
723
0
    }
724
0
}
725
726
static PyObject *
727
PyThreadHandleObject_set_done(PyObject *op, PyObject *Py_UNUSED(dummy))
728
0
{
729
0
    PyThreadHandleObject *self = PyThreadHandleObject_CAST(op);
730
0
    if (ThreadHandle_set_done(self->handle) < 0) {
731
0
        return NULL;
732
0
    }
733
0
    Py_RETURN_NONE;
734
0
}
735
736
static PyGetSetDef ThreadHandle_getsetlist[] = {
737
    {"ident", PyThreadHandleObject_get_ident, NULL, NULL},
738
    {0},
739
};
740
741
static PyMethodDef ThreadHandle_methods[] = {
742
    {"join", PyThreadHandleObject_join, METH_VARARGS, NULL},
743
    {"_set_done", PyThreadHandleObject_set_done, METH_NOARGS, NULL},
744
    {"is_done", PyThreadHandleObject_is_done, METH_NOARGS, NULL},
745
    {0, 0}
746
};
747
748
static PyType_Slot ThreadHandle_Type_slots[] = {
749
    {Py_tp_dealloc, PyThreadHandleObject_dealloc},
750
    {Py_tp_repr, PyThreadHandleObject_repr},
751
    {Py_tp_getset, ThreadHandle_getsetlist},
752
    {Py_tp_traverse, _PyObject_VisitType},
753
    {Py_tp_methods, ThreadHandle_methods},
754
    {Py_tp_new, PyThreadHandleObject_tp_new},
755
    {0, 0}
756
};
757
758
static PyType_Spec ThreadHandle_Type_spec = {
759
    "_thread._ThreadHandle",
760
    sizeof(PyThreadHandleObject),
761
    0,
762
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC,
763
    ThreadHandle_Type_slots,
764
};
765
766
/* Lock objects */
767
768
static void
769
lock_dealloc(PyObject *self)
770
1.27k
{
771
1.27k
    PyObject_GC_UnTrack(self);
772
1.27k
    PyObject_ClearWeakRefs(self);
773
1.27k
    PyTypeObject *tp = Py_TYPE(self);
774
1.27k
    tp->tp_free(self);
775
1.27k
    Py_DECREF(tp);
776
1.27k
}
777
778
779
static int
780
lock_acquire_parse_timeout(PyObject *timeout_obj, int blocking, PyTime_t *timeout)
781
2.89k
{
782
    // XXX Use PyThread_ParseTimeoutArg().
783
784
2.89k
    const PyTime_t unset_timeout = _PyTime_FromSeconds(-1);
785
2.89k
    *timeout = unset_timeout;
786
787
2.89k
    if (timeout_obj
788
0
        && _PyTime_FromSecondsObject(timeout,
789
0
                                     timeout_obj, _PyTime_ROUND_TIMEOUT) < 0)
790
0
        return -1;
791
792
2.89k
    if (!blocking && *timeout != unset_timeout ) {
793
0
        PyErr_SetString(PyExc_ValueError,
794
0
                        "can't specify a timeout for a non-blocking call");
795
0
        return -1;
796
0
    }
797
2.89k
    if (*timeout < 0 && *timeout != unset_timeout) {
798
0
        PyErr_SetString(PyExc_ValueError,
799
0
                        "timeout value must be a non-negative number");
800
0
        return -1;
801
0
    }
802
2.89k
    if (!blocking)
803
0
        *timeout = 0;
804
2.89k
    else if (*timeout != unset_timeout) {
805
0
        PyTime_t microseconds;
806
807
0
        microseconds = _PyTime_AsMicroseconds(*timeout, _PyTime_ROUND_TIMEOUT);
808
0
        if (microseconds > PY_TIMEOUT_MAX) {
809
0
            PyErr_SetString(PyExc_OverflowError,
810
0
                            "timeout value is too large");
811
0
            return -1;
812
0
        }
813
0
    }
814
2.89k
    return 0;
815
2.89k
}
816
/*[clinic input]
817
_thread.lock.acquire
818
    blocking: bool = True
819
    timeout as timeoutobj: object(py_default="-1") = NULL
820
821
Lock the lock.
822
823
Without argument, this blocks if the lock is already
824
locked (even by the same thread), waiting for another thread to release
825
the lock, and return True once the lock is acquired.
826
With an argument, this will only block if the argument is true,
827
and the return value reflects whether the lock is acquired.
828
The blocking operation is interruptible.
829
[clinic start generated code]*/
830
831
static PyObject *
832
_thread_lock_acquire_impl(lockobject *self, int blocking,
833
                          PyObject *timeoutobj)
834
/*[clinic end generated code: output=569d6b25d508bf6f input=13e999649bc1c798]*/
835
0
{
836
0
    PyTime_t timeout;
837
838
0
    if (lock_acquire_parse_timeout(timeoutobj, blocking, &timeout) < 0) {
839
0
        return NULL;
840
0
    }
841
842
0
    PyLockStatus r = _PyMutex_LockTimed(
843
0
        &self->lock, timeout,
844
0
        _PY_LOCK_PYTHONLOCK | _PY_LOCK_HANDLE_SIGNALS | _PY_LOCK_DETACH);
845
0
    if (r == PY_LOCK_INTR) {
846
0
        assert(PyErr_Occurred());
847
0
        return NULL;
848
0
    }
849
0
    if (r == PY_LOCK_FAILURE && PyErr_Occurred()) {
850
0
        return NULL;
851
0
    }
852
853
0
    return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
854
0
}
855
856
/*[clinic input]
857
_thread.lock.acquire_lock = _thread.lock.acquire
858
859
An obsolete synonym of acquire().
860
[clinic start generated code]*/
861
862
static PyObject *
863
_thread_lock_acquire_lock_impl(lockobject *self, int blocking,
864
                               PyObject *timeoutobj)
865
/*[clinic end generated code: output=ea6c87ea13b56694 input=5e65bd56327ebe85]*/
866
0
{
867
0
    return _thread_lock_acquire_impl(self, blocking, timeoutobj);
868
0
}
869
870
/*[clinic input]
871
_thread.lock.release
872
873
Release the lock.
874
875
Allows another thread that is blocked waiting for
876
the lock to acquire the lock.  The lock must be in the locked state,
877
but it needn't be locked by the same thread that unlocks it.
878
[clinic start generated code]*/
879
880
static PyObject *
881
_thread_lock_release_impl(lockobject *self)
882
/*[clinic end generated code: output=a4ab0d75d6e9fb73 input=dfe48f962dfe99b4]*/
883
0
{
884
    /* Sanity check: the lock must be locked */
885
0
    if (_PyMutex_TryUnlock(&self->lock) < 0) {
886
0
        PyErr_SetString(ThreadError, "release unlocked lock");
887
0
        return NULL;
888
0
    }
889
890
0
    Py_RETURN_NONE;
891
0
}
892
893
/*[clinic input]
894
_thread.lock.release_lock
895
896
An obsolete synonym of release().
897
[clinic start generated code]*/
898
899
static PyObject *
900
_thread_lock_release_lock_impl(lockobject *self)
901
/*[clinic end generated code: output=43025044d51789bb input=74d91374fc601433]*/
902
0
{
903
0
    return _thread_lock_release_impl(self);
904
0
}
905
906
/*[clinic input]
907
_thread.lock.__enter__
908
909
Lock the lock.
910
[clinic start generated code]*/
911
912
static PyObject *
913
_thread_lock___enter___impl(lockobject *self)
914
/*[clinic end generated code: output=f27725de751ae064 input=8f982991608d38e7]*/
915
0
{
916
0
    return _thread_lock_acquire_impl(self, 1, NULL);
917
0
}
918
919
/*[clinic input]
920
_thread.lock.__exit__
921
    exc_type: object
922
    exc_value: object
923
    exc_tb: object
924
    /
925
926
Release the lock.
927
[clinic start generated code]*/
928
929
static PyObject *
930
_thread_lock___exit___impl(lockobject *self, PyObject *exc_type,
931
                           PyObject *exc_value, PyObject *exc_tb)
932
/*[clinic end generated code: output=c9e8eefa69beed07 input=c74d4abe15a6c037]*/
933
0
{
934
0
    return _thread_lock_release_impl(self);
935
0
}
936
937
938
/*[clinic input]
939
_thread.lock.locked
940
941
Return whether the lock is in the locked state.
942
[clinic start generated code]*/
943
944
static PyObject *
945
_thread_lock_locked_impl(lockobject *self)
946
/*[clinic end generated code: output=63bb94e5a9efa382 input=d8e3d64861bbce73]*/
947
0
{
948
0
    return PyBool_FromLong(PyMutex_IsLocked(&self->lock));
949
0
}
950
951
/*[clinic input]
952
_thread.lock.locked_lock
953
954
An obsolete synonym of locked().
955
[clinic start generated code]*/
956
957
static PyObject *
958
_thread_lock_locked_lock_impl(lockobject *self)
959
/*[clinic end generated code: output=f747c8329e905f8e input=500b0c3592f9bf84]*/
960
0
{
961
0
    return _thread_lock_locked_impl(self);
962
0
}
963
964
static PyObject *
965
lock_repr(PyObject *op)
966
0
{
967
0
    lockobject *self = lockobject_CAST(op);
968
0
    return PyUnicode_FromFormat("<%s %s object at %p>",
969
0
        PyMutex_IsLocked(&self->lock) ? "locked" : "unlocked", Py_TYPE(self)->tp_name, self);
970
0
}
971
972
#ifdef HAVE_FORK
973
/*[clinic input]
974
_thread.lock._at_fork_reinit
975
[clinic start generated code]*/
976
977
static PyObject *
978
_thread_lock__at_fork_reinit_impl(lockobject *self)
979
/*[clinic end generated code: output=d8609f2d3bfa1fd5 input=a970cb76e2a0a131]*/
980
0
{
981
0
    _PyMutex_at_fork_reinit(&self->lock);
982
0
    Py_RETURN_NONE;
983
0
}
984
#endif  /* HAVE_FORK */
985
986
/*[clinic input]
987
@classmethod
988
_thread.lock.__new__ as lock_new
989
[clinic start generated code]*/
990
991
static PyObject *
992
lock_new_impl(PyTypeObject *type)
993
/*[clinic end generated code: output=eab660d5a4c05c8a input=260208a4e277d250]*/
994
1.27k
{
995
1.27k
    lockobject *self = (lockobject *)type->tp_alloc(type, 0);
996
1.27k
    if (self == NULL) {
997
0
        return NULL;
998
0
    }
999
1.27k
    self->lock = (PyMutex){0};
1000
1.27k
    return (PyObject *)self;
1001
1.27k
}
1002
1003
1004
static PyMethodDef lock_methods[] = {
1005
    _THREAD_LOCK_ACQUIRE_LOCK_METHODDEF
1006
    _THREAD_LOCK_ACQUIRE_METHODDEF
1007
    _THREAD_LOCK_RELEASE_LOCK_METHODDEF
1008
    _THREAD_LOCK_RELEASE_METHODDEF
1009
    _THREAD_LOCK_LOCKED_LOCK_METHODDEF
1010
    _THREAD_LOCK_LOCKED_METHODDEF
1011
    _THREAD_LOCK___ENTER___METHODDEF
1012
    _THREAD_LOCK___EXIT___METHODDEF
1013
#ifdef HAVE_FORK
1014
    _THREAD_LOCK__AT_FORK_REINIT_METHODDEF
1015
#endif
1016
    {NULL,           NULL}              /* sentinel */
1017
};
1018
1019
PyDoc_STRVAR(lock_doc,
1020
"lock()\n\
1021
--\n\
1022
\n\
1023
A lock object is a synchronization primitive.  To create a lock,\n\
1024
call threading.Lock().  Methods are:\n\
1025
\n\
1026
acquire() -- lock the lock, possibly blocking until it can be obtained\n\
1027
release() -- unlock of the lock\n\
1028
locked() -- test whether the lock is currently locked\n\
1029
\n\
1030
A lock is not owned by the thread that locked it; another thread may\n\
1031
unlock it.  A thread attempting to lock a lock that it has already locked\n\
1032
will block until another thread unlocks it.  Deadlocks may ensue.");
1033
1034
static PyType_Slot lock_type_slots[] = {
1035
    {Py_tp_dealloc, lock_dealloc},
1036
    {Py_tp_repr, lock_repr},
1037
    {Py_tp_doc, (void *)lock_doc},
1038
    {Py_tp_methods, lock_methods},
1039
    {Py_tp_traverse, _PyObject_VisitType},
1040
    {Py_tp_new, lock_new},
1041
    {0, 0}
1042
};
1043
1044
static PyType_Spec lock_type_spec = {
1045
    .name = "_thread.lock",
1046
    .basicsize = sizeof(lockobject),
1047
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1048
              Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_MANAGED_WEAKREF),
1049
    .slots = lock_type_slots,
1050
};
1051
1052
/* Recursive lock objects */
1053
1054
static int
1055
rlock_locked_impl(rlockobject *self)
1056
0
{
1057
0
    return PyMutex_IsLocked(&self->lock.mutex);
1058
0
}
1059
1060
static void
1061
rlock_dealloc(PyObject *self)
1062
1.27k
{
1063
1.27k
    PyObject_GC_UnTrack(self);
1064
1.27k
    PyObject_ClearWeakRefs(self);
1065
1.27k
    PyTypeObject *tp = Py_TYPE(self);
1066
1.27k
    tp->tp_free(self);
1067
1.27k
    Py_DECREF(tp);
1068
1.27k
}
1069
1070
/*[clinic input]
1071
_thread.RLock.acquire
1072
    blocking: bool = True
1073
    timeout as timeoutobj: object(py_default="-1") = NULL
1074
1075
Lock the lock.
1076
1077
`blocking` indicates whether we should wait
1078
for the lock to be available or not.  If `blocking` is False
1079
and another thread holds the lock, the method will return False
1080
immediately.  If `blocking` is True and another thread holds
1081
the lock, the method will wait for the lock to be released,
1082
take it and then return True.
1083
(note: the blocking operation is interruptible.)
1084
1085
In all other cases, the method will return True immediately.
1086
Precisely, if the current thread already holds the lock, its
1087
internal counter is simply incremented. If nobody holds the lock,
1088
the lock is taken and its internal counter initialized to 1.
1089
[clinic start generated code]*/
1090
1091
static PyObject *
1092
_thread_RLock_acquire_impl(rlockobject *self, int blocking,
1093
                           PyObject *timeoutobj)
1094
/*[clinic end generated code: output=73df5af6f67c1513 input=d55a0f5014522a8d]*/
1095
2.89k
{
1096
2.89k
    PyTime_t timeout;
1097
1098
2.89k
    if (lock_acquire_parse_timeout(timeoutobj, blocking, &timeout) < 0) {
1099
0
        return NULL;
1100
0
    }
1101
1102
2.89k
    PyLockStatus r = _PyRecursiveMutex_LockTimed(
1103
2.89k
        &self->lock, timeout,
1104
2.89k
        _PY_LOCK_PYTHONLOCK | _PY_LOCK_HANDLE_SIGNALS | _PY_LOCK_DETACH);
1105
2.89k
    if (r == PY_LOCK_INTR) {
1106
0
        assert(PyErr_Occurred());
1107
0
        return NULL;
1108
0
    }
1109
2.89k
    if (r == PY_LOCK_FAILURE && PyErr_Occurred()) {
1110
0
        return NULL;
1111
0
    }
1112
1113
2.89k
    return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
1114
2.89k
}
1115
1116
/*[clinic input]
1117
_thread.RLock.__enter__
1118
1119
Lock the lock.
1120
[clinic start generated code]*/
1121
1122
static PyObject *
1123
_thread_RLock___enter___impl(rlockobject *self)
1124
/*[clinic end generated code: output=63135898476bf89f input=33be37f459dca390]*/
1125
2.89k
{
1126
2.89k
    return _thread_RLock_acquire_impl(self, 1, NULL);
1127
2.89k
}
1128
1129
/*[clinic input]
1130
_thread.RLock.release
1131
1132
Release the lock.
1133
1134
Allows another thread that is blocked waiting for
1135
the lock to acquire the lock.  The lock must be in the locked state,
1136
and must be locked by the same thread that unlocks it; otherwise a
1137
`RuntimeError` is raised.
1138
1139
Do note that if the lock was acquire()d several times in a row by the
1140
current thread, release() needs to be called as many times for the lock
1141
to be available for other threads.
1142
[clinic start generated code]*/
1143
1144
static PyObject *
1145
_thread_RLock_release_impl(rlockobject *self)
1146
/*[clinic end generated code: output=51f4a013c5fae2c5 input=d425daf1a5782e63]*/
1147
2.89k
{
1148
2.89k
    if (_PyRecursiveMutex_TryUnlock(&self->lock) < 0) {
1149
0
        PyErr_SetString(PyExc_RuntimeError,
1150
0
                        "cannot release un-acquired lock");
1151
0
        return NULL;
1152
0
    }
1153
2.89k
    Py_RETURN_NONE;
1154
2.89k
}
1155
1156
/*[clinic input]
1157
_thread.RLock.__exit__
1158
    exc_type: object
1159
    exc_value: object
1160
    exc_tb: object
1161
    /
1162
1163
Release the lock.
1164
1165
[clinic start generated code]*/
1166
1167
static PyObject *
1168
_thread_RLock___exit___impl(rlockobject *self, PyObject *exc_type,
1169
                            PyObject *exc_value, PyObject *exc_tb)
1170
/*[clinic end generated code: output=79bb44d551aedeb5 input=79accf0778d91002]*/
1171
2.89k
{
1172
2.89k
    return _thread_RLock_release_impl(self);
1173
2.89k
}
1174
1175
/*[clinic input]
1176
_thread.RLock.locked
1177
1178
Return a boolean indicating whether this object is locked right now.
1179
[clinic start generated code]*/
1180
1181
static PyObject *
1182
_thread_RLock_locked_impl(rlockobject *self)
1183
/*[clinic end generated code: output=e9b6060492b3f94e input=8866d9237ba5391b]*/
1184
0
{
1185
0
    int is_locked = rlock_locked_impl(self);
1186
0
    return PyBool_FromLong(is_locked);
1187
0
}
1188
1189
/*[clinic input]
1190
_thread.RLock._acquire_restore
1191
    state: object
1192
    /
1193
1194
For internal use by `threading.Condition`.
1195
[clinic start generated code]*/
1196
1197
static PyObject *
1198
_thread_RLock__acquire_restore_impl(rlockobject *self, PyObject *state)
1199
/*[clinic end generated code: output=beb8f2713a35e775 input=c8f2094fde059447]*/
1200
0
{
1201
0
    PyThread_ident_t owner;
1202
0
    Py_ssize_t count;
1203
1204
0
    if (!PyArg_Parse(state, "(n" Py_PARSE_THREAD_IDENT_T "):_acquire_restore",
1205
0
            &count, &owner))
1206
0
        return NULL;
1207
1208
0
    _PyRecursiveMutex_Lock(&self->lock);
1209
0
    _Py_atomic_store_ullong_relaxed(&self->lock.thread, owner);
1210
0
    self->lock.level = (size_t)count - 1;
1211
0
    Py_RETURN_NONE;
1212
0
}
1213
1214
1215
/*[clinic input]
1216
_thread.RLock._release_save
1217
1218
For internal use by `threading.Condition`.
1219
[clinic start generated code]*/
1220
1221
static PyObject *
1222
_thread_RLock__release_save_impl(rlockobject *self)
1223
/*[clinic end generated code: output=d2916487315bea93 input=809d227cfc4a112c]*/
1224
0
{
1225
0
    if (!_PyRecursiveMutex_IsLockedByCurrentThread(&self->lock)) {
1226
0
        PyErr_SetString(PyExc_RuntimeError,
1227
0
                        "cannot release un-acquired lock");
1228
0
        return NULL;
1229
0
    }
1230
1231
0
    PyThread_ident_t owner = self->lock.thread;
1232
0
    Py_ssize_t count = self->lock.level + 1;
1233
0
    self->lock.level = 0;  // ensure the unlock releases the lock
1234
0
    _PyRecursiveMutex_Unlock(&self->lock);
1235
0
    return Py_BuildValue("n" Py_PARSE_THREAD_IDENT_T, count, owner);
1236
0
}
1237
1238
1239
/*[clinic input]
1240
_thread.RLock._recursion_count
1241
1242
For internal use by reentrancy checks.
1243
[clinic start generated code]*/
1244
1245
static PyObject *
1246
_thread_RLock__recursion_count_impl(rlockobject *self)
1247
/*[clinic end generated code: output=7993fb9695ef2c4d input=7fd1834cd7a4b044]*/
1248
0
{
1249
0
    if (_PyRecursiveMutex_IsLockedByCurrentThread(&self->lock)) {
1250
0
        return PyLong_FromSize_t(self->lock.level + 1);
1251
0
    }
1252
0
    return PyLong_FromLong(0);
1253
0
}
1254
1255
1256
/*[clinic input]
1257
_thread.RLock._is_owned
1258
1259
For internal use by `threading.Condition`.
1260
[clinic start generated code]*/
1261
1262
static PyObject *
1263
_thread_RLock__is_owned_impl(rlockobject *self)
1264
/*[clinic end generated code: output=bf14268a3cabbe07 input=fba6535538deb858]*/
1265
0
{
1266
0
    long owned = _PyRecursiveMutex_IsLockedByCurrentThread(&self->lock);
1267
0
    return PyBool_FromLong(owned);
1268
0
}
1269
1270
/*[clinic input]
1271
@classmethod
1272
_thread.RLock.__new__ as rlock_new
1273
[clinic start generated code]*/
1274
1275
static PyObject *
1276
rlock_new_impl(PyTypeObject *type)
1277
/*[clinic end generated code: output=bb4fb1edf6818df5 input=013591361bf1ac6e]*/
1278
1.27k
{
1279
1.27k
    rlockobject *self = (rlockobject *) type->tp_alloc(type, 0);
1280
1.27k
    if (self == NULL) {
1281
0
        return NULL;
1282
0
    }
1283
1.27k
    self->lock = (_PyRecursiveMutex){0};
1284
1.27k
    return (PyObject *) self;
1285
1.27k
}
1286
1287
static PyObject *
1288
rlock_repr(PyObject *op)
1289
0
{
1290
0
    rlockobject *self = rlockobject_CAST(op);
1291
0
    PyThread_ident_t owner = self->lock.thread;
1292
0
    int locked = rlock_locked_impl(self);
1293
0
    size_t count;
1294
0
    if (locked) {
1295
0
        count = self->lock.level + 1;
1296
0
    }
1297
0
    else {
1298
0
        count = 0;
1299
0
    }
1300
0
    return PyUnicode_FromFormat(
1301
0
        "<%s %s object owner=%" PY_FORMAT_THREAD_IDENT_T " count=%zu at %p>",
1302
0
        locked ? "locked" : "unlocked",
1303
0
        Py_TYPE(self)->tp_name, owner,
1304
0
        count, self);
1305
0
}
1306
1307
1308
#ifdef HAVE_FORK
1309
/*[clinic input]
1310
_thread.RLock._at_fork_reinit
1311
[clinic start generated code]*/
1312
1313
static PyObject *
1314
_thread_RLock__at_fork_reinit_impl(rlockobject *self)
1315
/*[clinic end generated code: output=d77a4ce40351817c input=a3b625b026a8df4f]*/
1316
0
{
1317
0
    self->lock = (_PyRecursiveMutex){0};
1318
0
    Py_RETURN_NONE;
1319
0
}
1320
#endif  /* HAVE_FORK */
1321
1322
1323
static PyMethodDef rlock_methods[] = {
1324
    _THREAD_RLOCK_ACQUIRE_METHODDEF
1325
    _THREAD_RLOCK_RELEASE_METHODDEF
1326
    _THREAD_RLOCK_LOCKED_METHODDEF
1327
    _THREAD_RLOCK__IS_OWNED_METHODDEF
1328
    _THREAD_RLOCK__ACQUIRE_RESTORE_METHODDEF
1329
    _THREAD_RLOCK__RELEASE_SAVE_METHODDEF
1330
    _THREAD_RLOCK__RECURSION_COUNT_METHODDEF
1331
    _THREAD_RLOCK___ENTER___METHODDEF
1332
    _THREAD_RLOCK___EXIT___METHODDEF
1333
#ifdef HAVE_FORK
1334
    _THREAD_RLOCK__AT_FORK_REINIT_METHODDEF
1335
#endif
1336
    {NULL,           NULL}              /* sentinel */
1337
};
1338
1339
1340
static PyType_Slot rlock_type_slots[] = {
1341
    {Py_tp_dealloc, rlock_dealloc},
1342
    {Py_tp_repr, rlock_repr},
1343
    {Py_tp_methods, rlock_methods},
1344
    {Py_tp_alloc, PyType_GenericAlloc},
1345
    {Py_tp_new, rlock_new},
1346
    {Py_tp_traverse, _PyObject_VisitType},
1347
    {0, 0},
1348
};
1349
1350
static PyType_Spec rlock_type_spec = {
1351
    .name = "_thread.RLock",
1352
    .basicsize = sizeof(rlockobject),
1353
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
1354
              Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_MANAGED_WEAKREF),
1355
    .slots = rlock_type_slots,
1356
};
1357
1358
/* Thread-local objects */
1359
1360
/* Quick overview:
1361
1362
   We need to be able to reclaim reference cycles as soon as possible
1363
   (both when a thread is being terminated, or a thread-local object
1364
    becomes unreachable from user data).  Constraints:
1365
   - it must not be possible for thread-state dicts to be involved in
1366
     reference cycles (otherwise the cyclic GC will refuse to consider
1367
     objects referenced from a reachable thread-state dict, even though
1368
     local_dealloc would clear them)
1369
   - the death of a thread-state dict must still imply destruction of the
1370
     corresponding local dicts in all thread-local objects.
1371
1372
   Our implementation uses small "localdummy" objects in order to break
1373
   the reference chain. These trivial objects are hashable (using the
1374
   default scheme of identity hashing) and weakrefable.
1375
1376
   Each thread-state holds two separate localdummy objects:
1377
1378
   - `threading_local_key` is used as a key to retrieve the locals dictionary
1379
     for the thread in any `threading.local` object.
1380
   - `threading_local_sentinel` is used to signal when a thread is being
1381
     destroyed. Consequently, the associated thread-state must hold the only
1382
     reference.
1383
1384
   Each `threading.local` object contains a dict mapping localdummy keys to
1385
   locals dicts and a set containing weak references to localdummy
1386
   sentinels. Each sentinel weak reference has a callback that removes itself
1387
   and the locals dict for the key from the `threading.local` object when
1388
   called.
1389
1390
   Therefore:
1391
   - The thread-state only holds strong references to localdummy objects, which
1392
     cannot participate in cycles.
1393
   - Only outside objects (application- or library-level) hold strong
1394
     references to the thread-local objects.
1395
   - As soon as thread-state's sentinel dummy is destroyed the callbacks for
1396
     all weakrefs attached to the sentinel are called, and destroy the
1397
     corresponding local dicts from thread-local objects.
1398
   - As soon as a thread-local object is destroyed, its local dicts are
1399
     destroyed.
1400
   - The GC can do its work correctly when a thread-local object is dangling,
1401
     without any interference from the thread-state dicts.
1402
1403
   This dual key arrangement is necessary to ensure that `threading.local`
1404
   values can be retrieved from finalizers. If we were to only keep a mapping
1405
   of localdummy weakrefs to locals dicts it's possible that the weakrefs would
1406
   be cleared before finalizers were called (GC currently clears weakrefs that
1407
   are garbage before invoking finalizers), causing lookups in finalizers to
1408
   fail.
1409
*/
1410
1411
typedef struct {
1412
    PyObject_HEAD
1413
    PyObject *weakreflist;      /* List of weak references to self */
1414
} localdummyobject;
1415
1416
0
#define localdummyobject_CAST(op)   ((localdummyobject *)(op))
1417
1418
static void
1419
localdummy_dealloc(PyObject *op)
1420
0
{
1421
0
    localdummyobject *self = localdummyobject_CAST(op);
1422
0
    FT_CLEAR_WEAKREFS(op, self->weakreflist);
1423
0
    PyTypeObject *tp = Py_TYPE(self);
1424
0
    tp->tp_free(self);
1425
0
    Py_DECREF(tp);
1426
0
}
1427
1428
static PyMemberDef local_dummy_type_members[] = {
1429
    {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(localdummyobject, weakreflist), Py_READONLY},
1430
    {NULL},
1431
};
1432
1433
static PyType_Slot local_dummy_type_slots[] = {
1434
    {Py_tp_dealloc, localdummy_dealloc},
1435
    {Py_tp_doc, "Thread-local dummy"},
1436
    {Py_tp_members, local_dummy_type_members},
1437
    {0, 0}
1438
};
1439
1440
static PyType_Spec local_dummy_type_spec = {
1441
    .name = "_thread._localdummy",
1442
    .basicsize = sizeof(localdummyobject),
1443
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION |
1444
              Py_TPFLAGS_IMMUTABLETYPE),
1445
    .slots = local_dummy_type_slots,
1446
};
1447
1448
1449
typedef struct {
1450
    PyObject_HEAD
1451
    PyObject *args;
1452
    PyObject *kw;
1453
    PyObject *weakreflist;      /* List of weak references to self */
1454
    /* A {localdummy -> localdict} dict */
1455
    PyObject *localdicts;
1456
    /* A set of weakrefs to thread sentinels localdummies*/
1457
    PyObject *thread_watchdogs;
1458
} localobject;
1459
1460
0
#define localobject_CAST(op)    ((localobject *)(op))
1461
1462
/* Forward declaration */
1463
static int create_localsdict(localobject *self, thread_module_state *state,
1464
                             PyObject **localsdict, PyObject **sentinel_wr);
1465
static PyObject *clear_locals(PyObject *meth_self, PyObject *dummyweakref);
1466
1467
/* Create a weakref to the sentinel localdummy for the current thread */
1468
static PyObject *
1469
create_sentinel_wr(localobject *self)
1470
0
{
1471
0
    static PyMethodDef wr_callback_def = {
1472
0
        "clear_locals", clear_locals, METH_O
1473
0
    };
1474
1475
0
    PyThreadState *tstate = PyThreadState_Get();
1476
1477
    /* We use a weak reference to self in the callback closure
1478
       in order to avoid spurious reference cycles */
1479
0
    PyObject *self_wr = PyWeakref_NewRef((PyObject *) self, NULL);
1480
0
    if (self_wr == NULL) {
1481
0
        return NULL;
1482
0
    }
1483
1484
0
    PyObject *args = _PyTuple_FromPairSteal(self_wr,
1485
0
                                            Py_NewRef(tstate->threading_local_key));
1486
0
    if (args == NULL) {
1487
0
        return NULL;
1488
0
    }
1489
1490
0
    PyObject *cb = PyCFunction_New(&wr_callback_def, args);
1491
0
    Py_DECREF(args);
1492
0
    if (cb == NULL) {
1493
0
        return NULL;
1494
0
    }
1495
1496
0
    PyObject *wr = PyWeakref_NewRef(tstate->threading_local_sentinel, cb);
1497
0
    Py_DECREF(cb);
1498
1499
0
    return wr;
1500
0
}
1501
1502
static PyObject *
1503
local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
1504
0
{
1505
0
    if (type->tp_init == PyBaseObject_Type.tp_init) {
1506
0
        int rc = 0;
1507
0
        if (args != NULL)
1508
0
            rc = PyObject_IsTrue(args);
1509
0
        if (rc == 0 && kw != NULL)
1510
0
            rc = PyObject_IsTrue(kw);
1511
0
        if (rc != 0) {
1512
0
            if (rc > 0) {
1513
0
                PyErr_SetString(PyExc_TypeError,
1514
0
                          "Initialization arguments are not supported");
1515
0
            }
1516
0
            return NULL;
1517
0
        }
1518
0
    }
1519
1520
0
    PyObject *module = PyType_GetModuleByDef(type, &thread_module);
1521
0
    assert(module != NULL);
1522
0
    thread_module_state *state = get_thread_state(module);
1523
1524
0
    localobject *self = (localobject *)type->tp_alloc(type, 0);
1525
0
    if (self == NULL) {
1526
0
        return NULL;
1527
0
    }
1528
1529
    // gh-128691: Use deferred reference counting for thread-locals to avoid
1530
    // contention on the shared object.
1531
0
    _PyObject_SetDeferredRefcount((PyObject *)self);
1532
1533
0
    self->args = Py_XNewRef(args);
1534
0
    self->kw = Py_XNewRef(kw);
1535
1536
0
    self->localdicts = PyDict_New();
1537
0
    if (self->localdicts == NULL) {
1538
0
        goto err;
1539
0
    }
1540
1541
0
    self->thread_watchdogs = PySet_New(NULL);
1542
0
    if (self->thread_watchdogs == NULL) {
1543
0
        goto err;
1544
0
    }
1545
1546
0
    PyObject *localsdict = NULL;
1547
0
    PyObject *sentinel_wr = NULL;
1548
0
    if (create_localsdict(self, state, &localsdict, &sentinel_wr) < 0) {
1549
0
        goto err;
1550
0
    }
1551
0
    Py_DECREF(localsdict);
1552
0
    Py_DECREF(sentinel_wr);
1553
1554
0
    return (PyObject *)self;
1555
1556
0
  err:
1557
0
    Py_DECREF(self);
1558
0
    return NULL;
1559
0
}
1560
1561
static int
1562
local_traverse(PyObject *op, visitproc visit, void *arg)
1563
0
{
1564
0
    localobject *self = localobject_CAST(op);
1565
0
    Py_VISIT(Py_TYPE(self));
1566
0
    Py_VISIT(self->args);
1567
0
    Py_VISIT(self->kw);
1568
0
    Py_VISIT(self->localdicts);
1569
0
    Py_VISIT(self->thread_watchdogs);
1570
0
    return 0;
1571
0
}
1572
1573
static int
1574
local_clear(PyObject *op)
1575
0
{
1576
0
    localobject *self = localobject_CAST(op);
1577
0
    Py_CLEAR(self->args);
1578
0
    Py_CLEAR(self->kw);
1579
0
    Py_CLEAR(self->localdicts);
1580
0
    Py_CLEAR(self->thread_watchdogs);
1581
0
    return 0;
1582
0
}
1583
1584
static void
1585
local_dealloc(PyObject *op)
1586
0
{
1587
0
    localobject *self = localobject_CAST(op);
1588
    /* Weakrefs must be invalidated right now, otherwise they can be used
1589
       from code called below, which is very dangerous since Py_REFCNT(self) == 0 */
1590
0
    if (self->weakreflist != NULL) {
1591
0
        PyObject_ClearWeakRefs(op);
1592
0
    }
1593
0
    PyObject_GC_UnTrack(self);
1594
0
    (void)local_clear(op);
1595
0
    PyTypeObject *tp = Py_TYPE(self);
1596
0
    tp->tp_free(self);
1597
0
    Py_DECREF(tp);
1598
0
}
1599
1600
/* Create the TLS key and sentinel if they don't exist */
1601
static int
1602
create_localdummies(thread_module_state *state)
1603
0
{
1604
0
    PyThreadState *tstate = _PyThreadState_GET();
1605
1606
0
    if (tstate->threading_local_key != NULL) {
1607
0
        return 0;
1608
0
    }
1609
1610
0
    PyTypeObject *ld_type = state->local_dummy_type;
1611
0
    tstate->threading_local_key = ld_type->tp_alloc(ld_type, 0);
1612
0
    if (tstate->threading_local_key == NULL) {
1613
0
        return -1;
1614
0
    }
1615
1616
0
    tstate->threading_local_sentinel = ld_type->tp_alloc(ld_type, 0);
1617
0
    if (tstate->threading_local_sentinel == NULL) {
1618
0
        Py_CLEAR(tstate->threading_local_key);
1619
0
        return -1;
1620
0
    }
1621
1622
0
    return 0;
1623
0
}
1624
1625
/* Insert a localsdict and sentinel weakref for the current thread, placing
1626
   strong references in localsdict and sentinel_wr, respectively.
1627
*/
1628
static int
1629
create_localsdict(localobject *self, thread_module_state *state,
1630
                  PyObject **localsdict, PyObject **sentinel_wr)
1631
0
{
1632
0
    PyThreadState *tstate = _PyThreadState_GET();
1633
0
    PyObject *ldict = NULL;
1634
0
    PyObject *wr = NULL;
1635
1636
0
    if (create_localdummies(state) < 0) {
1637
0
        goto err;
1638
0
    }
1639
1640
    /* Create and insert the locals dict and sentinel weakref */
1641
0
    ldict = PyDict_New();
1642
0
    if (ldict == NULL) {
1643
0
        goto err;
1644
0
    }
1645
1646
0
    if (PyDict_SetItem(self->localdicts, tstate->threading_local_key,
1647
0
                       ldict) < 0)
1648
0
    {
1649
0
        goto err;
1650
0
    }
1651
1652
0
    wr = create_sentinel_wr(self);
1653
0
    if (wr == NULL) {
1654
0
        PyObject *exc = PyErr_GetRaisedException();
1655
0
        if (PyDict_DelItem(self->localdicts,
1656
0
                           tstate->threading_local_key) < 0)
1657
0
        {
1658
0
            PyErr_FormatUnraisable("Exception ignored while deleting "
1659
0
                                   "thread local of %R", self);
1660
0
        }
1661
0
        PyErr_SetRaisedException(exc);
1662
0
        goto err;
1663
0
    }
1664
1665
0
    if (PySet_Add(self->thread_watchdogs, wr) < 0) {
1666
0
        PyObject *exc = PyErr_GetRaisedException();
1667
0
        if (PyDict_DelItem(self->localdicts,
1668
0
                           tstate->threading_local_key) < 0)
1669
0
        {
1670
0
            PyErr_FormatUnraisable("Exception ignored while deleting "
1671
0
                                   "thread local of %R", self);
1672
0
        }
1673
0
        PyErr_SetRaisedException(exc);
1674
0
        goto err;
1675
0
    }
1676
1677
0
    *localsdict = ldict;
1678
0
    *sentinel_wr = wr;
1679
0
    return 0;
1680
1681
0
err:
1682
0
    Py_XDECREF(ldict);
1683
0
    Py_XDECREF(wr);
1684
0
    return -1;
1685
0
}
1686
1687
/* Return a strong reference to the locals dict for the current thread,
1688
   creating it if necessary.
1689
*/
1690
static PyObject *
1691
_ldict(localobject *self, thread_module_state *state)
1692
0
{
1693
0
    if (create_localdummies(state) < 0) {
1694
0
        return NULL;
1695
0
    }
1696
1697
    /* Check if a localsdict already exists */
1698
0
    PyObject *ldict;
1699
0
    PyThreadState *tstate = _PyThreadState_GET();
1700
0
    if (PyDict_GetItemRef(self->localdicts, tstate->threading_local_key,
1701
0
                          &ldict) < 0) {
1702
0
        return NULL;
1703
0
    }
1704
0
    if (ldict != NULL) {
1705
0
        return ldict;
1706
0
    }
1707
1708
    /* threading.local hasn't been instantiated for this thread */
1709
0
    PyObject *wr;
1710
0
    if (create_localsdict(self, state, &ldict, &wr) < 0) {
1711
0
        return NULL;
1712
0
    }
1713
1714
    /* run __init__ if we're a subtype of `threading.local` */
1715
0
    if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init &&
1716
0
        Py_TYPE(self)->tp_init((PyObject *)self, self->args, self->kw) < 0) {
1717
        /* we need to get rid of ldict from thread so
1718
           we create a new one the next time we do an attr
1719
           access */
1720
0
        PyObject *exc = PyErr_GetRaisedException();
1721
0
        if (PyDict_DelItem(self->localdicts,
1722
0
                           tstate->threading_local_key) < 0)
1723
0
        {
1724
0
            PyErr_FormatUnraisable("Exception ignored while deleting "
1725
0
                                   "thread local of %R", self);
1726
0
            assert(!PyErr_Occurred());
1727
0
        }
1728
0
        if (PySet_Discard(self->thread_watchdogs, wr) < 0) {
1729
0
            PyErr_FormatUnraisable("Exception ignored while discarding "
1730
0
                                   "thread watchdog of %R", self);
1731
0
        }
1732
0
        PyErr_SetRaisedException(exc);
1733
0
        Py_DECREF(ldict);
1734
0
        Py_DECREF(wr);
1735
0
        return NULL;
1736
0
    }
1737
0
    Py_DECREF(wr);
1738
1739
0
    return ldict;
1740
0
}
1741
1742
static int
1743
local_setattro(PyObject *op, PyObject *name, PyObject *v)
1744
0
{
1745
0
    localobject *self = localobject_CAST(op);
1746
0
    PyObject *module = PyType_GetModuleByDef(Py_TYPE(self), &thread_module);
1747
0
    assert(module != NULL);
1748
0
    thread_module_state *state = get_thread_state(module);
1749
1750
0
    PyObject *ldict = _ldict(self, state);
1751
0
    if (ldict == NULL) {
1752
0
        goto err;
1753
0
    }
1754
1755
0
    int r = PyObject_RichCompareBool(name, &_Py_ID(__dict__), Py_EQ);
1756
0
    if (r == -1) {
1757
0
        goto err;
1758
0
    }
1759
0
    if (r == 1) {
1760
0
        PyErr_Format(PyExc_AttributeError,
1761
0
                     "'%.100s' object attribute %R is read-only",
1762
0
                     Py_TYPE(self)->tp_name, name);
1763
0
        goto err;
1764
0
    }
1765
1766
0
    int st = _PyObject_GenericSetAttrWithDict(op, name, v, ldict);
1767
0
    Py_DECREF(ldict);
1768
0
    return st;
1769
1770
0
err:
1771
0
    Py_XDECREF(ldict);
1772
0
    return -1;
1773
0
}
1774
1775
static PyObject *local_getattro(PyObject *, PyObject *);
1776
1777
static PyMemberDef local_type_members[] = {
1778
    {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(localobject, weakreflist), Py_READONLY},
1779
    {NULL},
1780
};
1781
1782
static PyType_Slot local_type_slots[] = {
1783
    {Py_tp_dealloc, local_dealloc},
1784
    {Py_tp_getattro, local_getattro},
1785
    {Py_tp_setattro, local_setattro},
1786
    {Py_tp_doc, "_local()\n--\n\nThread-local data"},
1787
    {Py_tp_traverse, local_traverse},
1788
    {Py_tp_clear, local_clear},
1789
    {Py_tp_new, local_new},
1790
    {Py_tp_members, local_type_members},
1791
    {0, 0}
1792
};
1793
1794
static PyType_Spec local_type_spec = {
1795
    .name = "_thread._local",
1796
    .basicsize = sizeof(localobject),
1797
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
1798
              Py_TPFLAGS_IMMUTABLETYPE),
1799
    .slots = local_type_slots,
1800
};
1801
1802
static PyObject *
1803
local_getattro(PyObject *op, PyObject *name)
1804
0
{
1805
0
    localobject *self = localobject_CAST(op);
1806
0
    PyObject *module = PyType_GetModuleByDef(Py_TYPE(self), &thread_module);
1807
0
    assert(module != NULL);
1808
0
    thread_module_state *state = get_thread_state(module);
1809
1810
0
    PyObject *ldict = _ldict(self, state);
1811
0
    if (ldict == NULL)
1812
0
        return NULL;
1813
1814
0
    int r = PyObject_RichCompareBool(name, &_Py_ID(__dict__), Py_EQ);
1815
0
    if (r == 1) {
1816
0
        return ldict;
1817
0
    }
1818
0
    if (r == -1) {
1819
0
        Py_DECREF(ldict);
1820
0
        return NULL;
1821
0
    }
1822
1823
0
    if (!Py_IS_TYPE(self, state->local_type)) {
1824
        /* use generic lookup for subtypes */
1825
0
        PyObject *res = _PyObject_GenericGetAttrWithDict(op, name, ldict, 0);
1826
0
        Py_DECREF(ldict);
1827
0
        return res;
1828
0
    }
1829
1830
    /* Optimization: just look in dict ourselves */
1831
0
    PyObject *value;
1832
0
    if (PyDict_GetItemRef(ldict, name, &value) != 0) {
1833
        // found or error
1834
0
        Py_DECREF(ldict);
1835
0
        return value;
1836
0
    }
1837
1838
    /* Fall back on generic to get __class__ and __dict__ */
1839
0
    PyObject *res = _PyObject_GenericGetAttrWithDict(op, name, ldict, 0);
1840
0
    Py_DECREF(ldict);
1841
0
    return res;
1842
0
}
1843
1844
/* Called when a dummy is destroyed, indicating that the owning thread is being
1845
 * cleared. */
1846
static PyObject *
1847
clear_locals(PyObject *locals_and_key, PyObject *dummyweakref)
1848
0
{
1849
0
    PyObject *localweakref = PyTuple_GetItem(locals_and_key, 0);
1850
0
    localobject *self = localobject_CAST(_PyWeakref_GET_REF(localweakref));
1851
0
    if (self == NULL) {
1852
0
        Py_RETURN_NONE;
1853
0
    }
1854
1855
    /* If the thread-local object is still alive and not being cleared,
1856
       remove the corresponding local dict */
1857
0
    if (self->localdicts != NULL) {
1858
0
        PyObject *key = PyTuple_GetItem(locals_and_key, 1);
1859
0
        if (PyDict_Pop(self->localdicts, key, NULL) < 0) {
1860
0
            PyErr_FormatUnraisable("Exception ignored while clearing "
1861
0
                                   "thread local %R", (PyObject *)self);
1862
0
        }
1863
0
    }
1864
0
    if (self->thread_watchdogs != NULL) {
1865
0
        if (PySet_Discard(self->thread_watchdogs, dummyweakref) < 0) {
1866
0
            PyErr_FormatUnraisable("Exception ignored while clearing "
1867
0
                                   "thread local %R", (PyObject *)self);
1868
0
        }
1869
0
    }
1870
1871
0
    Py_DECREF(self);
1872
0
    Py_RETURN_NONE;
1873
0
}
1874
1875
/* Module functions */
1876
1877
static PyObject *
1878
thread_daemon_threads_allowed(PyObject *module, PyObject *Py_UNUSED(ignored))
1879
0
{
1880
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
1881
0
    if (interp->feature_flags & Py_RTFLAGS_DAEMON_THREADS) {
1882
0
        Py_RETURN_TRUE;
1883
0
    }
1884
0
    else {
1885
0
        Py_RETURN_FALSE;
1886
0
    }
1887
0
}
1888
1889
PyDoc_STRVAR(daemon_threads_allowed_doc,
1890
"daemon_threads_allowed($module, /)\n\
1891
--\n\
1892
\n\
1893
Return True if daemon threads are allowed in the current interpreter,\n\
1894
and False otherwise.\n");
1895
1896
static int
1897
do_start_new_thread(thread_module_state *state, PyObject *func, PyObject *args,
1898
                    PyObject *kwargs, ThreadHandle *handle, int daemon)
1899
0
{
1900
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
1901
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_THREADS)) {
1902
0
        PyErr_SetString(PyExc_RuntimeError,
1903
0
                        "thread is not supported for isolated subinterpreters");
1904
0
        return -1;
1905
0
    }
1906
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
1907
0
        PyErr_SetString(PyExc_PythonFinalizationError,
1908
0
                        "can't create new thread at interpreter shutdown");
1909
0
        return -1;
1910
0
    }
1911
1912
0
    if (!daemon) {
1913
        // Add the handle before starting the thread to avoid adding a handle
1914
        // to a thread that has already finished (i.e. if the thread finishes
1915
        // before the call to `ThreadHandle_start()` below returns).
1916
0
        add_to_shutdown_handles(state, handle);
1917
0
    }
1918
1919
0
    if (ThreadHandle_start(handle, func, args, kwargs, daemon) < 0) {
1920
0
        if (!daemon) {
1921
0
            remove_from_shutdown_handles(handle);
1922
0
        }
1923
0
        return -1;
1924
0
    }
1925
1926
0
    return 0;
1927
0
}
1928
1929
static PyObject *
1930
thread_PyThread_start_new_thread(PyObject *module, PyObject *fargs)
1931
0
{
1932
0
    PyObject *func, *args, *kwargs = NULL;
1933
0
    thread_module_state *state = get_thread_state(module);
1934
1935
0
    if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3,
1936
0
                           &func, &args, &kwargs))
1937
0
        return NULL;
1938
0
    if (!PyCallable_Check(func)) {
1939
0
        PyErr_SetString(PyExc_TypeError,
1940
0
                        "first arg must be callable");
1941
0
        return NULL;
1942
0
    }
1943
0
    if (!PyTuple_Check(args)) {
1944
0
        PyErr_SetString(PyExc_TypeError,
1945
0
                        "2nd arg must be a tuple");
1946
0
        return NULL;
1947
0
    }
1948
0
    if (kwargs != NULL && !PyDict_Check(kwargs)) {
1949
0
        PyErr_SetString(PyExc_TypeError,
1950
0
                        "optional 3rd arg must be a dictionary");
1951
0
        return NULL;
1952
0
    }
1953
1954
0
    if (PySys_Audit("_thread.start_new_thread", "OOO",
1955
0
                    func, args, kwargs ? kwargs : Py_None) < 0) {
1956
0
        return NULL;
1957
0
    }
1958
1959
0
    ThreadHandle *handle = ThreadHandle_new();
1960
0
    if (handle == NULL) {
1961
0
        return NULL;
1962
0
    }
1963
1964
0
    int st =
1965
0
        do_start_new_thread(state, func, args, kwargs, handle, /*daemon=*/1);
1966
0
    if (st < 0) {
1967
0
        ThreadHandle_decref(handle);
1968
0
        return NULL;
1969
0
    }
1970
0
    PyThread_ident_t ident = ThreadHandle_ident(handle);
1971
0
    ThreadHandle_decref(handle);
1972
0
    return PyLong_FromUnsignedLongLong(ident);
1973
0
}
1974
1975
PyDoc_STRVAR(start_new_thread_doc,
1976
"start_new_thread($module, function, args, kwargs={}, /)\n\
1977
--\n\
1978
\n\
1979
Start a new thread and return its identifier.\n\
1980
\n\
1981
The thread will call the function with positional arguments from the\n\
1982
tuple args and keyword arguments taken from the optional dictionary\n\
1983
kwargs.  The thread exits when the function returns; the return value\n\
1984
is ignored.  The thread will also exit when the function raises an\n\
1985
unhandled exception; a stack trace will be printed unless the exception\n\
1986
is SystemExit.");
1987
1988
PyDoc_STRVAR(start_new_doc,
1989
"start_new($module, function, args, kwargs={}, /)\n\
1990
--\n\
1991
\n\
1992
An obsolete synonym of start_new_thread().");
1993
1994
static PyObject *
1995
thread_PyThread_start_joinable_thread(PyObject *module, PyObject *fargs,
1996
                                      PyObject *fkwargs)
1997
0
{
1998
0
    static char *keywords[] = {"function", "handle", "daemon", NULL};
1999
0
    PyObject *func = NULL;
2000
0
    int daemon = 1;
2001
0
    thread_module_state *state = get_thread_state(module);
2002
0
    PyObject *hobj = NULL;
2003
0
    if (!PyArg_ParseTupleAndKeywords(fargs, fkwargs,
2004
0
                                     "O|Op:start_joinable_thread", keywords,
2005
0
                                     &func, &hobj, &daemon)) {
2006
0
        return NULL;
2007
0
    }
2008
2009
0
    if (!PyCallable_Check(func)) {
2010
0
        PyErr_SetString(PyExc_TypeError,
2011
0
                        "thread function must be callable");
2012
0
        return NULL;
2013
0
    }
2014
2015
0
    if (hobj == NULL) {
2016
0
        hobj = Py_None;
2017
0
    }
2018
0
    else if (hobj != Py_None && !Py_IS_TYPE(hobj, state->thread_handle_type)) {
2019
0
        PyErr_SetString(PyExc_TypeError, "'handle' must be a _ThreadHandle");
2020
0
        return NULL;
2021
0
    }
2022
2023
0
    if (PySys_Audit("_thread.start_joinable_thread", "OiO", func, daemon,
2024
0
                    hobj) < 0) {
2025
0
        return NULL;
2026
0
    }
2027
2028
0
    if (hobj == Py_None) {
2029
0
        hobj = (PyObject *)PyThreadHandleObject_new(state->thread_handle_type);
2030
0
        if (hobj == NULL) {
2031
0
            return NULL;
2032
0
        }
2033
0
    }
2034
0
    else {
2035
0
        Py_INCREF(hobj);
2036
0
    }
2037
2038
0
    PyObject* args = PyTuple_New(0);
2039
0
    if (args == NULL) {
2040
0
        return NULL;
2041
0
    }
2042
0
    int st = do_start_new_thread(state, func, args,
2043
0
                                 /*kwargs=*/ NULL, ((PyThreadHandleObject*)hobj)->handle, daemon);
2044
0
    Py_DECREF(args);
2045
0
    if (st < 0) {
2046
0
        Py_DECREF(hobj);
2047
0
        return NULL;
2048
0
    }
2049
0
    return (PyObject *) hobj;
2050
0
}
2051
2052
PyDoc_STRVAR(start_joinable_doc,
2053
"start_joinable_thread($module, /, function, handle=None, daemon=True)\n\
2054
--\n\
2055
\n\
2056
*For internal use only*: start a new thread.\n\
2057
\n\
2058
Like start_new_thread(), this starts a new thread calling the given function.\n\
2059
Unlike start_new_thread(), this returns a handle object with methods to join\n\
2060
or detach the given thread.\n\
2061
This function is not for third-party code, please use the\n\
2062
`threading` module instead. During finalization the runtime will not wait for\n\
2063
the thread to exit if daemon is True. If handle is provided it must be a\n\
2064
newly created thread._ThreadHandle instance.");
2065
2066
static PyObject *
2067
thread_PyThread_exit_thread(PyObject *self, PyObject *Py_UNUSED(ignored))
2068
0
{
2069
0
    PyErr_SetNone(PyExc_SystemExit);
2070
0
    return NULL;
2071
0
}
2072
2073
PyDoc_STRVAR(exit_doc,
2074
"exit($module, /)\n\
2075
--\n\
2076
\n\
2077
This is synonymous to ``raise SystemExit''.  It will cause the current\n\
2078
thread to exit silently unless the exception is caught.");
2079
2080
PyDoc_STRVAR(exit_thread_doc,
2081
"exit_thread($module, /)\n\
2082
--\n\
2083
\n\
2084
An obsolete synonym of exit().");
2085
2086
static PyObject *
2087
thread_PyThread_interrupt_main(PyObject *self, PyObject *args)
2088
0
{
2089
0
    int signum = SIGINT;
2090
0
    if (!PyArg_ParseTuple(args, "|i:signum", &signum)) {
2091
0
        return NULL;
2092
0
    }
2093
2094
0
    if (PyErr_SetInterruptEx(signum)) {
2095
0
        PyErr_SetString(PyExc_ValueError, "signal number out of range");
2096
0
        return NULL;
2097
0
    }
2098
0
    Py_RETURN_NONE;
2099
0
}
2100
2101
PyDoc_STRVAR(interrupt_doc,
2102
"interrupt_main($module, signum=signal.SIGINT, /)\n\
2103
--\n\
2104
\n\
2105
Simulate the arrival of the given signal in the main thread,\n\
2106
where the corresponding signal handler will be executed.\n\
2107
If *signum* is omitted, SIGINT is assumed.\n\
2108
A subthread can use this function to interrupt the main thread.\n\
2109
\n\
2110
Note: the default signal handler for SIGINT raises ``KeyboardInterrupt``."
2111
);
2112
2113
static PyObject *
2114
thread_PyThread_allocate_lock(PyObject *module, PyObject *Py_UNUSED(ignored))
2115
1.27k
{
2116
1.27k
    thread_module_state *state = get_thread_state(module);
2117
1.27k
    return lock_new_impl(state->lock_type);
2118
1.27k
}
2119
2120
PyDoc_STRVAR(allocate_lock_doc,
2121
"allocate_lock($module, /)\n\
2122
--\n\
2123
\n\
2124
Create a new lock object. See help(type(threading.Lock())) for\n\
2125
information about locks.");
2126
2127
PyDoc_STRVAR(allocate_doc,
2128
"allocate($module, /)\n\
2129
--\n\
2130
\n\
2131
An obsolete synonym of allocate_lock().");
2132
2133
static PyObject *
2134
thread_get_ident(PyObject *self, PyObject *Py_UNUSED(ignored))
2135
2.89k
{
2136
2.89k
    PyThread_ident_t ident = PyThread_get_thread_ident_ex();
2137
2.89k
    if (ident == PYTHREAD_INVALID_THREAD_ID) {
2138
0
        PyErr_SetString(ThreadError, "no current thread ident");
2139
0
        return NULL;
2140
0
    }
2141
2.89k
    return PyLong_FromUnsignedLongLong(ident);
2142
2.89k
}
2143
2144
PyDoc_STRVAR(get_ident_doc,
2145
"get_ident($module, /)\n\
2146
--\n\
2147
\n\
2148
Return a non-zero integer that uniquely identifies the current thread\n\
2149
amongst other threads that exist simultaneously.\n\
2150
This may be used to identify per-thread resources.\n\
2151
Even though on some platforms threads identities may appear to be\n\
2152
allocated consecutive numbers starting at 1, this behavior should not\n\
2153
be relied upon, and the number should be seen purely as a magic cookie.\n\
2154
A thread's identity may be reused for another thread after it exits.");
2155
2156
#ifdef PY_HAVE_THREAD_NATIVE_ID
2157
static PyObject *
2158
thread_get_native_id(PyObject *self, PyObject *Py_UNUSED(ignored))
2159
0
{
2160
0
    unsigned long native_id = PyThread_get_thread_native_id();
2161
0
    return PyLong_FromUnsignedLong(native_id);
2162
0
}
2163
2164
PyDoc_STRVAR(get_native_id_doc,
2165
"get_native_id($module, /)\n\
2166
--\n\
2167
\n\
2168
Return a non-negative integer identifying the thread as reported\n\
2169
by the OS (kernel). This may be used to uniquely identify a\n\
2170
particular thread within a system.");
2171
#endif
2172
2173
static PyObject *
2174
thread__count(PyObject *self, PyObject *Py_UNUSED(ignored))
2175
0
{
2176
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
2177
0
    return PyLong_FromSsize_t(_Py_atomic_load_ssize(&interp->threads.count));
2178
0
}
2179
2180
PyDoc_STRVAR(_count_doc,
2181
"_count($module, /)\n\
2182
--\n\
2183
\n\
2184
Return the number of currently running Python threads, excluding\n\
2185
the main thread. The returned number comprises all threads created\n\
2186
through `start_new_thread()` as well as `threading.Thread`, and not\n\
2187
yet finished.\n\
2188
\n\
2189
This function is meant for internal and specialized purposes only.\n\
2190
In most applications `threading.enumerate()` should be used instead.");
2191
2192
static PyObject *
2193
thread_stack_size(PyObject *self, PyObject *args)
2194
0
{
2195
0
    size_t old_size;
2196
0
    Py_ssize_t new_size = 0;
2197
0
    int rc;
2198
2199
0
    if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size))
2200
0
        return NULL;
2201
2202
0
    Py_ssize_t min_size = _PyOS_MIN_STACK_SIZE + SYSTEM_PAGE_SIZE;
2203
0
    if (new_size != 0 && new_size < min_size) {
2204
0
        PyErr_Format(PyExc_ValueError,
2205
0
                     "size must be at least %zi bytes", min_size);
2206
0
        return NULL;
2207
0
    }
2208
2209
0
    old_size = PyThread_get_stacksize();
2210
2211
0
    rc = PyThread_set_stacksize((size_t) new_size);
2212
0
    if (rc == -1) {
2213
0
        PyErr_Format(PyExc_ValueError,
2214
0
                     "size not valid: %zd bytes",
2215
0
                     new_size);
2216
0
        return NULL;
2217
0
    }
2218
0
    if (rc == -2) {
2219
0
        PyErr_SetString(ThreadError,
2220
0
                        "setting stack size not supported");
2221
0
        return NULL;
2222
0
    }
2223
2224
0
    return PyLong_FromSsize_t((Py_ssize_t) old_size);
2225
0
}
2226
2227
PyDoc_STRVAR(stack_size_doc,
2228
"stack_size($module, size=0, /)\n\
2229
--\n\
2230
\n\
2231
Return the thread stack size used when creating new threads.  The\n\
2232
optional size argument specifies the stack size (in bytes) to be used\n\
2233
for subsequently created threads, and must be 0 (use platform or\n\
2234
configured default) or a positive integer value of at least 32,768 (32k).\n\
2235
If changing the thread stack size is unsupported, a ThreadError\n\
2236
exception is raised.  If the specified size is invalid, a ValueError\n\
2237
exception is raised, and the stack size is unmodified.  32k bytes\n\
2238
 currently the minimum supported stack size value to guarantee\n\
2239
sufficient stack space for the interpreter itself.\n\
2240
\n\
2241
Note that some platforms may have particular restrictions on values for\n\
2242
the stack size, such as requiring a minimum stack size larger than 32 KiB or\n\
2243
requiring allocation in multiples of the system memory page size\n\
2244
- platform documentation should be referred to for more information\n\
2245
(4 KiB pages are common; using multiples of 4096 for the stack size is\n\
2246
the suggested approach in the absence of more specific information).");
2247
2248
static int
2249
thread_excepthook_file(PyObject *file, PyObject *exc_type, PyObject *exc_value,
2250
                       PyObject *exc_traceback, PyObject *thread)
2251
0
{
2252
    /* print(f"Exception in thread {thread.name}:", file=file) */
2253
0
    if (PyFile_WriteString("Exception in thread ", file) < 0) {
2254
0
        return -1;
2255
0
    }
2256
2257
0
    PyObject *name = NULL;
2258
0
    if (thread != Py_None) {
2259
0
        if (PyObject_GetOptionalAttr(thread, &_Py_ID(name), &name) < 0) {
2260
0
            return -1;
2261
0
        }
2262
0
    }
2263
0
    if (name != NULL) {
2264
0
        if (PyFile_WriteObject(name, file, Py_PRINT_RAW) < 0) {
2265
0
            Py_DECREF(name);
2266
0
            return -1;
2267
0
        }
2268
0
        Py_DECREF(name);
2269
0
    }
2270
0
    else {
2271
0
        PyThread_ident_t ident = PyThread_get_thread_ident_ex();
2272
0
        PyObject *str = PyUnicode_FromFormat("%" PY_FORMAT_THREAD_IDENT_T, ident);
2273
0
        if (str != NULL) {
2274
0
            if (PyFile_WriteObject(str, file, Py_PRINT_RAW) < 0) {
2275
0
                Py_DECREF(str);
2276
0
                return -1;
2277
0
            }
2278
0
            Py_DECREF(str);
2279
0
        }
2280
0
        else {
2281
0
            PyErr_Clear();
2282
2283
0
            if (PyFile_WriteString("<failed to get thread name>", file) < 0) {
2284
0
                return -1;
2285
0
            }
2286
0
        }
2287
0
    }
2288
2289
0
    if (PyFile_WriteString(":\n", file) < 0) {
2290
0
        return -1;
2291
0
    }
2292
2293
    /* Display the traceback */
2294
0
    _PyErr_Display(file, exc_type, exc_value, exc_traceback);
2295
2296
    /* Call file.flush() */
2297
0
    if (_PyFile_Flush(file) < 0) {
2298
0
        return -1;
2299
0
    }
2300
2301
0
    return 0;
2302
0
}
2303
2304
2305
PyDoc_STRVAR(ExceptHookArgs__doc__,
2306
"ExceptHookArgs\n\
2307
\n\
2308
Type used to pass arguments to threading.excepthook.");
2309
2310
static PyStructSequence_Field ExceptHookArgs_fields[] = {
2311
    {"exc_type", "Exception type"},
2312
    {"exc_value", "Exception value"},
2313
    {"exc_traceback", "Exception traceback"},
2314
    {"thread", "Thread"},
2315
    {0}
2316
};
2317
2318
static PyStructSequence_Desc ExceptHookArgs_desc = {
2319
    .name = "_thread._ExceptHookArgs",
2320
    .doc = ExceptHookArgs__doc__,
2321
    .fields = ExceptHookArgs_fields,
2322
    .n_in_sequence = 4
2323
};
2324
2325
2326
static PyObject *
2327
thread_excepthook(PyObject *module, PyObject *args)
2328
0
{
2329
0
    thread_module_state *state = get_thread_state(module);
2330
2331
0
    if (!Py_IS_TYPE(args, state->excepthook_type)) {
2332
0
        PyErr_SetString(PyExc_TypeError,
2333
0
                        "_thread.excepthook argument type "
2334
0
                        "must be ExceptHookArgs");
2335
0
        return NULL;
2336
0
    }
2337
2338
    /* Borrowed reference */
2339
0
    PyObject *exc_type = PyStructSequence_GET_ITEM(args, 0);
2340
0
    if (exc_type == PyExc_SystemExit) {
2341
        /* silently ignore SystemExit */
2342
0
        Py_RETURN_NONE;
2343
0
    }
2344
2345
    /* Borrowed references */
2346
0
    PyObject *exc_value = PyStructSequence_GET_ITEM(args, 1);
2347
0
    PyObject *exc_tb = PyStructSequence_GET_ITEM(args, 2);
2348
0
    PyObject *thread = PyStructSequence_GET_ITEM(args, 3);
2349
2350
0
    PyObject *file;
2351
0
    if (PySys_GetOptionalAttr( &_Py_ID(stderr), &file) < 0) {
2352
0
        return NULL;
2353
0
    }
2354
0
    if (file == NULL || file == Py_None) {
2355
0
        Py_XDECREF(file);
2356
0
        if (thread == Py_None) {
2357
            /* do nothing if sys.stderr is None and thread is None */
2358
0
            Py_RETURN_NONE;
2359
0
        }
2360
2361
0
        file = PyObject_GetAttrString(thread, "_stderr");
2362
0
        if (file == NULL) {
2363
0
            return NULL;
2364
0
        }
2365
0
        if (file == Py_None) {
2366
0
            Py_DECREF(file);
2367
            /* do nothing if sys.stderr is None and sys.stderr was None
2368
               when the thread was created */
2369
0
            Py_RETURN_NONE;
2370
0
        }
2371
0
    }
2372
2373
0
    int res = thread_excepthook_file(file, exc_type, exc_value, exc_tb,
2374
0
                                     thread);
2375
0
    Py_DECREF(file);
2376
0
    if (res < 0) {
2377
0
        return NULL;
2378
0
    }
2379
2380
0
    Py_RETURN_NONE;
2381
0
}
2382
2383
PyDoc_STRVAR(excepthook_doc,
2384
"_excepthook($module, args, /)\n\
2385
--\n\
2386
\n\
2387
Handle uncaught Thread.run() exception.");
2388
2389
static PyObject *
2390
thread__is_main_interpreter(PyObject *module, PyObject *Py_UNUSED(ignored))
2391
0
{
2392
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
2393
0
    return PyBool_FromLong(_Py_IsMainInterpreter(interp));
2394
0
}
2395
2396
PyDoc_STRVAR(thread__is_main_interpreter_doc,
2397
"_is_main_interpreter($module, /)\n\
2398
--\n\
2399
\n\
2400
Return True if the current interpreter is the main Python interpreter.");
2401
2402
static PyObject *
2403
thread_shutdown(PyObject *self, PyObject *args)
2404
0
{
2405
0
    PyThread_ident_t ident = PyThread_get_thread_ident_ex();
2406
0
    thread_module_state *state = get_thread_state(self);
2407
2408
0
    for (;;) {
2409
0
        ThreadHandle *handle = NULL;
2410
2411
        // Find a thread that's not yet finished.
2412
0
        HEAD_LOCK(&_PyRuntime);
2413
0
        struct llist_node *node;
2414
0
        llist_for_each_safe(node, &state->shutdown_handles) {
2415
0
            ThreadHandle *cur = llist_data(node, ThreadHandle, shutdown_node);
2416
0
            if (cur->ident != ident) {
2417
0
                ThreadHandle_incref(cur);
2418
0
                handle = cur;
2419
0
                break;
2420
0
            }
2421
0
        }
2422
0
        HEAD_UNLOCK(&_PyRuntime);
2423
2424
0
        if (!handle) {
2425
            // No more threads to wait on!
2426
0
            break;
2427
0
        }
2428
2429
        // Wait for the thread to finish. If we're interrupted, such
2430
        // as by a ctrl-c we print the error and exit early.
2431
0
        if (ThreadHandle_join(handle, -1) < 0) {
2432
0
            ThreadHandle_decref(handle);
2433
0
            return NULL;
2434
0
        }
2435
2436
0
        ThreadHandle_decref(handle);
2437
0
    }
2438
2439
0
    Py_RETURN_NONE;
2440
0
}
2441
2442
PyDoc_STRVAR(shutdown_doc,
2443
"_shutdown($module, /)\n\
2444
--\n\
2445
\n\
2446
Wait for all non-daemon threads (other than the calling thread) to stop.");
2447
2448
static PyObject *
2449
thread__make_thread_handle(PyObject *module, PyObject *identobj)
2450
0
{
2451
0
    thread_module_state *state = get_thread_state(module);
2452
0
    if (!PyLong_Check(identobj)) {
2453
0
        PyErr_SetString(PyExc_TypeError, "ident must be an integer");
2454
0
        return NULL;
2455
0
    }
2456
0
    PyThread_ident_t ident = PyLong_AsUnsignedLongLong(identobj);
2457
0
    if (PyErr_Occurred()) {
2458
0
        return NULL;
2459
0
    }
2460
0
    PyThreadHandleObject *hobj =
2461
0
        PyThreadHandleObject_new(state->thread_handle_type);
2462
0
    if (hobj == NULL) {
2463
0
        return NULL;
2464
0
    }
2465
0
    PyMutex_Lock(&hobj->handle->mutex);
2466
0
    hobj->handle->ident = ident;
2467
0
    hobj->handle->state = THREAD_HANDLE_RUNNING;
2468
0
    PyMutex_Unlock(&hobj->handle->mutex);
2469
0
    return (PyObject*) hobj;
2470
0
}
2471
2472
PyDoc_STRVAR(thread__make_thread_handle_doc,
2473
"_make_thread_handle($module, ident, /)\n\
2474
--\n\
2475
\n\
2476
Internal only. Make a thread handle for threads not spawned\n\
2477
by the _thread or threading module.");
2478
2479
static PyObject *
2480
thread__get_main_thread_ident(PyObject *module, PyObject *Py_UNUSED(ignored))
2481
0
{
2482
0
    return PyLong_FromUnsignedLongLong(_PyRuntime.main_thread);
2483
0
}
2484
2485
PyDoc_STRVAR(thread__get_main_thread_ident_doc,
2486
"_get_main_thread_ident($module, /)\n\
2487
--\n\
2488
\n\
2489
Internal only. Return a non-zero integer that uniquely identifies the main thread\n\
2490
of the main interpreter.");
2491
2492
#if defined(__OpenBSD__)
2493
    /* pthread_*_np functions, especially pthread_{get,set}_name_np().
2494
       pthread_np.h exists on both OpenBSD and FreeBSD but the latter declares
2495
       pthread_getname_np() and pthread_setname_np() in pthread.h as long as
2496
       __BSD_VISIBLE remains set.
2497
     */
2498
#   include <pthread_np.h>
2499
#endif
2500
2501
#if defined(HAVE_PTHREAD_GETNAME_NP) || defined(HAVE_PTHREAD_GET_NAME_NP) || defined(MS_WINDOWS)
2502
/*[clinic input]
2503
_thread._get_name
2504
2505
Get the name of the current thread.
2506
[clinic start generated code]*/
2507
2508
static PyObject *
2509
_thread__get_name_impl(PyObject *module)
2510
/*[clinic end generated code: output=20026e7ee3da3dd7 input=35cec676833d04c8]*/
2511
0
{
2512
0
#ifndef MS_WINDOWS
2513
    // Linux and macOS are limited to respectively 16 and 64 bytes
2514
0
    char name[100];
2515
0
    pthread_t thread = pthread_self();
2516
0
#ifdef HAVE_PTHREAD_GETNAME_NP
2517
0
    int rc = pthread_getname_np(thread, name, Py_ARRAY_LENGTH(name));
2518
#else /* defined(HAVE_PTHREAD_GET_NAME_NP) */
2519
    int rc = 0; /* pthread_get_name_np() returns void */
2520
    pthread_get_name_np(thread, name, Py_ARRAY_LENGTH(name));
2521
#endif
2522
0
    if (rc) {
2523
0
        errno = rc;
2524
0
        return PyErr_SetFromErrno(PyExc_OSError);
2525
0
    }
2526
2527
#ifdef __sun
2528
    // gh-138004: Decode Solaris/Illumos (e.g. OpenIndiana) thread names
2529
    // from ASCII, since OpenIndiana only supports ASCII names.
2530
    return PyUnicode_DecodeASCII(name, strlen(name), "surrogateescape");
2531
#else
2532
0
    return PyUnicode_DecodeFSDefault(name);
2533
0
#endif
2534
#else
2535
    // Windows implementation
2536
    assert(pGetThreadDescription != NULL);
2537
2538
    wchar_t *name;
2539
    HRESULT hr = pGetThreadDescription(GetCurrentThread(), &name);
2540
    if (FAILED(hr)) {
2541
        PyErr_SetFromWindowsErr(0);
2542
        return NULL;
2543
    }
2544
2545
    PyObject *name_obj = PyUnicode_FromWideChar(name, -1);
2546
    LocalFree(name);
2547
    return name_obj;
2548
#endif
2549
0
}
2550
#endif  // HAVE_PTHREAD_GETNAME_NP || HAVE_PTHREAD_GET_NAME_NP || MS_WINDOWS
2551
2552
2553
#if defined(HAVE_PTHREAD_SETNAME_NP) || defined(HAVE_PTHREAD_SET_NAME_NP) || defined(MS_WINDOWS)
2554
/*[clinic input]
2555
_thread.set_name
2556
2557
    name as name_obj: unicode
2558
2559
Set the name of the current thread.
2560
[clinic start generated code]*/
2561
2562
static PyObject *
2563
_thread_set_name_impl(PyObject *module, PyObject *name_obj)
2564
/*[clinic end generated code: output=402b0c68e0c0daed input=7e7acd98261be82f]*/
2565
0
{
2566
0
#ifndef MS_WINDOWS
2567
#ifdef __sun
2568
    // gh-138004: Encode Solaris/Illumos thread names to ASCII,
2569
    // since OpenIndiana does not support non-ASCII names.
2570
    const char *encoding = "ascii";
2571
#else
2572
    // Encode the thread name to the filesystem encoding using the "replace"
2573
    // error handler
2574
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
2575
0
    const char *encoding = interp->unicode.fs_codec.encoding;
2576
0
#endif
2577
0
    PyObject *name_encoded;
2578
0
    name_encoded = PyUnicode_AsEncodedString(name_obj, encoding, "replace");
2579
0
    if (name_encoded == NULL) {
2580
0
        return NULL;
2581
0
    }
2582
2583
0
#ifdef _PYTHREAD_NAME_MAXLEN
2584
    // Truncate to _PYTHREAD_NAME_MAXLEN bytes + the NUL byte if needed
2585
0
    if (PyBytes_GET_SIZE(name_encoded) > _PYTHREAD_NAME_MAXLEN) {
2586
0
        PyObject *truncated;
2587
0
        truncated = PyBytes_FromStringAndSize(PyBytes_AS_STRING(name_encoded),
2588
0
                                              _PYTHREAD_NAME_MAXLEN);
2589
0
        if (truncated == NULL) {
2590
0
            Py_DECREF(name_encoded);
2591
0
            return NULL;
2592
0
        }
2593
0
        Py_SETREF(name_encoded, truncated);
2594
0
    }
2595
0
#endif
2596
2597
0
    const char *name = PyBytes_AS_STRING(name_encoded);
2598
#ifdef __APPLE__
2599
    int rc = pthread_setname_np(name);
2600
#elif defined(__NetBSD__)
2601
    pthread_t thread = pthread_self();
2602
    int rc = pthread_setname_np(thread, "%s", (void *)name);
2603
#elif defined(HAVE_PTHREAD_SETNAME_NP)
2604
    pthread_t thread = pthread_self();
2605
0
    int rc = pthread_setname_np(thread, name);
2606
#else /* defined(HAVE_PTHREAD_SET_NAME_NP) */
2607
    pthread_t thread = pthread_self();
2608
    int rc = 0; /* pthread_set_name_np() returns void */
2609
    pthread_set_name_np(thread, name);
2610
#endif
2611
0
    Py_DECREF(name_encoded);
2612
0
    if (rc) {
2613
0
        errno = rc;
2614
0
        return PyErr_SetFromErrno(PyExc_OSError);
2615
0
    }
2616
0
    Py_RETURN_NONE;
2617
#else
2618
    // Windows implementation
2619
    assert(pSetThreadDescription != NULL);
2620
2621
    Py_ssize_t len;
2622
    wchar_t *name = PyUnicode_AsWideCharString(name_obj, &len);
2623
    if (name == NULL) {
2624
        return NULL;
2625
    }
2626
2627
    if (len > _PYTHREAD_NAME_MAXLEN) {
2628
        // Truncate the name
2629
        Py_UCS4 ch = name[_PYTHREAD_NAME_MAXLEN-1];
2630
        if (Py_UNICODE_IS_HIGH_SURROGATE(ch)) {
2631
            name[_PYTHREAD_NAME_MAXLEN-1] = 0;
2632
        }
2633
        else {
2634
            name[_PYTHREAD_NAME_MAXLEN] = 0;
2635
        }
2636
    }
2637
2638
    HRESULT hr = pSetThreadDescription(GetCurrentThread(), name);
2639
    PyMem_Free(name);
2640
    if (FAILED(hr)) {
2641
        PyErr_SetFromWindowsErr((int)hr);
2642
        return NULL;
2643
    }
2644
    Py_RETURN_NONE;
2645
#endif
2646
0
}
2647
#endif  // HAVE_PTHREAD_SETNAME_NP || HAVE_PTHREAD_SET_NAME_NP || MS_WINDOWS
2648
2649
2650
static PyMethodDef thread_methods[] = {
2651
    {"start_new_thread",        thread_PyThread_start_new_thread,
2652
     METH_VARARGS, start_new_thread_doc},
2653
    {"start_new",               thread_PyThread_start_new_thread,
2654
     METH_VARARGS, start_new_doc},
2655
    {"start_joinable_thread",   _PyCFunction_CAST(thread_PyThread_start_joinable_thread),
2656
     METH_VARARGS | METH_KEYWORDS, start_joinable_doc},
2657
    {"daemon_threads_allowed",  thread_daemon_threads_allowed,
2658
     METH_NOARGS, daemon_threads_allowed_doc},
2659
    {"allocate_lock",           thread_PyThread_allocate_lock,
2660
     METH_NOARGS, allocate_lock_doc},
2661
    {"allocate",                thread_PyThread_allocate_lock,
2662
     METH_NOARGS, allocate_doc},
2663
    {"exit_thread",             thread_PyThread_exit_thread,
2664
     METH_NOARGS, exit_thread_doc},
2665
    {"exit",                    thread_PyThread_exit_thread,
2666
     METH_NOARGS, exit_doc},
2667
    {"interrupt_main",          thread_PyThread_interrupt_main,
2668
     METH_VARARGS, interrupt_doc},
2669
    {"get_ident",               thread_get_ident,
2670
     METH_NOARGS, get_ident_doc},
2671
#ifdef PY_HAVE_THREAD_NATIVE_ID
2672
    {"get_native_id",           thread_get_native_id,
2673
     METH_NOARGS, get_native_id_doc},
2674
#endif
2675
    {"_count",                  thread__count,
2676
     METH_NOARGS, _count_doc},
2677
    {"stack_size",              thread_stack_size,
2678
     METH_VARARGS, stack_size_doc},
2679
    {"_excepthook",             thread_excepthook,
2680
     METH_O, excepthook_doc},
2681
    {"_is_main_interpreter",    thread__is_main_interpreter,
2682
     METH_NOARGS, thread__is_main_interpreter_doc},
2683
    {"_shutdown",               thread_shutdown,
2684
     METH_NOARGS, shutdown_doc},
2685
    {"_make_thread_handle", thread__make_thread_handle,
2686
     METH_O, thread__make_thread_handle_doc},
2687
    {"_get_main_thread_ident", thread__get_main_thread_ident,
2688
     METH_NOARGS, thread__get_main_thread_ident_doc},
2689
    _THREAD_SET_NAME_METHODDEF
2690
    _THREAD__GET_NAME_METHODDEF
2691
    {NULL,                      NULL}           /* sentinel */
2692
};
2693
2694
2695
/* Initialization function */
2696
2697
static int
2698
thread_module_exec(PyObject *module)
2699
22
{
2700
22
    thread_module_state *state = get_thread_state(module);
2701
22
    PyObject *d = PyModule_GetDict(module);
2702
2703
    // Initialize the C thread library
2704
22
    PyThread_init_thread();
2705
2706
    // _ThreadHandle
2707
22
    state->thread_handle_type = (PyTypeObject *)PyType_FromSpec(&ThreadHandle_Type_spec);
2708
22
    if (state->thread_handle_type == NULL) {
2709
0
        return -1;
2710
0
    }
2711
22
    if (PyDict_SetItemString(d, "_ThreadHandle", (PyObject *)state->thread_handle_type) < 0) {
2712
0
        return -1;
2713
0
    }
2714
2715
    // Lock
2716
22
    state->lock_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, &lock_type_spec, NULL);
2717
22
    if (state->lock_type == NULL) {
2718
0
        return -1;
2719
0
    }
2720
22
    if (PyModule_AddType(module, state->lock_type) < 0) {
2721
0
        return -1;
2722
0
    }
2723
    // Old alias: lock -> LockType
2724
22
    if (PyDict_SetItemString(d, "LockType", (PyObject *)state->lock_type) < 0) {
2725
0
        return -1;
2726
0
    }
2727
2728
    // RLock
2729
22
    state->rlock_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, &rlock_type_spec, NULL);
2730
22
    if (state->rlock_type == NULL) {
2731
0
        return -1;
2732
0
    }
2733
22
    if (PyModule_AddType(module, state->rlock_type) < 0) {
2734
0
        return -1;
2735
0
    }
2736
2737
    // Local dummy
2738
22
    state->local_dummy_type = (PyTypeObject *)PyType_FromSpec(&local_dummy_type_spec);
2739
22
    if (state->local_dummy_type == NULL) {
2740
0
        return -1;
2741
0
    }
2742
2743
    // Local
2744
22
    state->local_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, &local_type_spec, NULL);
2745
22
    if (state->local_type == NULL) {
2746
0
        return -1;
2747
0
    }
2748
22
    if (PyModule_AddType(module, state->local_type) < 0) {
2749
0
        return -1;
2750
0
    }
2751
2752
    // Add module attributes
2753
22
    if (PyDict_SetItemString(d, "error", ThreadError) < 0) {
2754
0
        return -1;
2755
0
    }
2756
2757
    // _ExceptHookArgs type
2758
22
    state->excepthook_type = PyStructSequence_NewType(&ExceptHookArgs_desc);
2759
22
    if (state->excepthook_type == NULL) {
2760
0
        return -1;
2761
0
    }
2762
22
    if (PyModule_AddType(module, state->excepthook_type) < 0) {
2763
0
        return -1;
2764
0
    }
2765
2766
    // TIMEOUT_MAX
2767
22
    double timeout_max = (double)PY_TIMEOUT_MAX * 1e-6;
2768
22
    double time_max = PyTime_AsSecondsDouble(PyTime_MAX);
2769
22
    timeout_max = Py_MIN(timeout_max, time_max);
2770
    // Round towards minus infinity
2771
22
    timeout_max = floor(timeout_max);
2772
2773
22
    if (PyModule_Add(module, "TIMEOUT_MAX",
2774
22
                        PyFloat_FromDouble(timeout_max)) < 0) {
2775
0
        return -1;
2776
0
    }
2777
2778
22
    llist_init(&state->shutdown_handles);
2779
2780
22
#ifdef _PYTHREAD_NAME_MAXLEN
2781
22
    if (PyModule_AddIntConstant(module, "_NAME_MAXLEN",
2782
22
                                _PYTHREAD_NAME_MAXLEN) < 0) {
2783
0
        return -1;
2784
0
    }
2785
22
#endif
2786
2787
#ifdef MS_WINDOWS
2788
    HMODULE kernelbase = GetModuleHandleW(L"kernelbase.dll");
2789
    if (kernelbase != NULL) {
2790
        if (pGetThreadDescription == NULL) {
2791
            pGetThreadDescription = (PF_GET_THREAD_DESCRIPTION)GetProcAddress(
2792
                                        kernelbase, "GetThreadDescription");
2793
        }
2794
        if (pSetThreadDescription == NULL) {
2795
            pSetThreadDescription = (PF_SET_THREAD_DESCRIPTION)GetProcAddress(
2796
                                        kernelbase, "SetThreadDescription");
2797
        }
2798
    }
2799
2800
    if (pGetThreadDescription == NULL) {
2801
        if (PyObject_DelAttrString(module, "_get_name") < 0) {
2802
            return -1;
2803
        }
2804
    }
2805
    if (pSetThreadDescription == NULL) {
2806
        if (PyObject_DelAttrString(module, "set_name") < 0) {
2807
            return -1;
2808
        }
2809
    }
2810
#endif
2811
2812
22
    return 0;
2813
22
}
2814
2815
2816
static int
2817
thread_module_traverse(PyObject *module, visitproc visit, void *arg)
2818
420
{
2819
420
    thread_module_state *state = get_thread_state(module);
2820
420
    Py_VISIT(state->excepthook_type);
2821
420
    Py_VISIT(state->lock_type);
2822
420
    Py_VISIT(state->rlock_type);
2823
420
    Py_VISIT(state->local_type);
2824
420
    Py_VISIT(state->local_dummy_type);
2825
420
    Py_VISIT(state->thread_handle_type);
2826
420
    return 0;
2827
420
}
2828
2829
static int
2830
thread_module_clear(PyObject *module)
2831
0
{
2832
0
    thread_module_state *state = get_thread_state(module);
2833
0
    Py_CLEAR(state->excepthook_type);
2834
0
    Py_CLEAR(state->lock_type);
2835
0
    Py_CLEAR(state->rlock_type);
2836
0
    Py_CLEAR(state->local_type);
2837
0
    Py_CLEAR(state->local_dummy_type);
2838
0
    Py_CLEAR(state->thread_handle_type);
2839
    // Remove any remaining handles (e.g. if shutdown exited early due to
2840
    // interrupt) so that attempts to unlink the handle after our module state
2841
    // is destroyed do not crash.
2842
0
    clear_shutdown_handles(state);
2843
0
    return 0;
2844
0
}
2845
2846
static void
2847
thread_module_free(void *module)
2848
0
{
2849
0
    (void)thread_module_clear((PyObject *)module);
2850
0
}
2851
2852
2853
2854
PyDoc_STRVAR(thread_doc,
2855
"This module provides primitive operations to write multi-threaded programs.\n\
2856
The 'threading' module provides a more convenient interface.");
2857
2858
static PyModuleDef_Slot thread_module_slots[] = {
2859
    _Py_ABI_SLOT,
2860
    {Py_mod_exec, thread_module_exec},
2861
    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
2862
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
2863
    {0, NULL}
2864
};
2865
2866
static struct PyModuleDef thread_module = {
2867
    PyModuleDef_HEAD_INIT,
2868
    .m_name = "_thread",
2869
    .m_doc = thread_doc,
2870
    .m_size = sizeof(thread_module_state),
2871
    .m_methods = thread_methods,
2872
    .m_traverse = thread_module_traverse,
2873
    .m_clear = thread_module_clear,
2874
    .m_free = thread_module_free,
2875
    .m_slots = thread_module_slots,
2876
};
2877
2878
PyMODINIT_FUNC
2879
PyInit__thread(void)
2880
22
{
2881
22
    return PyModuleDef_Init(&thread_module);
2882
22
}