Coverage Report

Created: 2026-10-31 06:21

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
8.50M
{
59
8.50M
    void *state = _PyModule_GetState(module);
60
8.50M
    assert(state != NULL);
61
8.50M
    return (thread_module_state *)state;
62
8.50M
}
63
64
static inline thread_module_state*
65
get_thread_state_by_cls(PyTypeObject *cls)
66
23.6k
{
67
    // Use PyType_GetModuleByDef() to handle (R)Lock subclasses.
68
23.6k
    PyObject *module = PyType_GetModuleByDef(cls, &thread_module);
69
23.6k
    if (module == NULL) {
70
0
        return NULL;
71
0
    }
72
23.6k
    return get_thread_state(module);
73
23.6k
}
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
23.6k
#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
11.8k
{
792
11.8k
    PyObject_GC_UnTrack(self);
793
11.8k
    PyObject_ClearWeakRefs(self);
794
11.8k
    PyTypeObject *tp = Py_TYPE(self);
795
11.8k
    tp->tp_free(self);
796
11.8k
    Py_DECREF(tp);
797
11.8k
}
798
799
800
static int
801
lock_acquire_parse_timeout(PyObject *timeout_obj, int blocking, PyTime_t *timeout)
802
189k
{
803
    // XXX Use PyThread_ParseTimeoutArg().
804
805
189k
    const PyTime_t unset_timeout = _PyTime_FromSeconds(-1);
806
189k
    *timeout = unset_timeout;
807
808
189k
    if (timeout_obj
809
0
        && _PyTime_FromSecondsObject(timeout,
810
0
                                     timeout_obj, _PyTime_ROUND_TIMEOUT) < 0)
811
0
        return -1;
812
813
189k
    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
189k
    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
189k
    if (!blocking)
824
8
        *timeout = 0;
825
189k
    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
189k
    return 0;
836
189k
}
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
392
{
857
392
    PyTime_t timeout;
858
859
392
    if (lock_acquire_parse_timeout(timeoutobj, blocking, &timeout) < 0) {
860
0
        return NULL;
861
0
    }
862
863
392
    PyLockStatus r = _PyMutex_LockTimed(
864
392
        &self->lock, timeout,
865
392
        _PY_LOCK_PYTHONLOCK | _PY_LOCK_HANDLE_SIGNALS | _PY_LOCK_DETACH);
866
392
    if (r == PY_LOCK_INTR) {
867
0
        assert(PyErr_Occurred());
868
0
        return NULL;
869
0
    }
870
392
    if (r == PY_LOCK_FAILURE && PyErr_Occurred()) {
871
0
        return NULL;
872
0
    }
873
874
392
    return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
875
392
}
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
384
{
905
    /* Sanity check: the lock must be locked */
906
384
    if (_PyMutex_TryUnlock(&self->lock) < 0) {
907
0
        PyErr_SetString(ThreadError, "release unlocked lock");
908
0
        return NULL;
909
0
    }
910
911
384
    Py_RETURN_NONE;
912
384
}
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
376
{
937
376
    return _thread_lock_acquire_impl(self, 1, NULL);
938
376
}
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
376
{
955
376
    return _thread_lock_release_impl(self);
956
376
}
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
11.8k
{
1016
11.8k
    lockobject *self = (lockobject *)type->tp_alloc(type, 0);
1017
11.8k
    if (self == NULL) {
1018
0
        return NULL;
1019
0
    }
1020
11.8k
    self->lock = (PyMutex){0};
1021
11.8k
    return (PyObject *)self;
1022
11.8k
}
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.5k
{
1084
23.5k
    PyObject_GC_UnTrack(self);
1085
23.5k
    PyObject_ClearWeakRefs(self);
1086
23.5k
    PyTypeObject *tp = Py_TYPE(self);
1087
23.5k
    tp->tp_free(self);
1088
23.5k
    Py_DECREF(tp);
1089
23.5k
}
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
189k
{
1117
189k
    PyTime_t timeout;
1118
1119
189k
    if (lock_acquire_parse_timeout(timeoutobj, blocking, &timeout) < 0) {
1120
0
        return NULL;
1121
0
    }
1122
1123
189k
    PyLockStatus r = _PyRecursiveMutex_LockTimed(
1124
189k
        &self->lock, timeout,
1125
189k
        _PY_LOCK_PYTHONLOCK | _PY_LOCK_HANDLE_SIGNALS | _PY_LOCK_DETACH);
1126
189k
    if (r == PY_LOCK_INTR) {
1127
0
        assert(PyErr_Occurred());
1128
0
        return NULL;
1129
0
    }
1130
189k
    if (r == PY_LOCK_FAILURE && PyErr_Occurred()) {
1131
0
        return NULL;
1132
0
    }
1133
1134
189k
    return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
1135
189k
}
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
189k
{
1147
189k
    return _thread_RLock_acquire_impl(self, 1, NULL);
1148
189k
}
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
189k
{
1169
189k
    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
189k
    Py_RETURN_NONE;
1175
189k
}
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
189k
{
1193
189k
    return _thread_RLock_release_impl(self);
1194
189k
}
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.6k
{
1300
23.6k
    rlockobject *self = (rlockobject *) type->tp_alloc(type, 0);
1301
23.6k
    if (self == NULL) {
1302
0
        return NULL;
1303
0
    }
1304
23.6k
    self->lock = (_PyRecursiveMutex){0};
1305
23.6k
    return (PyObject *) self;
1306
23.6k
}
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
8.46M
#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
84
{
1492
84
    static PyMethodDef wr_callback_def = {
1493
84
        "clear_locals", clear_locals, METH_O
1494
84
    };
1495
1496
84
    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
84
    PyObject *self_wr = PyWeakref_NewRef((PyObject *) self, NULL);
1501
84
    if (self_wr == NULL) {
1502
0
        return NULL;
1503
0
    }
1504
1505
84
    PyObject *args = _PyTuple_FromPairSteal(self_wr,
1506
84
                                            Py_NewRef(tstate->threading_local_key));
1507
84
    if (args == NULL) {
1508
0
        return NULL;
1509
0
    }
1510
1511
84
    PyObject *cb = PyCFunction_New(&wr_callback_def, args);
1512
84
    Py_DECREF(args);
1513
84
    if (cb == NULL) {
1514
0
        return NULL;
1515
0
    }
1516
1517
84
    PyObject *wr = PyWeakref_NewRef(tstate->threading_local_sentinel, cb);
1518
84
    Py_DECREF(cb);
1519
1520
84
    return wr;
1521
84
}
1522
1523
static PyObject *
1524
local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
1525
84
{
1526
84
    if (type->tp_init == PyBaseObject_Type.tp_init) {
1527
84
        int rc = 0;
1528
84
        if (args != NULL)
1529
84
            rc = PyObject_IsTrue(args);
1530
84
        if (rc == 0 && kw != NULL)
1531
0
            rc = PyObject_IsTrue(kw);
1532
84
        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
84
    }
1540
1541
84
    PyObject *module = PyType_GetModuleByDef(type, &thread_module);
1542
84
    assert(module != NULL);
1543
84
    thread_module_state *state = get_thread_state(module);
1544
1545
    // A subclass finalizer may access attributes if construction fails.
1546
84
    PyObject *localdicts = PyDict_New();
1547
84
    if (localdicts == NULL) {
1548
0
        return NULL;
1549
0
    }
1550
84
    PyObject *thread_watchdogs = PySet_New(NULL);
1551
84
    if (thread_watchdogs == NULL) {
1552
0
        Py_DECREF(localdicts);
1553
0
        return NULL;
1554
0
    }
1555
1556
84
    localobject *self = (localobject *)type->tp_alloc(type, 0);
1557
84
    if (self == NULL) {
1558
0
        Py_DECREF(localdicts);
1559
0
        Py_DECREF(thread_watchdogs);
1560
0
        return NULL;
1561
0
    }
1562
84
    self->localdicts = localdicts;
1563
84
    self->thread_watchdogs = thread_watchdogs;
1564
1565
    // gh-128691: Use deferred reference counting for thread-locals to avoid
1566
    // contention on the shared object.
1567
84
    _PyObject_SetDeferredRefcount((PyObject *)self);
1568
1569
84
    self->args = Py_XNewRef(args);
1570
84
    self->kw = Py_XNewRef(kw);
1571
1572
84
    PyObject *localsdict = NULL;
1573
84
    PyObject *sentinel_wr = NULL;
1574
84
    if (create_localsdict(self, state, &localsdict, &sentinel_wr) < 0) {
1575
0
        goto err;
1576
0
    }
1577
84
    Py_DECREF(localsdict);
1578
84
    Py_DECREF(sentinel_wr);
1579
1580
84
    return (PyObject *)self;
1581
1582
0
  err:
1583
0
    Py_DECREF(self);
1584
0
    return NULL;
1585
84
}
1586
1587
static int
1588
local_traverse(PyObject *op, visitproc visit, void *arg)
1589
564
{
1590
564
    localobject *self = localobject_CAST(op);
1591
564
    Py_VISIT(Py_TYPE(self));
1592
564
    Py_VISIT(self->args);
1593
564
    Py_VISIT(self->kw);
1594
564
    Py_VISIT(self->localdicts);
1595
564
    Py_VISIT(self->thread_watchdogs);
1596
564
    return 0;
1597
564
}
1598
1599
static int
1600
local_clear(PyObject *op)
1601
4
{
1602
4
    localobject *self = localobject_CAST(op);
1603
4
    Py_CLEAR(self->args);
1604
4
    Py_CLEAR(self->kw);
1605
4
    Py_CLEAR(self->localdicts);
1606
4
    Py_CLEAR(self->thread_watchdogs);
1607
4
    return 0;
1608
4
}
1609
1610
static void
1611
local_dealloc(PyObject *op)
1612
4
{
1613
4
    localobject *self = localobject_CAST(op);
1614
    /* Weakrefs must be invalidated right now, otherwise they can be used
1615
       from code called below, which is very dangerous since Py_REFCNT(self) == 0 */
1616
4
    if (self->weakreflist != NULL) {
1617
0
        PyObject_ClearWeakRefs(op);
1618
0
    }
1619
4
    PyObject_GC_UnTrack(self);
1620
4
    (void)local_clear(op);
1621
4
    PyTypeObject *tp = Py_TYPE(self);
1622
4
    tp->tp_free(self);
1623
4
    Py_DECREF(tp);
1624
4
}
1625
1626
/* Create the TLS key and sentinel if they don't exist */
1627
static int
1628
create_localdummies(thread_module_state *state)
1629
8.46M
{
1630
8.46M
    PyThreadState *tstate = _PyThreadState_GET();
1631
1632
8.46M
    if (tstate->threading_local_key != NULL) {
1633
8.46M
        return 0;
1634
8.46M
    }
1635
1636
8
    PyTypeObject *ld_type = state->local_dummy_type;
1637
8
    tstate->threading_local_key = ld_type->tp_alloc(ld_type, 0);
1638
8
    if (tstate->threading_local_key == NULL) {
1639
0
        return -1;
1640
0
    }
1641
1642
8
    tstate->threading_local_sentinel = ld_type->tp_alloc(ld_type, 0);
1643
8
    if (tstate->threading_local_sentinel == NULL) {
1644
0
        Py_CLEAR(tstate->threading_local_key);
1645
0
        return -1;
1646
0
    }
1647
1648
8
    return 0;
1649
8
}
1650
1651
/* Insert a localsdict and sentinel weakref for the current thread, placing
1652
   strong references in localsdict and sentinel_wr, respectively.
1653
*/
1654
static int
1655
create_localsdict(localobject *self, thread_module_state *state,
1656
                  PyObject **localsdict, PyObject **sentinel_wr)
