Coverage Report

Created: 2026-10-17 06:15

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