Coverage Report

Created: 2025-08-26 06:26

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