1657
84
{
1658
84
    PyThreadState *tstate = _PyThreadState_GET();
1659
84
    PyObject *ldict = NULL;
1660
84
    PyObject *wr = NULL;
1661
1662
84
    if (create_localdummies(state) < 0) {
1663
0
        goto err;
1664
0
    }
1665
1666
    /* Create and insert the locals dict and sentinel weakref */
1667
84
    ldict = PyDict_New();
1668
84
    if (ldict == NULL) {
1669
0
        goto err;
1670
0
    }
1671
1672
84
    if (PyDict_SetItem(self->localdicts, tstate->threading_local_key,
1673
84
                       ldict) < 0)
1674
0
    {
1675
0
        goto err;
1676
0
    }
1677
1678
84
    wr = create_sentinel_wr(self);
1679
84
    if (wr == NULL) {
1680
0
        PyObject *exc = PyErr_GetRaisedException();
1681
0
        if (PyDict_DelItem(self->localdicts,
1682
0
                           tstate->threading_local_key) < 0)
1683
0
        {
1684
0
            PyErr_FormatUnraisable("Exception ignored while deleting "
1685
0
                                   "thread local of %R", self);
1686
0
        }
1687
0
        PyErr_SetRaisedException(exc);
1688
0
        goto err;
1689
0
    }
1690
1691
84
    if (PySet_Add(self->thread_watchdogs, wr) < 0) {
1692
0
        PyObject *exc = PyErr_GetRaisedException();
1693
0
        if (PyDict_DelItem(self->localdicts,
1694
0
                           tstate->threading_local_key) < 0)
1695
0
        {
1696
0
            PyErr_FormatUnraisable("Exception ignored while deleting "
1697
0
                                   "thread local of %R", self);
1698
0
        }
1699
0
        PyErr_SetRaisedException(exc);
1700
0
        goto err;
1701
0
    }
1702
1703
84
    *localsdict = ldict;
1704
84
    *sentinel_wr = wr;
1705
84
    return 0;
1706
1707
0
err:
1708
0
    Py_XDECREF(ldict);
1709
0
    Py_XDECREF(wr);
1710
0
    return -1;
1711
84
}
1712
1713
/* Return a strong reference to the locals dict for the current thread,
1714
   creating it if necessary.
1715
*/
1716
static PyObject *
1717
_ldict(localobject *self, thread_module_state *state)
1718
8.46M
{
1719
8.46M
    if (create_localdummies(state) < 0) {
1720
0
        return NULL;
1721
0
    }
1722
1723
    /* Check if a localsdict already exists */
1724
8.46M
    PyObject *ldict;
1725
8.46M
    PyThreadState *tstate = _PyThreadState_GET();
1726
8.46M
    if (PyDict_GetItemRef(self->localdicts, tstate->threading_local_key,
1727
8.46M
                          &ldict) < 0) {
1728
0
        return NULL;
1729
0
    }
1730
8.46M
    if (ldict != NULL) {
1731
8.46M
        return ldict;
1732
8.46M
    }
1733
1734
    /* threading.local hasn't been instantiated for this thread */
1735
0
    PyObject *wr;
1736
0
    if (create_localsdict(self, state, &ldict, &wr) < 0) {
1737
0
        return NULL;
1738
0
    }
1739
1740
    /* run __init__ if we're a subtype of `threading.local` */
1741
0
    if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init &&
1742
0
        Py_TYPE(self)->tp_init((PyObject *)self, self->args, self->kw) < 0) {
1743
        /* we need to get rid of ldict from thread so
1744
           we create a new one the next time we do an attr
1745
           access */
1746
0
        PyObject *exc = PyErr_GetRaisedException();
1747
0
        if (PyDict_DelItem(self->localdicts,
1748
0
                           tstate->threading_local_key) < 0)
1749
0
        {
1750
0
            PyErr_FormatUnraisable("Exception ignored while deleting "
1751
0
                                   "thread local of %R", self);
1752
0
            assert(!PyErr_Occurred());
1753
0
        }
1754
0
        if (PySet_Discard(self->thread_watchdogs, wr) < 0) {
1755
0
            PyErr_FormatUnraisable("Exception ignored while discarding "
1756
0
                                   "thread watchdog of %R", self);
1757
0
        }
1758
0
        PyErr_SetRaisedException(exc);
1759
0
        Py_DECREF(ldict);
1760
0
        Py_DECREF(wr);
1761
0
        return NULL;
1762
0
    }
1763
0
    Py_DECREF(wr);
1764
1765
0
    return ldict;
1766
0
}
1767
1768
static int
1769
local_setattro(PyObject *op, PyObject *name, PyObject *v)
1770
222k
{
1771
222k
    localobject *self = localobject_CAST(op);
1772
222k
    PyObject *module = PyType_GetModuleByDef(Py_TYPE(self), &thread_module);
1773
222k
    assert(module != NULL);
1774
222k
    thread_module_state *state = get_thread_state(module);
1775
1776
222k
    PyObject *ldict = _ldict(self, state);
1777
222k
    if (ldict == NULL) {
1778
0
        goto err;
1779
0
    }
1780
1781
222k
    int r = PyObject_RichCompareBool(name, &_Py_ID(__dict__), Py_EQ);
1782
222k
    if (r == -1) {
1783
0
        goto err;
1784
0
    }
1785
222k
    if (r == 1) {
1786
0
        PyErr_Format(PyExc_AttributeError,
1787
0
                     "'%.100s' object attribute %R is read-only",
1788
0
                     Py_TYPE(self)->tp_name, name);
1789
0
        goto err;
1790
0
    }
1791
1792
222k
    int st = _PyObject_GenericSetAttrWithDict(op, name, v, ldict);
1793
222k
    Py_DECREF(ldict);
1794
222k
    return st;
1795
1796
0
err:
1797
0
    Py_XDECREF(ldict);
1798
0
    return -1;
1799
222k
}
1800
1801
static PyObject *local_getattro(PyObject *, PyObject *);
1802
1803
static PyMemberDef local_type_members[] = {
1804
    {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(localobject, weakreflist), Py_READONLY},
1805
    {NULL},
1806
};
1807
1808
static PyType_Slot local_type_slots[] = {
1809
    {Py_tp_dealloc, local_dealloc},
1810
    {Py_tp_getattro, local_getattro},
1811
    {Py_tp_setattro, local_setattro},
1812
    {Py_tp_doc, "_local()\n--\n\nThread-local data"},
1813
    {Py_tp_traverse, local_traverse},
1814
    {Py_tp_clear, local_clear},
1815
    {Py_tp_new, local_new},
1816
    {Py_tp_members, local_type_members},
1817
    {0, 0}
1818
};
1819
1820
static PyType_Spec local_type_spec = {
1821
    .name = "_thread._local",
1822
    .basicsize = sizeof(localobject),
1823
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
1824
              Py_TPFLAGS_IMMUTABLETYPE),
1825
    .slots = local_type_slots,
1826
};
1827
1828
static PyObject *
1829
local_getattro(PyObject *op, PyObject *name)
1830
8.24M
{
1831
8.24M
    localobject *self = localobject_CAST(op);
1832
8.24M
    PyObject *module = PyType_GetModuleByDef(Py_TYPE(self), &thread_module);
1833
8.24M
    assert(module != NULL);
1834
8.24M
    thread_module_state *state = get_thread_state(module);
1835
1836
8.24M
    PyObject *ldict = _ldict(self, state);
1837
8.24M
    if (ldict == NULL)
1838
0
        return NULL;
1839
1840
8.24M
    int r = PyObject_RichCompareBool(name, &_Py_ID(__dict__), Py_EQ);
1841
8.24M
    if (r == 1) {
1842
0
        return ldict;
1843
0
    }
1844
8.24M
    if (r == -1) {
1845
0
        Py_DECREF(ldict);
1846
0
        return NULL;
1847
0
    }
1848
1849
8.24M
    if (!Py_IS_TYPE(self, state->local_type)) {
1850
        /* use generic lookup for subtypes */
1851
0
        PyObject *res = _PyObject_GenericGetAttrWithDict(op, name, ldict, 0);
1852
0
        Py_DECREF(ldict);
1853
0
        return res;
1854
0
    }
1855
1856
    /* Optimization: just look in dict ourselves */
1857
8.24M
    PyObject *value;
1858
8.24M
    if (PyDict_GetItemRef(ldict, name, &value) != 0) {
1859
        // found or error
1860
8.09M
        Py_DECREF(ldict);
1861
8.09M
        return value;
1862
8.09M
    }
1863
1864
    /* Fall back on generic to get __class__ and __dict__ */
1865
145k
    PyObject *res = _PyObject_GenericGetAttrWithDict(op, name, ldict, 0);
1866
145k
    Py_DECREF(ldict);
1867
145k
    return res;
1868
8.24M
}
1869
1870
/* Called when a dummy is destroyed, indicating that the owning thread is being
1871
 * cleared. */
1872
static PyObject *
1873
clear_locals(PyObject *locals_and_key, PyObject *dummyweakref)
1874
0
{
1875
0
    PyObject *localweakref = PyTuple_GetItem(locals_and_key, 0);
1876
0
    localobject *self = localobject_CAST(_PyWeakref_GET_REF(localweakref));
1877
0
    if (self == NULL) {
1878
0
        Py_RETURN_NONE;
1879
0
    }
1880
1881
    /* If the thread-local object is still alive and not being cleared,
1882
       remove the corresponding local dict */
1883
0
    if (self->localdicts != NULL) {
1884
0
        PyObject *key = PyTuple_GetItem(locals_and_key, 1);
1885
0
        if (PyDict_Pop(self->localdicts, key, NULL) < 0) {
1886
0
            PyErr_FormatUnraisable("Exception ignored while clearing "
1887
0
                                   "thread local %R", (PyObject *)self);
1888
0
        }
1889
0
    }
1890
0
    if (self->thread_watchdogs != NULL) {
1891
0
        if (PySet_Discard(self->thread_watchdogs, dummyweakref) < 0) {
1892
0
            PyErr_FormatUnraisable("Exception ignored while clearing "
1893
0
                                   "thread local %R", (PyObject *)self);
1894
0
        }
1895
0
    }
1896
1897
0
    Py_DECREF(self);
1898
0
    Py_RETURN_NONE;
1899
0
}
1900
1901
/* Module functions */
1902
1903
/*[clinic input]
1904
_thread.daemon_threads_allowed
1905
1906
Return True if daemon threads are allowed in the current interpreter.
1907
1908
Return False otherwise.
1909
[clinic start generated code]*/
1910
1911
static PyObject *
1912
_thread_daemon_threads_allowed_impl(PyObject *module)
1913
/*[clinic end generated code: output=c82b3b9490c7e11e input=f94150f9e14b7d0c]*/
1914
0
{
1915
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
1916
0
    if (interp->feature_flags & Py_RTFLAGS_DAEMON_THREADS) {
1917
0
        Py_RETURN_TRUE;
1918
0
    }
1919
0
    else {
1920
0
        Py_RETURN_FALSE;
1921
0
    }
1922
0
}
1923
1924
static int
1925
do_start_new_thread(thread_module_state *state, PyObject *func, PyObject *args,
1926
                    PyObject *kwargs, ThreadHandle *handle, int daemon)
1927
0
{
1928
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
1929
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_THREADS)) {
1930
0
        PyErr_SetString(PyExc_RuntimeError,
1931
0
                        "thread is not supported for isolated subinterpreters");
1932
0
        return -1;
1933
0
    }
1934
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
1935
0
        PyErr_SetString(PyExc_PythonFinalizationError,
1936
0
                        "can't create new thread at interpreter shutdown");
1937
0
        return -1;
1938
0
    }
1939
1940
0
    if (!daemon) {
1941
        // Add the handle before starting the thread to avoid adding a handle
1942
        // to a thread that has already finished (i.e. if the thread finishes
1943
        // before the call to `ThreadHandle_start()` below returns).
1944
0
        add_to_shutdown_handles(state, handle);
1945
0
    }
1946
1947
0
    if (ThreadHandle_start(handle, func, args, kwargs, daemon) < 0) {
1948
0
        if (!daemon) {
1949
0
            remove_from_shutdown_handles(handle);
1950
0
        }
1951
0
        return -1;
1952
0
    }
1953
1954
0
    return 0;
1955
0
}
1956
1957
/*[clinic input]
1958
_thread.start_new_thread
1959
1960
    function as func: object
1961
    args: object(subclass_of='&PyTuple_Type')
1962
    kwargs: object(subclass_of='&PyDict_Type', c_default="NULL") = {}
1963
    /
1964
1965
Start a new thread and return its identifier.
1966
1967
The thread will call the function with positional arguments from the
1968
tuple args and keyword arguments taken from the optional dictionary
1969
kwargs.  The thread exits when the function returns; the return value
1970
is ignored.  The thread will also exit when the function raises an
1971
unhandled exception; a stack trace will be printed unless the exception
1972
is SystemExit.
1973
[clinic start generated code]*/
1974
1975
static PyObject *
1976
_thread_start_new_thread_impl(PyObject *module, PyObject *func,
1977
                              PyObject *args, PyObject *kwargs)
1978
/*[clinic end generated code: output=0c27eb61b7a7152b input=b85f6b3301d30719]*/
1979
0
{
1980
0
    thread_module_state *state = get_thread_state(module);
1981
1982
0
    if (!PyCallable_Check(func)) {
1983
0
        PyErr_SetString(PyExc_TypeError,
1984
0
                        "first arg must be callable");
1985
0
        return NULL;
1986
0
    }
1987
0
    if (PySys_Audit("_thread.start_new_thread", "OOO",
1988
0
                    func, args, kwargs ? kwargs : Py_None) < 0) {
1989
0
        return NULL;
1990
0
    }
1991
1992
0
    ThreadHandle *handle = ThreadHandle_new();
1993
0
    if (handle == NULL) {
1994
0
        return NULL;
1995
0
    }
1996
1997
0
    int st =
1998
0
        do_start_new_thread(state, func, args, kwargs, handle, /*daemon=*/1);
1999
0
    if (st < 0) {
2000
0
        ThreadHandle_decref(handle);
2001
0
        return NULL;
2002
0
    }
2003
0
    PyThread_ident_t ident = ThreadHandle_ident(handle);
2004
0
    ThreadHandle_decref(handle);
2005
0
    return PyLong_FromUnsignedLongLong(ident);
2006
0
}
2007
2008
PyDoc_STRVAR(start_new_doc,
2009
"start_new($module, function, args, kwargs={}, /)\n\
2010
--\n\
2011
\n\
2012
An obsolete synonym of start_new_thread().");
2013
2014
/*[clinic input]
2015
_thread.start_joinable_thread
2016
2017
    function as func: object
2018
    handle as hobj: object = None
2019
    daemon: bool = True
2020
2021
*For internal use only*: start a new thread.
2022
2023
Like start_new_thread(), this starts a new thread calling the given
2024
function.  Unlike start_new_thread(), this returns a handle object with
2025
methods to join or detach the given thread.
2026
This function is not for third-party code, please use the `threading`
2027
module instead.  During finalization the runtime will not wait for the
2028
thread to exit if daemon is True.  If handle is provided it must be a
2029
newly created thread._ThreadHandle instance.
2030
[clinic start generated code]*/
2031
2032
static PyObject *
2033
_thread_start_joinable_thread_impl(PyObject *module, PyObject *func,
2034
                                   PyObject *hobj, int daemon)
2035
/*[clinic end generated code: output=58691769e60620cf input=e17b3aebc087952a]*/
2036
0
{
2037
0
    thread_module_state *state = get_thread_state(module);
2038
2039
0
    if (!PyCallable_Check(func)) {
2040
0
        PyErr_SetString(PyExc_TypeError,
2041
0
                        "thread function must be callable");
2042
0
        return NULL;
2043
0
    }
2044
2045
0
    if (hobj != Py_None && !Py_IS_TYPE(hobj, state->thread_handle_type)) {
2046
0
        PyErr_SetString(PyExc_TypeError, "'handle' must be a _ThreadHandle");
2047
0
        return NULL;
2048
0
    }
2049
2050
0
    if (PySys_Audit("_thread.start_joinable_thread", "OiO", func, daemon,
2051
0
                    hobj) < 0) {
2052
0
        return NULL;
2053
0
    }
2054
2055
0
    if (hobj == Py_None) {
2056
0
        hobj = (PyObject *)PyThreadHandleObject_new(state->thread_handle_type);
2057
0
        if (hobj == NULL) {
2058
0
            return NULL;
2059
0
        }
2060
0
    }
2061
0
    else {
2062
0
        Py_INCREF(hobj);
2063
0
    }
2064
2065
0
    PyObject* args = PyTuple_New(0);
2066
0
    if (args == NULL) {
2067
0
        return NULL;
2068
0
    }
2069
0
    int st = do_start_new_thread(state, func, args,
2070
0
                                 /*kwargs=*/ NULL, ((PyThreadHandleObject*)hobj)->handle, daemon);
2071
0
    Py_DECREF(args);
2072
0
    if (st < 0) {
2073
0
        Py_DECREF(hobj);
2074
0
        return NULL;
2075
0
    }
2076
0
    return (PyObject *) hobj;
2077
0
}
2078
2079
/*[clinic input]
2080
_thread.exit
2081
2082
Raise SystemExit.
2083
2084
It will cause the current thread to exit silently unless the exception
2085
is caught.
2086
[clinic start generated code]*/
2087
2088
static PyObject *
2089
_thread_exit_impl(PyObject *module)
2090
/*[clinic end generated code: output=b03924346e743f4c input=1f3dc5da8ad48c70]*/
2091
0
{
2092
0
    PyErr_SetNone(PyExc_SystemExit);
2093
0
    return NULL;
2094
0
}
2095
2096
PyDoc_STRVAR(exit_thread_doc,
2097
"exit_thread($module, /)\n\
2098
--\n\
2099
\n\
2100
An obsolete synonym of exit().");
2101
2102
/*[clinic input]
2103
_thread.interrupt_main
2104
2105
    signum: int(c_default="SIGINT") = signal.SIGINT
2106
    /
2107
2108
Simulate the arrival of the given signal in the main thread.
2109
2110
The corresponding signal handler will be executed.
2111
If *signum* is omitted, SIGINT is assumed.
2112
A subthread can use this function to interrupt the main thread.
2113
2114
Note: the default signal handler for SIGINT raises
2115
``KeyboardInterrupt``.
2116
[clinic start generated code]*/
2117
2118
static PyObject *
2119
_thread_interrupt_main_impl(PyObject *module, int signum)
2120
/*[clinic end generated code: output=fdafa7261ceb26e9 input=a8cf392f3a7f2a84]*/
2121
0
{
2122
0
    if (PyErr_SetInterruptEx(signum)) {
2123
0
        PyErr_SetString(PyExc_ValueError, "signal number out of range");
2124
0
        return NULL;
2125
0
    }
2126
0
    Py_RETURN_NONE;
2127
0
}
2128
2129
/*[clinic input]
2130
_thread.allocate_lock
2131
2132
Create a new lock object.
2133
2134
See help(type(threading.Lock())) for information about locks.
2135
[clinic start generated code]*/
2136
2137
static PyObject *
2138
_thread_allocate_lock_impl(PyObject *module)
2139
/*[clinic end generated code: output=884a4be6cb9ca731 input=49f5b1f966361bb6]*/
2140
11.8k
{
2141
11.8k
    thread_module_state *state = get_thread_state(module);
2142
11.8k
    return lock_new_impl(state->lock_type);
2143
11.8k
}
2144
2145
PyDoc_STRVAR(allocate_doc,
2146
"allocate($module, /)\n\
2147
--\n\
2148
\n\
2149
An obsolete synonym of allocate_lock().");
2150
2151
/*[clinic input]
2152
_thread.get_ident
2153
2154
Return a non-zero integer that uniquely identifies the current thread.
2155
2156
It is unique amongst other threads that exist simultaneously.
2157
This may be used to identify per-thread resources.
2158
Even though on some platforms threads identities may appear to be
2159
allocated consecutive numbers starting at 1, this behavior should not
2160
be relied upon, and the number should be seen purely as a magic cookie.
2161
A thread's identity may be reused for another thread after it exits.
2162
[clinic start generated code]*/
2163
2164
static PyObject *
2165
_thread_get_ident_impl(PyObject *module)
2166
/*[clinic end generated code: output=8c3f9d8aa938b332 input=08faef37d1fd9e67]*/
2167
329k
{
2168
329k
    PyThread_ident_t ident = PyThread_get_thread_ident_ex();
2169
329k
    if (ident == PYTHREAD_INVALID_THREAD_ID) {
2170
0
        PyErr_SetString(ThreadError, "no current thread ident");
2171
0
        return NULL;
2172
0
    }
2173
329k
    return PyLong_FromUnsignedLongLong(ident);
2174
329k
}
2175
2176
#ifdef PY_HAVE_THREAD_NATIVE_ID
2177
/*[clinic input]
2178
_thread.get_native_id
2179
2180
Return a non-negative integer identifying the thread.
2181
2182
It is reported by the OS (kernel).  This may be used to uniquely
2183
identify a particular thread within a system.
2184
[clinic start generated code]*/
2185
2186
static PyObject *
2187
_thread_get_native_id_impl(PyObject *module)
2188
/*[clinic end generated code: output=d69767224b4ba922 input=454af91013e4f747]*/
2189
8
{
2190
8
    unsigned long native_id = PyThread_get_thread_native_id();
2191
8
    return PyLong_FromUnsignedLong(native_id);
2192
8
}
2193
2194
#endif
2195
2196
/*[clinic input]
2197
_thread._count
2198
2199
Return the number of currently running Python threads.
2200
2201
The main thread is excluded.  The returned number comprises all threads
2202
created through `start_new_thread()` as well as `threading.Thread`, and
2203
not yet finished.
2204
2205
This function is meant for internal and specialized purposes only.
2206
In most applications `threading.enumerate()` should be used instead.
2207
[clinic start generated code]*/
2208
2209
static PyObject *
2210
_thread__count_impl(PyObject *module)
2211
/*[clinic end generated code: output=4cd03377c3e8521d input=bbd340043d174d48]*/
2212
0
{
2213
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
2214
0
    return PyLong_FromSsize_t(_Py_atomic_load_ssize(&interp->threads.count));
2215
0
}
2216
2217
/*[clinic input]
2218
_thread.stack_size
2219
2220
    size as new_size: Py_ssize_t = 0
2221
    /
2222
2223
Return the thread stack size used when creating new threads.
2224
2225
The optional size argument specifies the stack size (in bytes) to be
2226
used for subsequently created threads, and must be 0 (use platform or
2227
configured default) or a positive integer value of at least 32,768 (32
2228
KiB).  If changing the thread stack size is unsupported, a ThreadError
2229
exception is raised.  If the specified size is invalid, a ValueError
2230
exception is raised, and the stack size is unmodified.  32 KiB
2231
currently is the minimum supported stack size value to guarantee
2232
sufficient stack space for the interpreter itself.
2233
2234
Note that some systems may have particular restrictions on values for
2235
the stack size, such as requiring a minimum stack size larger than 32
2236
KiB or requiring allocation in multiples of the system memory page size
2237
- platform documentation should be referred to for more information
2238
(4 KiB pages are common; using multiples of 4096 for the stack size is
2239
the suggested approach in the absence of more specific information).
2240
[clinic start generated code]*/
2241
2242
static PyObject *
2243
_thread_stack_size_impl(PyObject *module, Py_ssize_t new_size)
2244
/*[clinic end generated code: output=cc7ba71bd35afc30 input=3249feb8ed2350f8]*/
2245
0
{
2246
0
    size_t old_size;
2247
0
    int rc;
2248
2249
0
    Py_ssize_t min_size = _PyOS_MIN_STACK_SIZE + SYSTEM_PAGE_SIZE;
2250
0
    if (new_size != 0 && new_size < min_size) {
2251
0
        PyErr_Format(PyExc_ValueError,
2252
0
                     "size must be at least %zi bytes", min_size);
2253
0
        return NULL;
2254
0
    }
2255
2256
0
    old_size = PyThread_get_stacksize();
2257
2258
0
    rc = PyThread_set_stacksize((size_t) new_size);
2259
0
    if (rc == -1) {
2260
0
        PyErr_Format(PyExc_ValueError,
2261
0
                     "size not valid: %zd bytes",
2262
0
                     new_size);
2263
0
        return NULL;
2264
0
    }
2265
0
    if (rc == -2) {
2266
0
        PyErr_SetString(ThreadError,
2267
0
                        "setting stack size not supported");
2268
0
        return NULL;
2269
0
    }
2270
2271
0
    return PyLong_FromSsize_t((Py_ssize_t) old_size);
2272
0
}
2273
2274
static int
2275
thread_excepthook_file(PyObject *file, PyObject *exc_type, PyObject *exc_value,
2276
                       PyObject *exc_traceback, PyObject *thread)
2277
0
{
2278
    /* print(f"Exception in thread {thread.name}:", file=file) */
2279
0
    if (PyFile_WriteString("Exception in thread ", file) < 0) {
2280
0
        return -1;
2281
0
    }
2282
2283
0
    PyObject *name = NULL;
2284
0
    if (thread != Py_None) {
2285
0
        if (PyObject_GetOptionalAttr(thread, &_Py_ID(name), &name) < 0) {
2286
0
            return -1;
2287
0
        }
2288
0
    }
2289
0
    if (name != NULL) {
2290
0
        if (PyFile_WriteObject(name, file, Py_PRINT_RAW) < 0) {
2291
0
            Py_DECREF(name);
2292
0
            return -1;
2293
0
        }
2294
0
        Py_DECREF(name);
2295
0
    }
2296
0
    else {
2297
0
        PyThread_ident_t ident = PyThread_get_thread_ident_ex();
2298
0
        PyObject *str = PyUnicode_FromFormat("%" PY_FORMAT_THREAD_IDENT_T, ident);
2299
0
        if (str != NULL) {
2300
0
            if (PyFile_WriteObject(str, file, Py_PRINT_RAW) < 0) {
2301
0
                Py_DECREF(str);
2302
0
                return -1;
2303
0
            }
2304
0
            Py_DECREF(str);
2305
0
        }
2306
0
        else {
2307
0
            PyErr_Clear();
2308
2309
0
            if (PyFile_WriteString("<failed to get thread name>", file) < 0) {
2310
0
                return -1;
2311
0
            }
2312
0
        }
2313
0
    }
2314
2315
0
    if (PyFile_WriteString(":\n", file) < 0) {
2316
0
        return -1;
2317
0
    }
2318
2319
    /* Display the traceback */
2320
0
    _PyErr_Display(file, exc_type, exc_value, exc_traceback);
2321
2322
    /* Call file.flush() */
2323
0
    if (_PyFile_Flush(file) < 0) {
2324
0
        return -1;
2325
0
    }
2326
2327
0
    return 0;
2328
0
}
2329
2330
2331
PyDoc_STRVAR(ExceptHookArgs__doc__,
2332
"ExceptHookArgs\n\
2333
\n\
2334
Type used to pass arguments to threading.excepthook.");
2335
2336
static PyStructSequence_Field ExceptHookArgs_fields[] = {
2337
    {"exc_type", "Exception type"},
2338
    {"exc_value", "Exception value"},
2339
    {"exc_traceback", "Exception traceback"},
2340
    {"thread", "Thread"},
2341
    {0}
2342
};
2343
2344
static PyStructSequence_Desc ExceptHookArgs_desc = {
2345
    .name = "_thread._ExceptHookArgs",
2346
    .doc = ExceptHookArgs__doc__,
2347
    .fields = ExceptHookArgs_fields,
2348
    .n_in_sequence = 4
2349
};
2350
2351
2352
/*[clinic input]
2353
_thread._excepthook
2354
2355
    args: object
2356
    /
2357
2358
Handle uncaught Thread.run() exception.
2359
[clinic start generated code]*/
2360
2361
static PyObject *
2362
_thread__excepthook(PyObject *module, PyObject *args)
2363
/*[clinic end generated code: output=cadc54a3be0e6007 input=5ae2316c400a3497]*/
2364
0
{
2365
0
    thread_module_state *state = get_thread_state(module);
2366
2367
0
    if (!Py_IS_TYPE(args, state->excepthook_type)) {
2368
0
        PyErr_SetString(PyExc_TypeError,
2369
0
                        "_thread.excepthook argument type "
2370
0
                        "must be ExceptHookArgs");
2371
0
        return NULL;
2372
0
    }
2373
2374
    /* Borrowed reference */
2375
0
    PyObject *exc_type = PyStructSequence_GET_ITEM(args, 0);
2376
0
    if (exc_type == PyExc_SystemExit) {
2377
        /* silently ignore SystemExit */
2378
0
        Py_RETURN_NONE;
2379
0
    }
2380
2381
    /* Borrowed references */
2382
0
    PyObject *exc_value = PyStructSequence_GET_ITEM(args, 1);
2383
0
    PyObject *exc_tb = PyStructSequence_GET_ITEM(args, 2);
2384
0
    PyObject *thread = PyStructSequence_GET_ITEM(args, 3);
2385
2386
0
    PyObject *file;
2387
0
    if (PySys_GetOptionalAttr( &_Py_ID(stderr), &file) < 0) {
2388
0
        return NULL;
2389
0
    }
2390
0
    if (file == NULL || file == Py_None) {
2391
0
        Py_XDECREF(file);
2392
0
        if (thread == Py_None) {
2393
            /* do nothing if sys.stderr is None and thread is None */
2394
0
            Py_RETURN_NONE;
2395
0
        }
2396
2397
0
        file = PyObject_GetAttrString(thread, "_stderr");
2398
0
        if (file == NULL) {
2399
0
            return NULL;
2400
0
        }
2401
0
        if (file == Py_None) {
2402
0
            Py_DECREF(file);
2403
            /* do nothing if sys.stderr is None and sys.stderr was None
2404
               when the thread was created */
2405
0
            Py_RETURN_NONE;
2406
0
        }
2407
0
    }
2408
2409
0
    int res = thread_excepthook_file(file, exc_type, exc_value, exc_tb,
2410
0
                                     thread);
2411
0
    Py_DECREF(file);
2412
0
    if (res < 0) {
2413
0
        return NULL;
2414
0
    }
2415
2416
0
    Py_RETURN_NONE;
2417
0
}
2418
2419
/*[clinic input]
2420
_thread._is_main_interpreter
2421
2422
Return True if the current interpreter is the main Python interpreter.
2423
[clinic start generated code]*/
2424
2425
static PyObject *
2426
_thread__is_main_interpreter_impl(PyObject *module)
2427
/*[clinic end generated code: output=7dd82e1728339adc input=cc1eb00fd4598915]*/
2428
0
{
2429
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
2430
0
    return PyBool_FromLong(_Py_IsMainInterpreter(interp));
2431
0
}
2432
2433
/*[clinic input]
2434
_thread._shutdown
2435
2436
Wait for all non-daemon threads (other than the calling thread) to stop.
2437
[clinic start generated code]*/
2438
2439
static PyObject *
2440
_thread__shutdown_impl(PyObject *module)
2441
/*[clinic end generated code: output=a19afe92bddc1824 input=bcaeaceb3a6fa590]*/
2442
0
{
2443
0
    PyThread_ident_t ident = PyThread_get_thread_ident_ex();
2444
0
    thread_module_state *state = get_thread_state(module);
2445
2446
0
    for (;;) {
2447
0
        ThreadHandle *handle = NULL;
2448
2449
        // Find a thread that's not yet finished.
2450
0
        HEAD_LOCK(&_PyRuntime);
2451
0
        struct llist_node *node;
2452
0
        llist_for_each_safe(node, &state->shutdown_handles) {
2453
0
            ThreadHandle *cur = llist_data(node, ThreadHandle, shutdown_node);
2454
0
            if (ThreadHandle_ident(cur) != ident) {
2455
0
                ThreadHandle_incref(cur);
2456
0
                handle = cur;
2457
0
                break;
2458
0
            }
2459
0
        }
2460
0
        HEAD_UNLOCK(&_PyRuntime);
2461
2462
0
        if (!handle) {
2463
            // No more threads to wait on!
2464
0
            break;
2465
0
        }
2466
2467
        // Wait for the thread to finish. If we're interrupted, such
2468
        // as by a ctrl-c we print the error and exit early.
2469
0
        if (ThreadHandle_join(handle, -1) < 0) {
2470
0
            ThreadHandle_decref(handle);
2471
0
            return NULL;
2472
0
        }
2473
2474
0
        ThreadHandle_decref(handle);
2475
0
    }
2476
2477
0
    Py_RETURN_NONE;
2478
0
}
2479
2480
/*[clinic input]
2481
_thread._make_thread_handle
2482
2483
    ident as identobj: object
2484
    /
2485
2486
Internal only.
2487
2488
Make a thread handle for threads not spawned by the _thread or
2489
threading module.
2490
[clinic start generated code]*/
2491
2492
static PyObject *
2493
_thread__make_thread_handle(PyObject *module, PyObject *identobj)
2494
/*[clinic end generated code: output=afa56c40a7e1c394 input=57bb20ebf5825dd1]*/
2495
8
{
2496
8
    thread_module_state *state = get_thread_state(module);
2497
8
    if (!PyLong_Check(identobj)) {
2498
0
        PyErr_SetString(PyExc_TypeError, "ident must be an integer");
2499
0
        return NULL;
2500
0
    }
2501
8
    PyThread_ident_t ident = PyLong_AsUnsignedLongLong(identobj);
2502
8
    if (PyErr_Occurred()) {
2503
0
        return NULL;
2504
0
    }
2505
8
    PyThreadHandleObject *hobj =
2506
8
        PyThreadHandleObject_new(state->thread_handle_type);
2507
8
    if (hobj == NULL) {
2508
0
        return NULL;
2509
0
    }
2510
8
    PyMutex_Lock(&hobj->handle->mutex);
2511
8
    hobj->handle->ident = ident;
2512
8
    hobj->handle->state = THREAD_HANDLE_RUNNING;
2513
8
    PyMutex_Unlock(&hobj->handle->mutex);
2514
8
    return (PyObject*) hobj;
2515
8
}
2516
2517
/*[clinic input]
2518
_thread._get_main_thread_ident
2519
2520
Internal only.
2521
2522
Return a non-zero integer that uniquely identifies the main thread of
2523
the main interpreter.
2524
[clinic start generated code]*/
2525
2526
static PyObject *
2527
_thread__get_main_thread_ident_impl(PyObject *module)
2528
/*[clinic end generated code: output=01aa07c5553458bf input=feea25c7039ba4b5]*/
2529
8
{
2530
8
    return PyLong_FromUnsignedLongLong(_PyRuntime.main_thread);
2531
8
}
2532
2533
#if defined(__OpenBSD__)
2534
    /* pthread_*_np functions, especially pthread_{get,set}_name_np().
2535
       pthread_np.h exists on both OpenBSD and FreeBSD but the latter declares
2536
       pthread_getname_np() and pthread_setname_np() in pthread.h as long as
2537
       __BSD_VISIBLE remains set.
2538
     */
2539
#   include <pthread_np.h>
2540
#endif
2541
2542
#if defined(HAVE_PTHREAD_GETNAME_NP) || defined(HAVE_PTHREAD_GET_NAME_NP) || defined(MS_WINDOWS)
2543
/*[clinic input]
2544
_thread._get_name
2545
2546
Get the name of the current thread.
2547
[clinic start generated code]*/
2548
2549
static PyObject *
2550
_thread__get_name_impl(PyObject *module)
2551
/*[clinic end generated code: output=20026e7ee3da3dd7 input=35cec676833d04c8]*/
2552
0
{
2553
0
#ifndef MS_WINDOWS
2554
    // Linux and macOS are limited to respectively 16 and 64 bytes
2555
0
    char name[100];
2556
0
    pthread_t thread = pthread_self();
2557
0
#ifdef HAVE_PTHREAD_GETNAME_NP
2558
0
    int rc = pthread_getname_np(thread, name, Py_ARRAY_LENGTH(name));
2559
#else /* defined(HAVE_PTHREAD_GET_NAME_NP) */
2560
    int rc = 0; /* pthread_get_name_np() returns void */
2561
    pthread_get_name_np(thread, name, Py_ARRAY_LENGTH(name));
2562
#endif
2563
0
    if (rc) {
2564
0
        errno = rc;
2565
0
        return PyErr_SetFromErrno(PyExc_OSError);
2566
0
    }
2567
2568
#ifdef __sun
2569
    // gh-138004: Decode Solaris/Illumos (e.g. OpenIndiana) thread names
2570
    // from ASCII, since OpenIndiana only supports ASCII names.
2571
    return PyUnicode_DecodeASCII(name, strlen(name), "surrogateescape");
2572
#else
2573
0
    return PyUnicode_DecodeFSDefault(name);
2574
0
#endif
2575
#else
2576
    // Windows implementation
2577
    assert(pGetThreadDescription != NULL);
2578
2579
    wchar_t *name;
2580
    HRESULT hr = pGetThreadDescription(GetCurrentThread(), &name);
2581
    if (FAILED(hr)) {
2582
        PyErr_SetFromWindowsErr(0);
2583
        return NULL;
2584
    }
2585
2586
    PyObject *name_obj = PyUnicode_FromWideChar(name, -1);
2587
    LocalFree(name);
2588
    return name_obj;
2589
#endif
2590
0
}
2591
#endif  // HAVE_PTHREAD_GETNAME_NP || HAVE_PTHREAD_GET_NAME_NP || MS_WINDOWS
2592
2593
2594
#if defined(HAVE_PTHREAD_SETNAME_NP) || defined(HAVE_PTHREAD_SET_NAME_NP) || defined(MS_WINDOWS)
2595
/*[clinic input]
2596
_thread.set_name
2597
2598
    name as name_obj: unicode
2599
2600
Set the name of the current thread.
2601
[clinic start generated code]*/
2602
2603
static PyObject *
2604
_thread_set_name_impl(PyObject *module, PyObject *name_obj)
2605
/*[clinic end generated code: output=402b0c68e0c0daed input=7e7acd98261be82f]*/
2606
0
{
2607
0
#ifndef MS_WINDOWS
2608
#ifdef __sun
2609
    // gh-138004: Encode Solaris/Illumos thread names to ASCII,
2610
    // since OpenIndiana does not support non-ASCII names.
2611
    const char *encoding = "ascii";
2612
#else
2613
    // Encode the thread name to the filesystem encoding using the "replace"
2614
    // error handler
2615
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
2616
0
    const char *encoding = interp->unicode.fs_codec.encoding;
2617
0
#endif
2618
0
    PyObject *name_encoded;
2619
0
    name_encoded = PyUnicode_AsEncodedString(name_obj, encoding, "replace");
2620
0
    if (name_encoded == NULL) {
2621
0
        return NULL;
2622
0
    }
2623
2624
0
#ifdef _PYTHREAD_NAME_MAXLEN
2625
    // Truncate to _PYTHREAD_NAME_MAXLEN bytes + the NUL byte if needed
2626
0
    if (PyBytes_GET_SIZE(name_encoded) > _PYTHREAD_NAME_MAXLEN) {
2627
0
        PyObject *truncated;
2628
0
        truncated = PyBytes_FromStringAndSize(PyBytes_AS_STRING(name_encoded),
2629
0
                                              _PYTHREAD_NAME_MAXLEN);
2630
0
        if (truncated == NULL) {
2631
0
            Py_DECREF(name_encoded);
2632
0
            return NULL;
2633
0
        }
2634
0
        Py_SETREF(name_encoded, truncated);
2635
0
    }
2636
0
#endif
2637
2638
0
    const char *name = PyBytes_AS_STRING(name_encoded);
2639
#ifdef __APPLE__
2640
    int rc = pthread_setname_np(name);
2641
#elif defined(__NetBSD__)
2642
    pthread_t thread = pthread_self();
2643
    int rc = pthread_setname_np(thread, "%s", (void *)name);
2644
#elif defined(HAVE_PTHREAD_SETNAME_NP)
2645
    pthread_t thread = pthread_self();
2646
0
    int rc = pthread_setname_np(thread, name);
2647
#else /* defined(HAVE_PTHREAD_SET_NAME_NP) */
2648
    pthread_t thread = pthread_self();
2649
    int rc = 0; /* pthread_set_name_np() returns void */
2650
    pthread_set_name_np(thread, name);
2651
#endif
2652
0
    Py_DECREF(name_encoded);
2653
0
    if (rc) {
2654
0
        errno = rc;
2655
0
        return PyErr_SetFromErrno(PyExc_OSError);
2656
0
    }
2657
0
    Py_RETURN_NONE;
2658
#else
2659
    // Windows implementation
2660
    assert(pSetThreadDescription != NULL);
2661
2662
    Py_ssize_t len;
2663
    wchar_t *name = PyUnicode_AsWideCharString(name_obj, &len);
2664
    if (name == NULL) {
2665
        return NULL;
2666
    }
2667
2668
    if (len > _PYTHREAD_NAME_MAXLEN) {
2669
        // Truncate the name
2670
        Py_UCS4 ch = name[_PYTHREAD_NAME_MAXLEN-1];
2671
        if (Py_UNICODE_IS_HIGH_SURROGATE(ch)) {
2672
            name[_PYTHREAD_NAME_MAXLEN-1] = 0;
2673
        }
2674
        else {
2675
            name[_PYTHREAD_NAME_MAXLEN] = 0;
2676
        }
2677
    }
2678
2679
    HRESULT hr = pSetThreadDescription(GetCurrentThread(), name);
2680
    PyMem_Free(name);
2681
    if (FAILED(hr)) {
2682
        PyErr_SetFromWindowsErr((int)hr);
2683
        return NULL;
2684
    }
2685
    Py_RETURN_NONE;
2686
#endif
2687
0
}
2688
#endif  // HAVE_PTHREAD_SETNAME_NP || HAVE_PTHREAD_SET_NAME_NP || MS_WINDOWS
2689
2690
2691
static PyMethodDef thread_methods[] = {
2692
    _THREAD_START_NEW_THREAD_METHODDEF
2693
    {"start_new",               _PyCFunction_CAST(_thread_start_new_thread),
2694
     METH_FASTCALL, start_new_doc},
2695
    _THREAD_START_JOINABLE_THREAD_METHODDEF
2696
    _THREAD_DAEMON_THREADS_ALLOWED_METHODDEF
2697
    _THREAD_ALLOCATE_LOCK_METHODDEF
2698
    {"allocate",                _thread_allocate_lock,
2699
     METH_NOARGS, allocate_doc},
2700
    {"exit_thread",             _thread_exit,
2701
     METH_NOARGS, exit_thread_doc},
2702
    _THREAD_EXIT_METHODDEF
2703
    _THREAD_INTERRUPT_MAIN_METHODDEF
2704
    _THREAD_GET_IDENT_METHODDEF
2705
#ifdef PY_HAVE_THREAD_NATIVE_ID
2706
    _THREAD_GET_NATIVE_ID_METHODDEF
2707
#endif
2708
    _THREAD__COUNT_METHODDEF
2709
    _THREAD_STACK_SIZE_METHODDEF
2710
    _THREAD__EXCEPTHOOK_METHODDEF
2711
    _THREAD__IS_MAIN_INTERPRETER_METHODDEF
2712
    _THREAD__SHUTDOWN_METHODDEF
2713
    _THREAD__MAKE_THREAD_HANDLE_METHODDEF
2714
    _THREAD__GET_MAIN_THREAD_IDENT_METHODDEF
2715
    _THREAD_SET_NAME_METHODDEF
2716
    _THREAD__GET_NAME_METHODDEF
2717
    {NULL,                      NULL}           /* sentinel */
2718
};
2719
2720
2721
/* Initialization function */
2722
2723
static int
2724
thread_module_exec(PyObject *module)
2725
37
{
2726
37
    thread_module_state *state = get_thread_state(module);
2727
37
    PyObject *d = PyModule_GetDict(module);
2728
2729
    // Initialize the C thread library
2730
37
    PyThread_init_thread();
2731
2732
    // _ThreadHandle
2733
37
    state->thread_handle_type = (PyTypeObject *)PyType_FromSpec(&ThreadHandle_Type_spec);
2734
37
    if (state->thread_handle_type == NULL) {
2735
0
        return -1;
2736
0
    }
2737
37
    if (PyDict_SetItemString(d, "_ThreadHandle", (PyObject *)state->thread_handle_type) < 0) {
2738
0
        return -1;
2739
0
    }
2740
2741
    // Lock
2742
37
    state->lock_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, &lock_type_spec, NULL);
2743
37
    if (state->lock_type == NULL) {
2744
0
        return -1;
2745
0
    }
2746
37
    if (PyModule_AddType(module, state->lock_type) < 0) {
2747
0
        return -1;
2748
0
    }
2749
    // Old alias: lock -> LockType
2750
37
    if (PyDict_SetItemString(d, "LockType", (PyObject *)state->lock_type) < 0) {
2751
0
        return -1;
2752
0
    }
2753
2754
    // RLock
2755
37
    state->rlock_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, &rlock_type_spec, NULL);
2756
37
    if (state->rlock_type == NULL) {
2757
0
        return -1;
2758
0
    }
2759
37
    if (PyModule_AddType(module, state->rlock_type) < 0) {
2760
0
        return -1;
2761
0
    }
2762
2763
    // Local dummy
2764
37
    state->local_dummy_type = (PyTypeObject *)PyType_FromSpec(&local_dummy_type_spec);
2765
37
    if (state->local_dummy_type == NULL) {
2766
0
        return -1;
2767
0
    }
2768
2769
    // Local
2770
37
    state->local_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, &local_type_spec, NULL);
2771
37
    if (state->local_type == NULL) {
2772
0
        return -1;
2773
0
    }
2774
37
    if (PyModule_AddType(module, state->local_type) < 0) {
2775
0
        return -1;
2776
0
    }
2777
2778
    // Add module attributes
2779
37
    if (PyDict_SetItemString(d, "error", ThreadError) < 0) {
2780
0
        return -1;
2781
0
    }
2782
2783
    // _ExceptHookArgs type
2784
37
    state->excepthook_type = PyStructSequence_NewType(&ExceptHookArgs_desc);
2785
37
    if (state->excepthook_type == NULL) {
2786
0
        return -1;
2787
0
    }
2788
37
    if (PyModule_AddType(module, state->excepthook_type) < 0) {
2789
0
        return -1;
2790
0
    }
2791
2792
    // TIMEOUT_MAX
2793
37
    double timeout_max = (double)PY_TIMEOUT_MAX * 1e-6;
2794
37
    double time_max = PyTime_AsSecondsDouble(PyTime_MAX);
2795
37
    timeout_max = Py_MIN(timeout_max, time_max);
2796
    // Round towards minus infinity
2797
37
    timeout_max = floor(timeout_max);
2798
2799
37
    if (PyModule_Add(module, "TIMEOUT_MAX",
2800
37
                        PyFloat_FromDouble(timeout_max)) < 0) {
2801
0
        return -1;
2802
0
    }
2803
2804
37
    llist_init(&state->shutdown_handles);
2805
2806
37
#ifdef _PYTHREAD_NAME_MAXLEN
2807
37
    if (PyModule_AddIntConstant(module, "_NAME_MAXLEN",
2808
37
                                _PYTHREAD_NAME_MAXLEN) < 0) {
2809
0
        return -1;
2810
0
    }
2811
37
#endif
2812
2813
#ifdef MS_WINDOWS
2814
    HMODULE kernelbase = GetModuleHandleW(L"kernelbase.dll");
2815
    if (kernelbase != NULL) {
2816
        if (pGetThreadDescription == NULL) {
2817
            pGetThreadDescription = (PF_GET_THREAD_DESCRIPTION)GetProcAddress(
2818
                                        kernelbase, "GetThreadDescription");
2819
        }
2820
        if (pSetThreadDescription == NULL) {
2821
            pSetThreadDescription = (PF_SET_THREAD_DESCRIPTION)GetProcAddress(
2822
                                        kernelbase, "SetThreadDescription");
2823
        }
2824
    }
2825
2826
    if (pGetThreadDescription == NULL) {
2827
        if (PyObject_DelAttrString(module, "_get_name") < 0) {
2828
            return -1;
2829
        }
2830
    }
2831
    if (pSetThreadDescription == NULL) {
2832
        if (PyObject_DelAttrString(module, "set_name") < 0) {
2833
            return -1;
2834
        }
2835
    }
2836
#endif
2837
2838
37
    return 0;
2839
37
}
2840
2841
2842
static int
2843
thread_module_traverse(PyObject *module, visitproc visit, void *arg)
2844
1.64k
{
2845
1.64k
    thread_module_state *state = get_thread_state(module);
2846
1.64k
    Py_VISIT(state->excepthook_type);
2847
1.64k
    Py_VISIT(state->lock_type);
2848
1.64k
    Py_VISIT(state->rlock_type);
2849
1.64k
    Py_VISIT(state->local_type);
2850
1.64k
    Py_VISIT(state->local_dummy_type);
2851
1.64k
    Py_VISIT(state->thread_handle_type);
2852
1.64k
    return 0;
2853
1.64k
}
2854
2855
static int
2856
thread_module_clear(PyObject *module)
2857
0
{
2858
0
    thread_module_state *state = get_thread_state(module);
2859
0
    Py_CLEAR(state->excepthook_type);
2860
0
    Py_CLEAR(state->lock_type);
2861
0
    Py_CLEAR(state->rlock_type);
2862
0
    Py_CLEAR(state->local_type);
2863
0
    Py_CLEAR(state->local_dummy_type);
2864
0
    Py_CLEAR(state->thread_handle_type);
2865
    // Remove any remaining handles (e.g. if shutdown exited early due to
2866
    // interrupt) so that attempts to unlink the handle after our module state
2867
    // is destroyed do not crash.
2868
0
    clear_shutdown_handles(state);
2869
0
    return 0;
2870
0
}
2871
2872
static void
2873
thread_module_free(void *module)
2874
0
{
2875
0
    (void)thread_module_clear((PyObject *)module);
2876
0
}
2877
2878
2879
2880
PyDoc_STRVAR(thread_doc,
2881
"This module provides primitive operations to write multi-threaded programs.\n\
2882
The 'threading' module provides a more convenient interface.");
2883
2884
static PyModuleDef_Slot thread_module_slots[] = {
2885
    _Py_ABI_SLOT,
2886
    {Py_mod_exec, thread_module_exec},
2887
    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
2888
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
2889
    {0, NULL}
2890
};
2891
2892
static struct PyModuleDef thread_module = {
2893
    PyModuleDef_HEAD_INIT,
2894
    .m_name = "_thread",
2895
    .m_doc = thread_doc,
2896
    .m_size = sizeof(thread_module_state),
2897
    .m_methods = thread_methods,
2898
    .m_traverse = thread_module_traverse,
2899
    .m_clear = thread_module_clear,
2900
    .m_free = thread_module_free,
2901
    .m_slots = thread_module_slots,
2902
};
2903
2904
PyMODINIT_FUNC
2905
PyInit__thread(void)
2906
37
{
2907
37
    return PyModuleDef_Init(&thread_module);
2908
37
}