Coverage Report

Created: 2025-09-05 07:10

/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
10.3k
{
58
10.3k
    void *state = _PyModule_GetState(module);
59
10.3k
    assert(state != NULL);
60
10.3k
    return (thread_module_state *)state;
61
10.3k
}
62
63
static inline thread_module_state*
64
get_thread_state_by_cls(PyTypeObject *cls)
65
2.55k
{
66
    // Use PyType_GetModuleByDef() to handle (R)Lock subclasses.
67
2.55k
    PyObject *module = PyType_GetModuleByDef(cls, &thread_module);
68
2.55k
    if (module == NULL) {
69
0
        return NULL;
70
0
    }
71
2.55k
    return get_thread_state(module);
72
2.55k
}
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.55k
#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 void
659
PyThreadHandleObject_dealloc(PyObject *op)
660
0
{
661
0
    PyThreadHandleObject *self = PyThreadHandleObject_CAST(op);
662
0
    PyObject_GC_UnTrack(self);
663
0
    PyTypeObject *tp = Py_TYPE(self);
664
0
    ThreadHandle_decref(self->handle);
665
0
    tp->tp_free(self);
666
0
    Py_DECREF(tp);
667
0
}
668
669
static PyObject *
670
PyThreadHandleObject_repr(PyObject *op)
671
0
{
672
0
    PyThreadHandleObject *self = PyThreadHandleObject_CAST(op);
673
0
    PyThread_ident_t ident = ThreadHandle_ident(self->handle);
674
0
    return PyUnicode_FromFormat("<%s object: ident=%" PY_FORMAT_THREAD_IDENT_T ">",
675
0
                                Py_TYPE(self)->tp_name, ident);
676
0
}
677
678
static PyObject *
679
PyThreadHandleObject_get_ident(PyObject *op, void *Py_UNUSED(closure))
680
0
{
681
0
    PyThreadHandleObject *self = PyThreadHandleObject_CAST(op);
682
0
    return PyLong_FromUnsignedLongLong(ThreadHandle_ident(self->handle));
683
0
}
684
685
static PyObject *
686
PyThreadHandleObject_join(PyObject *op, PyObject *args)
687
0
{
688
0
    PyThreadHandleObject *self = PyThreadHandleObject_CAST(op);
689
690
0
    PyObject *timeout_obj = NULL;
691
0
    if (!PyArg_ParseTuple(args, "|O:join", &timeout_obj)) {
692
0
        return NULL;
693
0
    }
694
695
0
    PyTime_t timeout_ns = -1;
696
0
    if (timeout_obj != NULL && timeout_obj != Py_None) {
697
0
        if (_PyTime_FromSecondsObject(&timeout_ns, timeout_obj,
698
0
                                      _PyTime_ROUND_TIMEOUT) < 0) {
699
0
            return NULL;
700
0
        }
701
0
    }
702
703
0
    if (ThreadHandle_join(self->handle, timeout_ns) < 0) {
704
0
        return NULL;
705
0
    }
706
0
    Py_RETURN_NONE;
707
0
}
708
709
static PyObject *
710
PyThreadHandleObject_is_done(PyObject *op, PyObject *Py_UNUSED(dummy))
711
0
{
712
0
    PyThreadHandleObject *self = PyThreadHandleObject_CAST(op);
713
0
    if (_PyEvent_IsSet(&self->handle->thread_is_exiting)) {
714
0
        Py_RETURN_TRUE;
715
0
    }
716
0
    else {
717
0
        Py_RETURN_FALSE;
718
0
    }
719
0
}
720
721
static PyObject *
722
PyThreadHandleObject_set_done(PyObject *op, PyObject *Py_UNUSED(dummy))
723
0
{
724
0
    PyThreadHandleObject *self = PyThreadHandleObject_CAST(op);
725
0
    if (ThreadHandle_set_done(self->handle) < 0) {
726
0
        return NULL;
727
0
    }
728
0
    Py_RETURN_NONE;
729
0
}
730
731
static PyGetSetDef ThreadHandle_getsetlist[] = {
732
    {"ident", PyThreadHandleObject_get_ident, NULL, NULL},
733
    {0},
734
};
735
736
static PyMethodDef ThreadHandle_methods[] = {
737
    {"join", PyThreadHandleObject_join, METH_VARARGS, NULL},
738
    {"_set_done", PyThreadHandleObject_set_done, METH_NOARGS, NULL},
739
    {"is_done", PyThreadHandleObject_is_done, METH_NOARGS, NULL},
740
    {0, 0}
741
};
742
743
static PyType_Slot ThreadHandle_Type_slots[] = {
744
    {Py_tp_dealloc, PyThreadHandleObject_dealloc},
745
    {Py_tp_repr, PyThreadHandleObject_repr},
746
    {Py_tp_getset, ThreadHandle_getsetlist},
747
    {Py_tp_traverse, _PyObject_VisitType},
748
    {Py_tp_methods, ThreadHandle_methods},
749
    {Py_tp_new, PyThreadHandleObject_tp_new},
750
    {0, 0}
751
};
752
753
static PyType_Spec ThreadHandle_Type_spec = {
754
    "_thread._ThreadHandle",
755
    sizeof(PyThreadHandleObject),
756
    0,
757
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_HAVE_GC,
758
    ThreadHandle_Type_slots,
759
};
760
761
/* Lock objects */
762
763
static void
764
lock_dealloc(PyObject *self)
765
2.54k
{
766
2.54k
    PyObject_GC_UnTrack(self);
767
2.54k
    PyObject_ClearWeakRefs(self);
768
2.54k
    PyTypeObject *tp = Py_TYPE(self);
769
2.54k
    tp->tp_free(self);
770
2.54k
    Py_DECREF(tp);
771
2.54k
}
772
773
774
static int
775
lock_acquire_parse_timeout(PyObject *timeout_obj, int blocking, PyTime_t *timeout)
776
5.46k
{
777
    // XXX Use PyThread_ParseTimeoutArg().
778
779
5.46k
    const PyTime_t unset_timeout = _PyTime_FromSeconds(-1);
780
5.46k
    *timeout = unset_timeout;
781
782
5.46k
    if (timeout_obj
783
5.46k
        && _PyTime_FromSecondsObject(timeout,
784
0
                                     timeout_obj, _PyTime_ROUND_TIMEOUT) < 0)
785
0
        return -1;
786
787
5.46k
    if (!blocking && *timeout != unset_timeout ) {
788
0
        PyErr_SetString(PyExc_ValueError,
789
0
                        "can't specify a timeout for a non-blocking call");
790
0
        return -1;
791
0
    }
792
5.46k
    if (*timeout < 0 && *timeout != unset_timeout) {
793
0
        PyErr_SetString(PyExc_ValueError,
794
0
                        "timeout value must be a non-negative number");
795
0
        return -1;
796
0
    }
797
5.46k
    if (!blocking)
798
0
        *timeout = 0;
799
5.46k
    else if (*timeout != unset_timeout) {
800
0
        PyTime_t microseconds;
801
802
0
        microseconds = _PyTime_AsMicroseconds(*timeout, _PyTime_ROUND_TIMEOUT);
803
0
        if (microseconds > PY_TIMEOUT_MAX) {
804
0
            PyErr_SetString(PyExc_OverflowError,
805
0
                            "timeout value is too large");
806
0
            return -1;
807
0
        }
808
0
    }
809
5.46k
    return 0;
810
5.46k
}
811
/*[clinic input]
812
_thread.lock.acquire
813
    blocking: bool = True
814
    timeout as timeoutobj: object(py_default="-1") = NULL
815
816
Lock the lock.
817
818
Without argument, this blocks if the lock is already
819
locked (even by the same thread), waiting for another thread to release
820
the lock, and return True once the lock is acquired.
821
With an argument, this will only block if the argument is true,
822
and the return value reflects whether the lock is acquired.
823
The blocking operation is interruptible.
824
[clinic start generated code]*/
825
826
static PyObject *
827
_thread_lock_acquire_impl(lockobject *self, int blocking,
828
                          PyObject *timeoutobj)
829
/*[clinic end generated code: output=569d6b25d508bf6f input=13e999649bc1c798]*/
830
0
{
831
0
    PyTime_t timeout;
832
833
0
    if (lock_acquire_parse_timeout(timeoutobj, blocking, &timeout) < 0) {
834
0
        return NULL;
835
0
    }
836
837
0
    PyLockStatus r = _PyMutex_LockTimed(
838
0
        &self->lock, timeout,
839
0
        _PY_LOCK_PYTHONLOCK | _PY_LOCK_HANDLE_SIGNALS | _PY_LOCK_DETACH);
840
0
    if (r == PY_LOCK_INTR) {
841
0
        assert(PyErr_Occurred());
842
0
        return NULL;
843
0
    }
844
0
    if (r == PY_LOCK_FAILURE && PyErr_Occurred()) {
845
0
        return NULL;
846
0
    }
847
848
0
    return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
849
0
}
850
851
/*[clinic input]
852
_thread.lock.acquire_lock = _thread.lock.acquire
853
854
An obsolete synonym of acquire().
855
[clinic start generated code]*/
856
857
static PyObject *
858
_thread_lock_acquire_lock_impl(lockobject *self, int blocking,
859
                               PyObject *timeoutobj)
860
/*[clinic end generated code: output=ea6c87ea13b56694 input=5e65bd56327ebe85]*/
861
0
{
862
0
    return _thread_lock_acquire_impl(self, blocking, timeoutobj);
863
0
}
864
865
/*[clinic input]
866
_thread.lock.release
867
868
Release the lock.
869
870
Allows another thread that is blocked waiting for
871
the lock to acquire the lock.  The lock must be in the locked state,
872
but it needn't be locked by the same thread that unlocks it.
873
[clinic start generated code]*/
874
875
static PyObject *
876
_thread_lock_release_impl(lockobject *self)
877
/*[clinic end generated code: output=a4ab0d75d6e9fb73 input=dfe48f962dfe99b4]*/
878
0
{
879
    /* Sanity check: the lock must be locked */
880
0
    if (_PyMutex_TryUnlock(&self->lock) < 0) {
881
0
        PyErr_SetString(ThreadError, "release unlocked lock");
882
0
        return NULL;
883
0
    }
884
885
0
    Py_RETURN_NONE;
886
0
}
887
888
/*[clinic input]
889
_thread.lock.release_lock
890
891
An obsolete synonym of release().
892
[clinic start generated code]*/
893
894
static PyObject *
895
_thread_lock_release_lock_impl(lockobject *self)
896
/*[clinic end generated code: output=43025044d51789bb input=74d91374fc601433]*/
897
0
{
898
0
    return _thread_lock_release_impl(self);
899
0
}
900
901
/*[clinic input]
902
_thread.lock.__enter__
903
904
Lock the lock.
905
[clinic start generated code]*/
906
907
static PyObject *
908
_thread_lock___enter___impl(lockobject *self)
909
/*[clinic end generated code: output=f27725de751ae064 input=8f982991608d38e7]*/
910
0
{
911
0
    return _thread_lock_acquire_impl(self, 1, NULL);
912
0
}
913
914
/*[clinic input]
915
_thread.lock.__exit__
916
    exc_type: object
917
    exc_value: object
918
    exc_tb: object
919
    /
920
921
Release the lock.
922
[clinic start generated code]*/
923
924
static PyObject *
925
_thread_lock___exit___impl(lockobject *self, PyObject *exc_type,
926
                           PyObject *exc_value, PyObject *exc_tb)
927
/*[clinic end generated code: output=c9e8eefa69beed07 input=c74d4abe15a6c037]*/
928
0
{
929
0
    return _thread_lock_release_impl(self);
930
0
}
931
932
933
/*[clinic input]
934
_thread.lock.locked
935
936
Return whether the lock is in the locked state.
937
[clinic start generated code]*/
938
939
static PyObject *
940
_thread_lock_locked_impl(lockobject *self)
941
/*[clinic end generated code: output=63bb94e5a9efa382 input=d8e3d64861bbce73]*/
942
0
{
943
0
    return PyBool_FromLong(PyMutex_IsLocked(&self->lock));
944
0
}
945
946
/*[clinic input]
947
_thread.lock.locked_lock
948
949
An obsolete synonym of locked().
950
[clinic start generated code]*/
951
952
static PyObject *
953
_thread_lock_locked_lock_impl(lockobject *self)
954
/*[clinic end generated code: output=f747c8329e905f8e input=500b0c3592f9bf84]*/
955
0
{
956
0
    return _thread_lock_locked_impl(self);
957
0
}
958
959
static PyObject *
960
lock_repr(PyObject *op)
961
0
{
962
0
    lockobject *self = lockobject_CAST(op);
963
0
    return PyUnicode_FromFormat("<%s %s object at %p>",
964
0
        PyMutex_IsLocked(&self->lock) ? "locked" : "unlocked", Py_TYPE(self)->tp_name, self);
965
0
}
966
967
#ifdef HAVE_FORK
968
/*[clinic input]
969
_thread.lock._at_fork_reinit
970
[clinic start generated code]*/
971
972
static PyObject *
973
_thread_lock__at_fork_reinit_impl(lockobject *self)
974
/*[clinic end generated code: output=d8609f2d3bfa1fd5 input=a970cb76e2a0a131]*/
975
0
{
976
0
    _PyMutex_at_fork_reinit(&self->lock);
977
0
    Py_RETURN_NONE;
978
0
}
979
#endif  /* HAVE_FORK */
980
981
/*[clinic input]
982
@classmethod
983
_thread.lock.__new__ as lock_new
984
[clinic start generated code]*/
985
986
static PyObject *
987
lock_new_impl(PyTypeObject *type)
988
/*[clinic end generated code: output=eab660d5a4c05c8a input=260208a4e277d250]*/
989
2.54k
{
990
2.54k
    lockobject *self = (lockobject *)type->tp_alloc(type, 0);
991
2.54k
    if (self == NULL) {
992
0
        return NULL;
993
0
    }
994
2.54k
    self->lock = (PyMutex){0};
995
2.54k
    return (PyObject *)self;
996
2.54k
}
997
998
999
static PyMethodDef lock_methods[] = {
1000
    _THREAD_LOCK_ACQUIRE_LOCK_METHODDEF
1001
    _THREAD_LOCK_ACQUIRE_METHODDEF
1002
    _THREAD_LOCK_RELEASE_LOCK_METHODDEF
1003
    _THREAD_LOCK_RELEASE_METHODDEF
1004
    _THREAD_LOCK_LOCKED_LOCK_METHODDEF
1005
    _THREAD_LOCK_LOCKED_METHODDEF
1006
    _THREAD_LOCK___ENTER___METHODDEF
1007
    _THREAD_LOCK___EXIT___METHODDEF
1008
#ifdef HAVE_FORK
1009
    _THREAD_LOCK__AT_FORK_REINIT_METHODDEF
1010
#endif
1011
    {NULL,           NULL}              /* sentinel */
1012
};
1013
1014
PyDoc_STRVAR(lock_doc,
1015
"lock()\n\
1016
--\n\
1017
\n\
1018
A lock object is a synchronization primitive.  To create a lock,\n\
1019
call threading.Lock().  Methods are:\n\
1020
\n\
1021
acquire() -- lock the lock, possibly blocking until it can be obtained\n\
1022
release() -- unlock of the lock\n\
1023
locked() -- test whether the lock is currently locked\n\
1024
\n\
1025
A lock is not owned by the thread that locked it; another thread may\n\
1026
unlock it.  A thread attempting to lock a lock that it has already locked\n\
1027
will block until another thread unlocks it.  Deadlocks may ensue.");
1028
1029
static PyType_Slot lock_type_slots[] = {
1030
    {Py_tp_dealloc, lock_dealloc},
1031
    {Py_tp_repr, lock_repr},
1032
    {Py_tp_doc, (void *)lock_doc},
1033
    {Py_tp_methods, lock_methods},
1034
    {Py_tp_traverse, _PyObject_VisitType},
1035
    {Py_tp_new, lock_new},
1036
    {0, 0}
1037
};
1038
1039
static PyType_Spec lock_type_spec = {
1040
    .name = "_thread.lock",
1041
    .basicsize = sizeof(lockobject),
1042
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1043
              Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_MANAGED_WEAKREF),
1044
    .slots = lock_type_slots,
1045
};
1046
1047
/* Recursive lock objects */
1048
1049
static int
1050
rlock_locked_impl(rlockobject *self)
1051
0
{
1052
0
    return PyMutex_IsLocked(&self->lock.mutex);
1053
0
}
1054
1055
static void
1056
rlock_dealloc(PyObject *self)
1057
2.54k
{
1058
2.54k
    PyObject_GC_UnTrack(self);
1059
2.54k
    PyObject_ClearWeakRefs(self);
1060
2.54k
    PyTypeObject *tp = Py_TYPE(self);
1061
2.54k
    tp->tp_free(self);
1062
2.54k
    Py_DECREF(tp);
1063
2.54k
}
1064
1065
/*[clinic input]
1066
_thread.RLock.acquire
1067
    blocking: bool = True
1068
    timeout as timeoutobj: object(py_default="-1") = NULL
1069
1070
Lock the lock.
1071
1072
`blocking` indicates whether we should wait
1073
for the lock to be available or not.  If `blocking` is False
1074
and another thread holds the lock, the method will return False
1075
immediately.  If `blocking` is True and another thread holds
1076
the lock, the method will wait for the lock to be released,
1077
take it and then return True.
1078
(note: the blocking operation is interruptible.)
1079
1080
In all other cases, the method will return True immediately.
1081
Precisely, if the current thread already holds the lock, its
1082
internal counter is simply incremented. If nobody holds the lock,
1083
the lock is taken and its internal counter initialized to 1.
1084
[clinic start generated code]*/
1085
1086
static PyObject *
1087
_thread_RLock_acquire_impl(rlockobject *self, int blocking,
1088
                           PyObject *timeoutobj)
1089
/*[clinic end generated code: output=73df5af6f67c1513 input=d55a0f5014522a8d]*/
1090
5.46k
{
1091
5.46k
    PyTime_t timeout;
1092
1093
5.46k
    if (lock_acquire_parse_timeout(timeoutobj, blocking, &timeout) < 0) {
1094
0
        return NULL;
1095
0
    }
1096
1097
5.46k
    PyLockStatus r = _PyRecursiveMutex_LockTimed(
1098
5.46k
        &self->lock, timeout,
1099
5.46k
        _PY_LOCK_PYTHONLOCK | _PY_LOCK_HANDLE_SIGNALS | _PY_LOCK_DETACH);
1100
5.46k
    if (r == PY_LOCK_INTR) {
1101
0
        assert(PyErr_Occurred());
1102
0
        return NULL;
1103
0
    }
1104
5.46k
    if (r == PY_LOCK_FAILURE && PyErr_Occurred()) {
1105
0
        return NULL;
1106
0
    }
1107
1108
5.46k
    return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
1109
5.46k
}
1110
1111
/*[clinic input]
1112
_thread.RLock.__enter__
1113
1114
Lock the lock.
1115
[clinic start generated code]*/
1116
1117
static PyObject *
1118
_thread_RLock___enter___impl(rlockobject *self)
1119
/*[clinic end generated code: output=63135898476bf89f input=33be37f459dca390]*/
1120
5.46k
{
1121
5.46k
    return _thread_RLock_acquire_impl(self, 1, NULL);
1122
5.46k
}
1123
1124
/*[clinic input]
1125
_thread.RLock.release
1126
1127
Release the lock.
1128
1129
Allows another thread that is blocked waiting for
1130
the lock to acquire the lock.  The lock must be in the locked state,
1131
and must be locked by the same thread that unlocks it; otherwise a
1132
`RuntimeError` is raised.
1133
1134
Do note that if the lock was acquire()d several times in a row by the
1135
current thread, release() needs to be called as many times for the lock
1136
to be available for other threads.
1137
[clinic start generated code]*/
1138
1139
static PyObject *
1140
_thread_RLock_release_impl(rlockobject *self)
1141
/*[clinic end generated code: output=51f4a013c5fae2c5 input=d425daf1a5782e63]*/
1142
5.46k
{
1143
5.46k
    if (_PyRecursiveMutex_TryUnlock(&self->lock) < 0) {
1144
0
        PyErr_SetString(PyExc_RuntimeError,
1145
0
                        "cannot release un-acquired lock");
1146
0
        return NULL;
1147
0
    }
1148
5.46k
    Py_RETURN_NONE;
1149
5.46k
}
1150
1151
/*[clinic input]
1152
_thread.RLock.__exit__
1153
    exc_type: object
1154
    exc_value: object
1155
    exc_tb: object
1156
    /
1157
1158
Release the lock.
1159
1160
[clinic start generated code]*/
1161
1162
static PyObject *
1163
_thread_RLock___exit___impl(rlockobject *self, PyObject *exc_type,
1164
                            PyObject *exc_value, PyObject *exc_tb)
1165
/*[clinic end generated code: output=79bb44d551aedeb5 input=79accf0778d91002]*/
1166
5.46k
{
1167
5.46k
    return _thread_RLock_release_impl(self);
1168
5.46k
}
1169
1170
/*[clinic input]
1171
_thread.RLock.locked
1172
1173
Return a boolean indicating whether this object is locked right now.
1174
[clinic start generated code]*/
1175
1176
static PyObject *
1177
_thread_RLock_locked_impl(rlockobject *self)
1178
/*[clinic end generated code: output=e9b6060492b3f94e input=8866d9237ba5391b]*/
1179
0
{
1180
0
    int is_locked = rlock_locked_impl(self);
1181
0
    return PyBool_FromLong(is_locked);
1182
0
}
1183
1184
/*[clinic input]
1185
_thread.RLock._acquire_restore
1186
    state: object
1187
    /
1188
1189
For internal use by `threading.Condition`.
1190
[clinic start generated code]*/
1191
1192
static PyObject *
1193
_thread_RLock__acquire_restore_impl(rlockobject *self, PyObject *state)
1194
/*[clinic end generated code: output=beb8f2713a35e775 input=c8f2094fde059447]*/
1195
0
{
1196
0
    PyThread_ident_t owner;
1197
0
    Py_ssize_t count;
1198
1199
0
    if (!PyArg_Parse(state, "(n" Py_PARSE_THREAD_IDENT_T "):_acquire_restore",
1200
0
            &count, &owner))
1201
0
        return NULL;
1202
1203
0
    _PyRecursiveMutex_Lock(&self->lock);
1204
0
    _Py_atomic_store_ullong_relaxed(&self->lock.thread, owner);
1205
0
    self->lock.level = (size_t)count - 1;
1206
0
    Py_RETURN_NONE;
1207
0
}
1208
1209
1210
/*[clinic input]
1211
_thread.RLock._release_save
1212
1213
For internal use by `threading.Condition`.
1214
[clinic start generated code]*/
1215
1216
static PyObject *
1217
_thread_RLock__release_save_impl(rlockobject *self)
1218
/*[clinic end generated code: output=d2916487315bea93 input=809d227cfc4a112c]*/
1219
0
{
1220
0
    if (!_PyRecursiveMutex_IsLockedByCurrentThread(&self->lock)) {
1221
0
        PyErr_SetString(PyExc_RuntimeError,
1222
0
                        "cannot release un-acquired lock");
1223
0
        return NULL;
1224
0
    }
1225
1226
0
    PyThread_ident_t owner = self->lock.thread;
1227
0
    Py_ssize_t count = self->lock.level + 1;
1228
0
    self->lock.level = 0;  // ensure the unlock releases the lock
1229
0
    _PyRecursiveMutex_Unlock(&self->lock);
1230
0
    return Py_BuildValue("n" Py_PARSE_THREAD_IDENT_T, count, owner);
1231
0
}
1232
1233
1234
/*[clinic input]
1235
_thread.RLock._recursion_count
1236
1237
For internal use by reentrancy checks.
1238
[clinic start generated code]*/
1239
1240
static PyObject *
1241
_thread_RLock__recursion_count_impl(rlockobject *self)
1242
/*[clinic end generated code: output=7993fb9695ef2c4d input=7fd1834cd7a4b044]*/
1243
0
{
1244
0
    if (_PyRecursiveMutex_IsLockedByCurrentThread(&self->lock)) {
1245
0
        return PyLong_FromSize_t(self->lock.level + 1);
1246
0
    }
1247
0
    return PyLong_FromLong(0);
1248
0
}
1249
1250
1251
/*[clinic input]
1252
_thread.RLock._is_owned
1253
1254
For internal use by `threading.Condition`.
1255
[clinic start generated code]*/
1256
1257
static PyObject *
1258
_thread_RLock__is_owned_impl(rlockobject *self)
1259
/*[clinic end generated code: output=bf14268a3cabbe07 input=fba6535538deb858]*/
1260
0
{
1261
0
    long owned = _PyRecursiveMutex_IsLockedByCurrentThread(&self->lock);
1262
0
    return PyBool_FromLong(owned);
1263
0
}
1264
1265
/*[clinic input]
1266
@classmethod
1267
_thread.RLock.__new__ as rlock_new
1268
[clinic start generated code]*/
1269
1270
static PyObject *
1271
rlock_new_impl(PyTypeObject *type)
1272
/*[clinic end generated code: output=bb4fb1edf6818df5 input=013591361bf1ac6e]*/
1273
2.55k
{
1274
2.55k
    rlockobject *self = (rlockobject *) type->tp_alloc(type, 0);
1275
2.55k
    if (self == NULL) {
1276
0
        return NULL;
1277
0
    }
1278
2.55k
    self->lock = (_PyRecursiveMutex){0};
1279
2.55k
    return (PyObject *) self;
1280
2.55k
}
1281
1282
static PyObject *
1283
rlock_repr(PyObject *op)
1284
0
{
1285
0
    rlockobject *self = rlockobject_CAST(op);
1286
0
    PyThread_ident_t owner = self->lock.thread;
1287
0
    int locked = rlock_locked_impl(self);
1288
0
    size_t count;
1289
0
    if (locked) {
1290
0
        count = self->lock.level + 1;
1291
0
    }
1292
0
    else {
1293
0
        count = 0;
1294
0
    }
1295
0
    return PyUnicode_FromFormat(
1296
0
        "<%s %s object owner=%" PY_FORMAT_THREAD_IDENT_T " count=%zu at %p>",
1297
0
        locked ? "locked" : "unlocked",
1298
0
        Py_TYPE(self)->tp_name, owner,
1299
0
        count, self);
1300
0
}
1301
1302
1303
#ifdef HAVE_FORK
1304
/*[clinic input]
1305
_thread.RLock._at_fork_reinit
1306
[clinic start generated code]*/
1307
1308
static PyObject *
1309
_thread_RLock__at_fork_reinit_impl(rlockobject *self)
1310
/*[clinic end generated code: output=d77a4ce40351817c input=a3b625b026a8df4f]*/
1311
0
{
1312
0
    self->lock = (_PyRecursiveMutex){0};
1313
0
    Py_RETURN_NONE;
1314
0
}
1315
#endif  /* HAVE_FORK */
1316
1317
1318
static PyMethodDef rlock_methods[] = {
1319
    _THREAD_RLOCK_ACQUIRE_METHODDEF
1320
    _THREAD_RLOCK_RELEASE_METHODDEF
1321
    _THREAD_RLOCK_LOCKED_METHODDEF
1322
    _THREAD_RLOCK__IS_OWNED_METHODDEF
1323
    _THREAD_RLOCK__ACQUIRE_RESTORE_METHODDEF
1324
    _THREAD_RLOCK__RELEASE_SAVE_METHODDEF
1325
    _THREAD_RLOCK__RECURSION_COUNT_METHODDEF
1326
    _THREAD_RLOCK___ENTER___METHODDEF
1327
    _THREAD_RLOCK___EXIT___METHODDEF
1328
#ifdef HAVE_FORK
1329
    _THREAD_RLOCK__AT_FORK_REINIT_METHODDEF
1330
#endif
1331
    {NULL,           NULL}              /* sentinel */
1332
};
1333
1334
1335
static PyType_Slot rlock_type_slots[] = {
1336
    {Py_tp_dealloc, rlock_dealloc},
1337
    {Py_tp_repr, rlock_repr},
1338
    {Py_tp_methods, rlock_methods},
1339
    {Py_tp_alloc, PyType_GenericAlloc},
1340
    {Py_tp_new, rlock_new},
1341
    {Py_tp_traverse, _PyObject_VisitType},
1342
    {0, 0},
1343
};
1344
1345
static PyType_Spec rlock_type_spec = {
1346
    .name = "_thread.RLock",
1347
    .basicsize = sizeof(rlockobject),
1348
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
1349
              Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE | Py_TPFLAGS_MANAGED_WEAKREF),
1350
    .slots = rlock_type_slots,
1351
};
1352
1353
/* Thread-local objects */
1354
1355
/* Quick overview:
1356
1357
   We need to be able to reclaim reference cycles as soon as possible
1358
   (both when a thread is being terminated, or a thread-local object
1359
    becomes unreachable from user data).  Constraints:
1360
   - it must not be possible for thread-state dicts to be involved in
1361
     reference cycles (otherwise the cyclic GC will refuse to consider
1362
     objects referenced from a reachable thread-state dict, even though
1363
     local_dealloc would clear them)
1364
   - the death of a thread-state dict must still imply destruction of the
1365
     corresponding local dicts in all thread-local objects.
1366
1367
   Our implementation uses small "localdummy" objects in order to break
1368
   the reference chain. These trivial objects are hashable (using the
1369
   default scheme of identity hashing) and weakrefable.
1370
1371
   Each thread-state holds two separate localdummy objects:
1372
1373
   - `threading_local_key` is used as a key to retrieve the locals dictionary
1374
     for the thread in any `threading.local` object.
1375
   - `threading_local_sentinel` is used to signal when a thread is being
1376
     destroyed. Consequently, the associated thread-state must hold the only
1377
     reference.
1378
1379
   Each `threading.local` object contains a dict mapping localdummy keys to
1380
   locals dicts and a set containing weak references to localdummy
1381
   sentinels. Each sentinel weak reference has a callback that removes itself
1382
   and the locals dict for the key from the `threading.local` object when
1383
   called.
1384
1385
   Therefore:
1386
   - The thread-state only holds strong references to localdummy objects, which
1387
     cannot participate in cycles.
1388
   - Only outside objects (application- or library-level) hold strong
1389
     references to the thread-local objects.
1390
   - As soon as thread-state's sentinel dummy is destroyed the callbacks for
1391
     all weakrefs attached to the sentinel are called, and destroy the
1392
     corresponding local dicts from thread-local objects.
1393
   - As soon as a thread-local object is destroyed, its local dicts are
1394
     destroyed.
1395
   - The GC can do its work correctly when a thread-local object is dangling,
1396
     without any interference from the thread-state dicts.
1397
1398
   This dual key arrangement is necessary to ensure that `threading.local`
1399
   values can be retrieved from finalizers. If we were to only keep a mapping
1400
   of localdummy weakrefs to locals dicts it's possible that the weakrefs would
1401
   be cleared before finalizers were called (GC currently clears weakrefs that
1402
   are garbage before invoking finalizers), causing lookups in finalizers to
1403
   fail.
1404
*/
1405
1406
typedef struct {
1407
    PyObject_HEAD
1408
    PyObject *weakreflist;      /* List of weak references to self */
1409
} localdummyobject;
1410
1411
0
#define localdummyobject_CAST(op)   ((localdummyobject *)(op))
1412
1413
static void
1414
localdummy_dealloc(PyObject *op)
1415
0
{
1416
0
    localdummyobject *self = localdummyobject_CAST(op);
1417
0
    FT_CLEAR_WEAKREFS(op, self->weakreflist);
1418
0
    PyTypeObject *tp = Py_TYPE(self);
1419
0
    tp->tp_free(self);
1420
0
    Py_DECREF(tp);
1421
0
}
1422
1423
static PyMemberDef local_dummy_type_members[] = {
1424
    {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(localdummyobject, weakreflist), Py_READONLY},
1425
    {NULL},
1426
};
1427
1428
static PyType_Slot local_dummy_type_slots[] = {
1429
    {Py_tp_dealloc, localdummy_dealloc},
1430
    {Py_tp_doc, "Thread-local dummy"},
1431
    {Py_tp_members, local_dummy_type_members},
1432
    {0, 0}
1433
};
1434
1435
static PyType_Spec local_dummy_type_spec = {
1436
    .name = "_thread._localdummy",
1437
    .basicsize = sizeof(localdummyobject),
1438
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION |
1439
              Py_TPFLAGS_IMMUTABLETYPE),
1440
    .slots = local_dummy_type_slots,
1441
};
1442
1443
1444
typedef struct {
1445
    PyObject_HEAD
1446
    PyObject *args;
1447
    PyObject *kw;
1448
    PyObject *weakreflist;      /* List of weak references to self */
1449
    /* A {localdummy -> localdict} dict */
1450
    PyObject *localdicts;
1451
    /* A set of weakrefs to thread sentinels localdummies*/
1452
    PyObject *thread_watchdogs;
1453
} localobject;
1454
1455
0
#define localobject_CAST(op)    ((localobject *)(op))
1456
1457
/* Forward declaration */
1458
static int create_localsdict(localobject *self, thread_module_state *state,
1459
                             PyObject **localsdict, PyObject **sentinel_wr);
1460
static PyObject *clear_locals(PyObject *meth_self, PyObject *dummyweakref);
1461
1462
/* Create a weakref to the sentinel localdummy for the current thread */
1463
static PyObject *
1464
create_sentinel_wr(localobject *self)
1465
0
{
1466
0
    static PyMethodDef wr_callback_def = {
1467
0
        "clear_locals", clear_locals, METH_O
1468
0
    };
1469
1470
0
    PyThreadState *tstate = PyThreadState_Get();
1471
1472
    /* We use a weak reference to self in the callback closure
1473
       in order to avoid spurious reference cycles */
1474
0
    PyObject *self_wr = PyWeakref_NewRef((PyObject *) self, NULL);
1475
0
    if (self_wr == NULL) {
1476
0
        return NULL;
1477
0
    }
1478
1479
0
    PyObject *args = PyTuple_New(2);
1480
0
    if (args == NULL) {
1481
0
        Py_DECREF(self_wr);
1482
0
        return NULL;
1483
0
    }
1484
0
    PyTuple_SET_ITEM(args, 0, self_wr);
1485
0
    PyTuple_SET_ITEM(args, 1, Py_NewRef(tstate->threading_local_key));
1486
1487
0
    PyObject *cb = PyCFunction_New(&wr_callback_def, args);
1488
0
    Py_DECREF(args);
1489
0
    if (cb == NULL) {
1490
0
        return NULL;
1491
0
    }
1492
1493
0
    PyObject *wr = PyWeakref_NewRef(tstate->threading_local_sentinel, cb);
1494
0
    Py_DECREF(cb);
1495
1496
0
    return wr;
1497
0
}
1498
1499
static PyObject *
1500
local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
1501
0
{
1502
0
    if (type->tp_init == PyBaseObject_Type.tp_init) {
1503
0
        int rc = 0;
1504
0
        if (args != NULL)
1505
0
            rc = PyObject_IsTrue(args);
1506
0
        if (rc == 0 && kw != NULL)
1507
0
            rc = PyObject_IsTrue(kw);
1508
0
        if (rc != 0) {
1509
0
            if (rc > 0) {
1510
0
                PyErr_SetString(PyExc_TypeError,
1511
0
                          "Initialization arguments are not supported");
1512
0
            }
1513
0
            return NULL;
1514
0
        }
1515
0
    }
1516
1517
0
    PyObject *module = PyType_GetModuleByDef(type, &thread_module);
1518
0
    assert(module != NULL);
1519
0
    thread_module_state *state = get_thread_state(module);
1520
1521
0
    localobject *self = (localobject *)type->tp_alloc(type, 0);
1522
0
    if (self == NULL) {
1523
0
        return NULL;
1524
0
    }
1525
1526
    // gh-128691: Use deferred reference counting for thread-locals to avoid
1527
    // contention on the shared object.
1528
0
    _PyObject_SetDeferredRefcount((PyObject *)self);
1529
1530
0
    self->args = Py_XNewRef(args);
1531
0
    self->kw = Py_XNewRef(kw);
1532
1533
0
    self->localdicts = PyDict_New();
1534
0
    if (self->localdicts == NULL) {
1535
0
        goto err;
1536
0
    }
1537
1538
0
    self->thread_watchdogs = PySet_New(NULL);
1539
0
    if (self->thread_watchdogs == NULL) {
1540
0
        goto err;
1541
0
    }
1542
1543
0
    PyObject *localsdict = NULL;
1544
0
    PyObject *sentinel_wr = NULL;
1545
0
    if (create_localsdict(self, state, &localsdict, &sentinel_wr) < 0) {
1546
0
        goto err;
1547
0
    }
1548
0
    Py_DECREF(localsdict);
1549
0
    Py_DECREF(sentinel_wr);
1550
1551
0
    return (PyObject *)self;
1552
1553
0
  err:
1554
0
    Py_DECREF(self);
1555
0
    return NULL;
1556
0
}
1557
1558
static int
1559
local_traverse(PyObject *op, visitproc visit, void *arg)
1560
0
{
1561
0
    localobject *self = localobject_CAST(op);
1562
0
    Py_VISIT(Py_TYPE(self));
1563
0
    Py_VISIT(self->args);
1564
0
    Py_VISIT(self->kw);
1565
0
    Py_VISIT(self->localdicts);
1566
0
    Py_VISIT(self->thread_watchdogs);
1567
0
    return 0;
1568
0
}
1569
1570
static int
1571
local_clear(PyObject *op)
1572
0
{
1573
0
    localobject *self = localobject_CAST(op);
1574
0
    Py_CLEAR(self->args);
1575
0
    Py_CLEAR(self->kw);
1576
0
    Py_CLEAR(self->localdicts);
1577
0
    Py_CLEAR(self->thread_watchdogs);
1578
0
    return 0;
1579
0
}
1580
1581
static void
1582
local_dealloc(PyObject *op)
1583
0
{
1584
0
    localobject *self = localobject_CAST(op);
1585
    /* Weakrefs must be invalidated right now, otherwise they can be used
1586
       from code called below, which is very dangerous since Py_REFCNT(self) == 0 */
1587
0
    if (self->weakreflist != NULL) {
1588
0
        PyObject_ClearWeakRefs(op);
1589
0
    }
1590
0
    PyObject_GC_UnTrack(self);
1591
0
    (void)local_clear(op);
1592
0
    PyTypeObject *tp = Py_TYPE(self);
1593
0
    tp->tp_free(self);
1594
0
    Py_DECREF(tp);
1595
0
}
1596
1597
/* Create the TLS key and sentinel if they don't exist */
1598
static int
1599
create_localdummies(thread_module_state *state)
1600
0
{
1601
0
    PyThreadState *tstate = _PyThreadState_GET();
1602
1603
0
    if (tstate->threading_local_key != NULL) {
1604
0
        return 0;
1605
0
    }
1606
1607
0
    PyTypeObject *ld_type = state->local_dummy_type;
1608
0
    tstate->threading_local_key = ld_type->tp_alloc(ld_type, 0);
1609
0
    if (tstate->threading_local_key == NULL) {
1610
0
        return -1;
1611
0
    }
1612
1613
0
    tstate->threading_local_sentinel = ld_type->tp_alloc(ld_type, 0);
1614
0
    if (tstate->threading_local_sentinel == NULL) {
1615
0
        Py_CLEAR(tstate->threading_local_key);
1616
0
        return -1;
1617
0
    }
1618
1619
0
    return 0;
1620
0
}
1621
1622
/* Insert a localsdict and sentinel weakref for the current thread, placing
1623
   strong references in localsdict and sentinel_wr, respectively.
1624
*/
1625
static int
1626
create_localsdict(localobject *self, thread_module_state *state,
1627
                  PyObject **localsdict, PyObject **sentinel_wr)
1628
0
{
1629
0
    PyThreadState *tstate = _PyThreadState_GET();
1630
0
    PyObject *ldict = NULL;
1631
0
    PyObject *wr = NULL;
1632
1633
0
    if (create_localdummies(state) < 0) {
1634
0
        goto err;
1635
0
    }
1636
1637
    /* Create and insert the locals dict and sentinel weakref */
1638
0
    ldict = PyDict_New();
1639
0
    if (ldict == NULL) {
1640
0
        goto err;
1641
0
    }
1642
1643
0
    if (PyDict_SetItem(self->localdicts, tstate->threading_local_key,
1644
0
                       ldict) < 0)
1645
0
    {
1646
0
        goto err;
1647
0
    }
1648
1649
0
    wr = create_sentinel_wr(self);
1650
0
    if (wr == NULL) {
1651
0
        PyObject *exc = PyErr_GetRaisedException();
1652
0
        if (PyDict_DelItem(self->localdicts,
1653
0
                           tstate->threading_local_key) < 0)
1654
0
        {
1655
0
            PyErr_FormatUnraisable("Exception ignored while deleting "
1656
0
                                   "thread local of %R", self);
1657
0
        }
1658
0
        PyErr_SetRaisedException(exc);
1659
0
        goto err;
1660
0
    }
1661
1662
0
    if (PySet_Add(self->thread_watchdogs, wr) < 0) {
1663
0
        PyObject *exc = PyErr_GetRaisedException();
1664
0
        if (PyDict_DelItem(self->localdicts,
1665
0
                           tstate->threading_local_key) < 0)
1666
0
        {
1667
0
            PyErr_FormatUnraisable("Exception ignored while deleting "
1668
0
                                   "thread local of %R", self);
1669
0
        }
1670
0
        PyErr_SetRaisedException(exc);
1671
0
        goto err;
1672
0
    }
1673
1674
0
    *localsdict = ldict;
1675
0
    *sentinel_wr = wr;
1676
0
    return 0;
1677
1678
0
err:
1679
0
    Py_XDECREF(ldict);
1680
0
    Py_XDECREF(wr);
1681
0
    return -1;
1682
0
}
1683
1684
/* Return a strong reference to the locals dict for the current thread,
1685
   creating it if necessary.
1686
*/
1687
static PyObject *
1688
_ldict(localobject *self, thread_module_state *state)
1689
0
{
1690
0
    if (create_localdummies(state) < 0) {
1691
0
        return NULL;
1692
0
    }
1693
1694
    /* Check if a localsdict already exists */
1695
0
    PyObject *ldict;
1696
0
    PyThreadState *tstate = _PyThreadState_GET();
1697
0
    if (PyDict_GetItemRef(self->localdicts, tstate->threading_local_key,
1698
0
                          &ldict) < 0) {
1699
0
        return NULL;
1700
0
    }
1701
0
    if (ldict != NULL) {
1702
0
        return ldict;
1703
0
    }
1704
1705
    /* threading.local hasn't been instantiated for this thread */
1706
0
    PyObject *wr;
1707
0
    if (create_localsdict(self, state, &ldict, &wr) < 0) {
1708
0
        return NULL;
1709
0
    }
1710
1711
    /* run __init__ if we're a subtype of `threading.local` */
1712
0
    if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init &&
1713
0
        Py_TYPE(self)->tp_init((PyObject *)self, self->args, self->kw) < 0) {
1714
        /* we need to get rid of ldict from thread so
1715
           we create a new one the next time we do an attr
1716
           access */
1717
0
        PyObject *exc = PyErr_GetRaisedException();
1718
0
        if (PyDict_DelItem(self->localdicts,
1719
0
                           tstate->threading_local_key) < 0)
1720
0
        {
1721
0
            PyErr_FormatUnraisable("Exception ignored while deleting "
1722
0
                                   "thread local of %R", self);
1723
0
            assert(!PyErr_Occurred());
1724
0
        }
1725
0
        if (PySet_Discard(self->thread_watchdogs, wr) < 0) {
1726
0
            PyErr_FormatUnraisable("Exception ignored while discarding "
1727
0
                                   "thread watchdog of %R", self);
1728
0
        }
1729
0
        PyErr_SetRaisedException(exc);
1730
0
        Py_DECREF(ldict);
1731
0
        Py_DECREF(wr);
1732
0
        return NULL;
1733
0
    }
1734
0
    Py_DECREF(wr);
1735
1736
0
    return ldict;
1737
0
}
1738
1739
static int
1740
local_setattro(PyObject *op, PyObject *name, PyObject *v)
1741
0
{
1742
0
    localobject *self = localobject_CAST(op);
1743
0
    PyObject *module = PyType_GetModuleByDef(Py_TYPE(self), &thread_module);
1744
0
    assert(module != NULL);
1745
0
    thread_module_state *state = get_thread_state(module);
1746
1747
0
    PyObject *ldict = _ldict(self, state);
1748
0
    if (ldict == NULL) {
1749
0
        goto err;
1750
0
    }
1751
1752
0
    int r = PyObject_RichCompareBool(name, &_Py_ID(__dict__), Py_EQ);
1753
0
    if (r == -1) {
1754
0
        goto err;
1755
0
    }
1756
0
    if (r == 1) {
1757
0
        PyErr_Format(PyExc_AttributeError,
1758
0
                     "'%.100s' object attribute %R is read-only",
1759
0
                     Py_TYPE(self)->tp_name, name);
1760
0
        goto err;
1761
0
    }
1762
1763
0
    int st = _PyObject_GenericSetAttrWithDict(op, name, v, ldict);
1764
0
    Py_DECREF(ldict);
1765
0
    return st;
1766
1767
0
err:
1768
0
    Py_XDECREF(ldict);
1769
0
    return -1;
1770
0
}
1771
1772
static PyObject *local_getattro(PyObject *, PyObject *);
1773
1774
static PyMemberDef local_type_members[] = {
1775
    {"__weaklistoffset__", Py_T_PYSSIZET, offsetof(localobject, weakreflist), Py_READONLY},
1776
    {NULL},
1777
};
1778
1779
static PyType_Slot local_type_slots[] = {
1780
    {Py_tp_dealloc, local_dealloc},
1781
    {Py_tp_getattro, local_getattro},
1782
    {Py_tp_setattro, local_setattro},
1783
    {Py_tp_doc, "_local()\n--\n\nThread-local data"},
1784
    {Py_tp_traverse, local_traverse},
1785
    {Py_tp_clear, local_clear},
1786
    {Py_tp_new, local_new},
1787
    {Py_tp_members, local_type_members},
1788
    {0, 0}
1789
};
1790
1791
static PyType_Spec local_type_spec = {
1792
    .name = "_thread._local",
1793
    .basicsize = sizeof(localobject),
1794
    .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
1795
              Py_TPFLAGS_IMMUTABLETYPE),
1796
    .slots = local_type_slots,
1797
};
1798
1799
static PyObject *
1800
local_getattro(PyObject *op, PyObject *name)
1801
0
{
1802
0
    localobject *self = localobject_CAST(op);
1803
0
    PyObject *module = PyType_GetModuleByDef(Py_TYPE(self), &thread_module);
1804
0
    assert(module != NULL);
1805
0
    thread_module_state *state = get_thread_state(module);
1806
1807
0
    PyObject *ldict = _ldict(self, state);
1808
0
    if (ldict == NULL)
1809
0
        return NULL;
1810
1811
0
    int r = PyObject_RichCompareBool(name, &_Py_ID(__dict__), Py_EQ);
1812
0
    if (r == 1) {
1813
0
        return ldict;
1814
0
    }
1815
0
    if (r == -1) {
1816
0
        Py_DECREF(ldict);
1817
0
        return NULL;
1818
0
    }
1819
1820
0
    if (!Py_IS_TYPE(self, state->local_type)) {
1821
        /* use generic lookup for subtypes */
1822
0
        PyObject *res = _PyObject_GenericGetAttrWithDict(op, name, ldict, 0);
1823
0
        Py_DECREF(ldict);
1824
0
        return res;
1825
0
    }
1826
1827
    /* Optimization: just look in dict ourselves */
1828
0
    PyObject *value;
1829
0
    if (PyDict_GetItemRef(ldict, name, &value) != 0) {
1830
        // found or error
1831
0
        Py_DECREF(ldict);
1832
0
        return value;
1833
0
    }
1834
1835
    /* Fall back on generic to get __class__ and __dict__ */
1836
0
    PyObject *res = _PyObject_GenericGetAttrWithDict(op, name, ldict, 0);
1837
0
    Py_DECREF(ldict);
1838
0
    return res;
1839
0
}
1840
1841
/* Called when a dummy is destroyed, indicating that the owning thread is being
1842
 * cleared. */
1843
static PyObject *
1844
clear_locals(PyObject *locals_and_key, PyObject *dummyweakref)
1845
0
{
1846
0
    PyObject *localweakref = PyTuple_GetItem(locals_and_key, 0);
1847
0
    localobject *self = localobject_CAST(_PyWeakref_GET_REF(localweakref));
1848
0
    if (self == NULL) {
1849
0
        Py_RETURN_NONE;
1850
0
    }
1851
1852
    /* If the thread-local object is still alive and not being cleared,
1853
       remove the corresponding local dict */
1854
0
    if (self->localdicts != NULL) {
1855
0
        PyObject *key = PyTuple_GetItem(locals_and_key, 1);
1856
0
        if (PyDict_Pop(self->localdicts, key, NULL) < 0) {
1857
0
            PyErr_FormatUnraisable("Exception ignored while clearing "
1858
0
                                   "thread local %R", (PyObject *)self);
1859
0
        }
1860
0
    }
1861
0
    if (self->thread_watchdogs != NULL) {
1862
0
        if (PySet_Discard(self->thread_watchdogs, dummyweakref) < 0) {
1863
0
            PyErr_FormatUnraisable("Exception ignored while clearing "
1864
0
                                   "thread local %R", (PyObject *)self);
1865
0
        }
1866
0
    }
1867
1868
0
    Py_DECREF(self);
1869
0
    Py_RETURN_NONE;
1870
0
}
1871
1872
/* Module functions */
1873
1874
static PyObject *
1875
thread_daemon_threads_allowed(PyObject *module, PyObject *Py_UNUSED(ignored))
1876
0
{
1877
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
1878
0
    if (interp->feature_flags & Py_RTFLAGS_DAEMON_THREADS) {
1879
0
        Py_RETURN_TRUE;
1880
0
    }
1881
0
    else {
1882
0
        Py_RETURN_FALSE;
1883
0
    }
1884
0
}
1885
1886
PyDoc_STRVAR(daemon_threads_allowed_doc,
1887
"daemon_threads_allowed($module, /)\n\
1888
--\n\
1889
\n\
1890
Return True if daemon threads are allowed in the current interpreter,\n\
1891
and False otherwise.\n");
1892
1893
static int
1894
do_start_new_thread(thread_module_state *state, PyObject *func, PyObject *args,
1895
                    PyObject *kwargs, ThreadHandle *handle, int daemon)
1896
0
{
1897
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
1898
0
    if (!_PyInterpreterState_HasFeature(interp, Py_RTFLAGS_THREADS)) {
1899
0
        PyErr_SetString(PyExc_RuntimeError,
1900
0
                        "thread is not supported for isolated subinterpreters");
1901
0
        return -1;
1902
0
    }
1903
0
    if (_PyInterpreterState_GetFinalizing(interp) != NULL) {
1904
0
        PyErr_SetString(PyExc_PythonFinalizationError,
1905
0
                        "can't create new thread at interpreter shutdown");
1906
0
        return -1;
1907
0
    }
1908
1909
0
    if (!daemon) {
1910
        // Add the handle before starting the thread to avoid adding a handle
1911
        // to a thread that has already finished (i.e. if the thread finishes
1912
        // before the call to `ThreadHandle_start()` below returns).
1913
0
        add_to_shutdown_handles(state, handle);
1914
0
    }
1915
1916
0
    if (ThreadHandle_start(handle, func, args, kwargs) < 0) {
1917
0
        if (!daemon) {
1918
0
            remove_from_shutdown_handles(handle);
1919
0
        }
1920
0
        return -1;
1921
0
    }
1922
1923
0
    return 0;
1924
0
}
1925
1926
static PyObject *
1927
thread_PyThread_start_new_thread(PyObject *module, PyObject *fargs)
1928
0
{
1929
0
    PyObject *func, *args, *kwargs = NULL;
1930
0
    thread_module_state *state = get_thread_state(module);
1931
1932
0
    if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3,
1933
0
                           &func, &args, &kwargs))
1934
0
        return NULL;
1935
0
    if (!PyCallable_Check(func)) {
1936
0
        PyErr_SetString(PyExc_TypeError,
1937
0
                        "first arg must be callable");
1938
0
        return NULL;
1939
0
    }
1940
0
    if (!PyTuple_Check(args)) {
1941
0
        PyErr_SetString(PyExc_TypeError,
1942
0
                        "2nd arg must be a tuple");
1943
0
        return NULL;
1944
0
    }
1945
0
    if (kwargs != NULL && !PyDict_Check(kwargs)) {
1946
0
        PyErr_SetString(PyExc_TypeError,
1947
0
                        "optional 3rd arg must be a dictionary");
1948
0
        return NULL;
1949
0
    }
1950
1951
0
    if (PySys_Audit("_thread.start_new_thread", "OOO",
1952
0
                    func, args, kwargs ? kwargs : Py_None) < 0) {
1953
0
        return NULL;
1954
0
    }
1955
1956
0
    ThreadHandle *handle = ThreadHandle_new();
1957
0
    if (handle == NULL) {
1958
0
        return NULL;
1959
0
    }
1960
1961
0
    int st =
1962
0
        do_start_new_thread(state, func, args, kwargs, handle, /*daemon=*/1);
1963
0
    if (st < 0) {
1964
0
        ThreadHandle_decref(handle);
1965
0
        return NULL;
1966
0
    }
1967
0
    PyThread_ident_t ident = ThreadHandle_ident(handle);
1968
0
    ThreadHandle_decref(handle);
1969
0
    return PyLong_FromUnsignedLongLong(ident);
1970
0
}
1971
1972
PyDoc_STRVAR(start_new_thread_doc,
1973
"start_new_thread($module, function, args, kwargs={}, /)\n\
1974
--\n\
1975
\n\
1976
Start a new thread and return its identifier.\n\
1977
\n\
1978
The thread will call the function with positional arguments from the\n\
1979
tuple args and keyword arguments taken from the optional dictionary\n\
1980
kwargs.  The thread exits when the function returns; the return value\n\
1981
is ignored.  The thread will also exit when the function raises an\n\
1982
unhandled exception; a stack trace will be printed unless the exception\n\
1983
is SystemExit.");
1984
1985
PyDoc_STRVAR(start_new_doc,
1986
"start_new($module, function, args, kwargs={}, /)\n\
1987
--\n\
1988
\n\
1989
An obsolete synonym of start_new_thread().");
1990
1991
static PyObject *
1992
thread_PyThread_start_joinable_thread(PyObject *module, PyObject *fargs,
1993
                                      PyObject *fkwargs)
1994
0
{
1995
0
    static char *keywords[] = {"function", "handle", "daemon", NULL};
1996
0
    PyObject *func = NULL;
1997
0
    int daemon = 1;
1998
0
    thread_module_state *state = get_thread_state(module);
1999
0
    PyObject *hobj = NULL;
2000
0
    if (!PyArg_ParseTupleAndKeywords(fargs, fkwargs,
2001
0
                                     "O|Op:start_joinable_thread", keywords,
2002
0
                                     &func, &hobj, &daemon)) {
2003
0
        return NULL;
2004
0
    }
2005
2006
0
    if (!PyCallable_Check(func)) {
2007
0
        PyErr_SetString(PyExc_TypeError,
2008
0
                        "thread function must be callable");
2009
0
        return NULL;
2010
0
    }
2011
2012
0
    if (hobj == NULL) {
2013
0
        hobj = Py_None;
2014
0
    }
2015
0
    else if (hobj != Py_None && !Py_IS_TYPE(hobj, state->thread_handle_type)) {
2016
0
        PyErr_SetString(PyExc_TypeError, "'handle' must be a _ThreadHandle");
2017
0
        return NULL;
2018
0
    }
2019
2020
0
    if (PySys_Audit("_thread.start_joinable_thread", "OiO", func, daemon,
2021
0
                    hobj) < 0) {
2022
0
        return NULL;
2023
0
    }
2024
2025
0
    if (hobj == Py_None) {
2026
0
        hobj = (PyObject *)PyThreadHandleObject_new(state->thread_handle_type);
2027
0
        if (hobj == NULL) {
2028
0
            return NULL;
2029
0
        }
2030
0
    }
2031
0
    else {
2032
0
        Py_INCREF(hobj);
2033
0
    }
2034
2035
0
    PyObject* args = PyTuple_New(0);
2036
0
    if (args == NULL) {
2037
0
        return NULL;
2038
0
    }
2039
0
    int st = do_start_new_thread(state, func, args,
2040
                                 /*kwargs=*/ NULL, ((PyThreadHandleObject*)hobj)->handle, daemon);
2041
0
    Py_DECREF(args);
2042
0
    if (st < 0) {
2043
0
        Py_DECREF(hobj);
2044
0
        return NULL;
2045
0
    }
2046
0
    return (PyObject *) hobj;
2047
0
}
2048
2049
PyDoc_STRVAR(start_joinable_doc,
2050
"start_joinable_thread($module, /, function, handle=None, daemon=True)\n\
2051
--\n\
2052
\n\
2053
*For internal use only*: start a new thread.\n\
2054
\n\
2055
Like start_new_thread(), this starts a new thread calling the given function.\n\
2056
Unlike start_new_thread(), this returns a handle object with methods to join\n\
2057
or detach the given thread.\n\
2058
This function is not for third-party code, please use the\n\
2059
`threading` module instead. During finalization the runtime will not wait for\n\
2060
the thread to exit if daemon is True. If handle is provided it must be a\n\
2061
newly created thread._ThreadHandle instance.");
2062
2063
static PyObject *
2064
thread_PyThread_exit_thread(PyObject *self, PyObject *Py_UNUSED(ignored))
2065
0
{
2066
0
    PyErr_SetNone(PyExc_SystemExit);
2067
0
    return NULL;
2068
0
}
2069
2070
PyDoc_STRVAR(exit_doc,
2071
"exit($module, /)\n\
2072
--\n\
2073
\n\
2074
This is synonymous to ``raise SystemExit''.  It will cause the current\n\
2075
thread to exit silently unless the exception is caught.");
2076
2077
PyDoc_STRVAR(exit_thread_doc,
2078
"exit_thread($module, /)\n\
2079
--\n\
2080
\n\
2081
An obsolete synonym of exit().");
2082
2083
static PyObject *
2084
thread_PyThread_interrupt_main(PyObject *self, PyObject *args)
2085
0
{
2086
0
    int signum = SIGINT;
2087
0
    if (!PyArg_ParseTuple(args, "|i:signum", &signum)) {
2088
0
        return NULL;
2089
0
    }
2090
2091
0
    if (PyErr_SetInterruptEx(signum)) {
2092
0
        PyErr_SetString(PyExc_ValueError, "signal number out of range");
2093
0
        return NULL;
2094
0
    }
2095
0
    Py_RETURN_NONE;
2096
0
}
2097
2098
PyDoc_STRVAR(interrupt_doc,
2099
"interrupt_main($module, signum=signal.SIGINT, /)\n\
2100
--\n\
2101
\n\
2102
Simulate the arrival of the given signal in the main thread,\n\
2103
where the corresponding signal handler will be executed.\n\
2104
If *signum* is omitted, SIGINT is assumed.\n\
2105
A subthread can use this function to interrupt the main thread.\n\
2106
\n\
2107
Note: the default signal handler for SIGINT raises ``KeyboardInterrupt``."
2108
);
2109
2110
static PyObject *
2111
thread_PyThread_allocate_lock(PyObject *module, PyObject *Py_UNUSED(ignored))
2112
2.54k
{
2113
2.54k
    thread_module_state *state = get_thread_state(module);
2114
2.54k
    return lock_new_impl(state->lock_type);
2115
2.54k
}
2116
2117
PyDoc_STRVAR(allocate_lock_doc,
2118
"allocate_lock($module, /)\n\
2119
--\n\
2120
\n\
2121
Create a new lock object. See help(type(threading.Lock())) for\n\
2122
information about locks.");
2123
2124
PyDoc_STRVAR(allocate_doc,
2125
"allocate($module, /)\n\
2126
--\n\
2127
\n\
2128
An obsolete synonym of allocate_lock().");
2129
2130
static PyObject *
2131
thread_get_ident(PyObject *self, PyObject *Py_UNUSED(ignored))
2132
5.46k
{
2133
5.46k
    PyThread_ident_t ident = PyThread_get_thread_ident_ex();
2134
5.46k
    if (ident == PYTHREAD_INVALID_THREAD_ID) {
2135
0
        PyErr_SetString(ThreadError, "no current thread ident");
2136
0
        return NULL;
2137
0
    }
2138
5.46k
    return PyLong_FromUnsignedLongLong(ident);
2139
5.46k
}
2140
2141
PyDoc_STRVAR(get_ident_doc,
2142
"get_ident($module, /)\n\
2143
--\n\
2144
\n\
2145
Return a non-zero integer that uniquely identifies the current thread\n\
2146
amongst other threads that exist simultaneously.\n\
2147
This may be used to identify per-thread resources.\n\
2148
Even though on some platforms threads identities may appear to be\n\
2149
allocated consecutive numbers starting at 1, this behavior should not\n\
2150
be relied upon, and the number should be seen purely as a magic cookie.\n\
2151
A thread's identity may be reused for another thread after it exits.");
2152
2153
#ifdef PY_HAVE_THREAD_NATIVE_ID
2154
static PyObject *
2155
thread_get_native_id(PyObject *self, PyObject *Py_UNUSED(ignored))
2156
0
{
2157
0
    unsigned long native_id = PyThread_get_thread_native_id();
2158
0
    return PyLong_FromUnsignedLong(native_id);
2159
0
}
2160
2161
PyDoc_STRVAR(get_native_id_doc,
2162
"get_native_id($module, /)\n\
2163
--\n\
2164
\n\
2165
Return a non-negative integer identifying the thread as reported\n\
2166
by the OS (kernel). This may be used to uniquely identify a\n\
2167
particular thread within a system.");
2168
#endif
2169
2170
static PyObject *
2171
thread__count(PyObject *self, PyObject *Py_UNUSED(ignored))
2172
0
{
2173
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
2174
0
    return PyLong_FromSsize_t(_Py_atomic_load_ssize(&interp->threads.count));
2175
0
}
2176
2177
PyDoc_STRVAR(_count_doc,
2178
"_count($module, /)\n\
2179
--\n\
2180
\n\
2181
Return the number of currently running Python threads, excluding\n\
2182
the main thread. The returned number comprises all threads created\n\
2183
through `start_new_thread()` as well as `threading.Thread`, and not\n\
2184
yet finished.\n\
2185
\n\
2186
This function is meant for internal and specialized purposes only.\n\
2187
In most applications `threading.enumerate()` should be used instead.");
2188
2189
static PyObject *
2190
thread_stack_size(PyObject *self, PyObject *args)
2191
0
{
2192
0
    size_t old_size;
2193
0
    Py_ssize_t new_size = 0;
2194
0
    int rc;
2195
2196
0
    if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size))
2197
0
        return NULL;
2198
2199
0
    if (new_size < 0) {
2200
0
        PyErr_SetString(PyExc_ValueError,
2201
0
                        "size must be 0 or a positive value");
2202
0
        return NULL;
2203
0
    }
2204
2205
0
    old_size = PyThread_get_stacksize();
2206
2207
0
    rc = PyThread_set_stacksize((size_t) new_size);
2208
0
    if (rc == -1) {
2209
0
        PyErr_Format(PyExc_ValueError,
2210
0
                     "size not valid: %zd bytes",
2211
0
                     new_size);
2212
0
        return NULL;
2213
0
    }
2214
0
    if (rc == -2) {
2215
0
        PyErr_SetString(ThreadError,
2216
0
                        "setting stack size not supported");
2217
0
        return NULL;
2218
0
    }
2219
2220
0
    return PyLong_FromSsize_t((Py_ssize_t) old_size);
2221
0
}
2222
2223
PyDoc_STRVAR(stack_size_doc,
2224
"stack_size($module, size=0, /)\n\
2225
--\n\
2226
\n\
2227
Return the thread stack size used when creating new threads.  The\n\
2228
optional size argument specifies the stack size (in bytes) to be used\n\
2229
for subsequently created threads, and must be 0 (use platform or\n\
2230
configured default) or a positive integer value of at least 32,768 (32k).\n\
2231
If changing the thread stack size is unsupported, a ThreadError\n\
2232
exception is raised.  If the specified size is invalid, a ValueError\n\
2233
exception is raised, and the stack size is unmodified.  32k bytes\n\
2234
 currently the minimum supported stack size value to guarantee\n\
2235
sufficient stack space for the interpreter itself.\n\
2236
\n\
2237
Note that some platforms may have particular restrictions on values for\n\
2238
the stack size, such as requiring a minimum stack size larger than 32 KiB or\n\
2239
requiring allocation in multiples of the system memory page size\n\
2240
- platform documentation should be referred to for more information\n\
2241
(4 KiB pages are common; using multiples of 4096 for the stack size is\n\
2242
the suggested approach in the absence of more specific information).");
2243
2244
static int
2245
thread_excepthook_file(PyObject *file, PyObject *exc_type, PyObject *exc_value,
2246
                       PyObject *exc_traceback, PyObject *thread)
2247
0
{
2248
    /* print(f"Exception in thread {thread.name}:", file=file) */
2249
0
    if (PyFile_WriteString("Exception in thread ", file) < 0) {
2250
0
        return -1;
2251
0
    }
2252
2253
0
    PyObject *name = NULL;
2254
0
    if (thread != Py_None) {
2255
0
        if (PyObject_GetOptionalAttr(thread, &_Py_ID(name), &name) < 0) {
2256
0
            return -1;
2257
0
        }
2258
0
    }
2259
0
    if (name != NULL) {
2260
0
        if (PyFile_WriteObject(name, file, Py_PRINT_RAW) < 0) {
2261
0
            Py_DECREF(name);
2262
0
            return -1;
2263
0
        }
2264
0
        Py_DECREF(name);
2265
0
    }
2266
0
    else {
2267
0
        PyThread_ident_t ident = PyThread_get_thread_ident_ex();
2268
0
        PyObject *str = PyUnicode_FromFormat("%" PY_FORMAT_THREAD_IDENT_T, ident);
2269
0
        if (str != NULL) {
2270
0
            if (PyFile_WriteObject(str, file, Py_PRINT_RAW) < 0) {
2271
0
                Py_DECREF(str);
2272
0
                return -1;
2273
0
            }
2274
0
            Py_DECREF(str);
2275
0
        }
2276
0
        else {
2277
0
            PyErr_Clear();
2278
2279
0
            if (PyFile_WriteString("<failed to get thread name>", file) < 0) {
2280
0
                return -1;
2281
0
            }
2282
0
        }
2283
0
    }
2284
2285
0
    if (PyFile_WriteString(":\n", file) < 0) {
2286
0
        return -1;
2287
0
    }
2288
2289
    /* Display the traceback */
2290
0
    _PyErr_Display(file, exc_type, exc_value, exc_traceback);
2291
2292
    /* Call file.flush() */
2293
0
    if (_PyFile_Flush(file) < 0) {
2294
0
        return -1;
2295
0
    }
2296
2297
0
    return 0;
2298
0
}
2299
2300
2301
PyDoc_STRVAR(ExceptHookArgs__doc__,
2302
"ExceptHookArgs\n\
2303
\n\
2304
Type used to pass arguments to threading.excepthook.");
2305
2306
static PyStructSequence_Field ExceptHookArgs_fields[] = {
2307
    {"exc_type", "Exception type"},
2308
    {"exc_value", "Exception value"},
2309
    {"exc_traceback", "Exception traceback"},
2310
    {"thread", "Thread"},
2311
    {0}
2312
};
2313
2314
static PyStructSequence_Desc ExceptHookArgs_desc = {
2315
    .name = "_thread._ExceptHookArgs",
2316
    .doc = ExceptHookArgs__doc__,
2317
    .fields = ExceptHookArgs_fields,
2318
    .n_in_sequence = 4
2319
};
2320
2321
2322
static PyObject *
2323
thread_excepthook(PyObject *module, PyObject *args)
2324
0
{
2325
0
    thread_module_state *state = get_thread_state(module);
2326
2327
0
    if (!Py_IS_TYPE(args, state->excepthook_type)) {
2328
0
        PyErr_SetString(PyExc_TypeError,
2329
0
                        "_thread.excepthook argument type "
2330
0
                        "must be ExceptHookArgs");
2331
0
        return NULL;
2332
0
    }
2333
2334
    /* Borrowed reference */
2335
0
    PyObject *exc_type = PyStructSequence_GET_ITEM(args, 0);
2336
0
    if (exc_type == PyExc_SystemExit) {
2337
        /* silently ignore SystemExit */
2338
0
        Py_RETURN_NONE;
2339
0
    }
2340
2341
    /* Borrowed references */
2342
0
    PyObject *exc_value = PyStructSequence_GET_ITEM(args, 1);
2343
0
    PyObject *exc_tb = PyStructSequence_GET_ITEM(args, 2);
2344
0
    PyObject *thread = PyStructSequence_GET_ITEM(args, 3);
2345
2346
0
    PyObject *file;
2347
0
    if (PySys_GetOptionalAttr( &_Py_ID(stderr), &file) < 0) {
2348
0
        return NULL;
2349
0
    }
2350
0
    if (file == NULL || file == Py_None) {
2351
0
        Py_XDECREF(file);
2352
0
        if (thread == Py_None) {
2353
            /* do nothing if sys.stderr is None and thread is None */
2354
0
            Py_RETURN_NONE;
2355
0
        }
2356
2357
0
        file = PyObject_GetAttrString(thread, "_stderr");
2358
0
        if (file == NULL) {
2359
0
            return NULL;
2360
0
        }
2361
0
        if (file == Py_None) {
2362
0
            Py_DECREF(file);
2363
            /* do nothing if sys.stderr is None and sys.stderr was None
2364
               when the thread was created */
2365
0
            Py_RETURN_NONE;
2366
0
        }
2367
0
    }
2368
2369
0
    int res = thread_excepthook_file(file, exc_type, exc_value, exc_tb,
2370
0
                                     thread);
2371
0
    Py_DECREF(file);
2372
0
    if (res < 0) {
2373
0
        return NULL;
2374
0
    }
2375
2376
0
    Py_RETURN_NONE;
2377
0
}
2378
2379
PyDoc_STRVAR(excepthook_doc,
2380
"_excepthook($module, args, /)\n\
2381
--\n\
2382
\n\
2383
Handle uncaught Thread.run() exception.");
2384
2385
static PyObject *
2386
thread__is_main_interpreter(PyObject *module, PyObject *Py_UNUSED(ignored))
2387
0
{
2388
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
2389
0
    return PyBool_FromLong(_Py_IsMainInterpreter(interp));
2390
0
}
2391
2392
PyDoc_STRVAR(thread__is_main_interpreter_doc,
2393
"_is_main_interpreter($module, /)\n\
2394
--\n\
2395
\n\
2396
Return True if the current interpreter is the main Python interpreter.");
2397
2398
static PyObject *
2399
thread_shutdown(PyObject *self, PyObject *args)
2400
0
{
2401
0
    PyThread_ident_t ident = PyThread_get_thread_ident_ex();
2402
0
    thread_module_state *state = get_thread_state(self);
2403
2404
0
    for (;;) {
2405
0
        ThreadHandle *handle = NULL;
2406
2407
        // Find a thread that's not yet finished.
2408
0
        HEAD_LOCK(&_PyRuntime);
2409
0
        struct llist_node *node;
2410
0
        llist_for_each_safe(node, &state->shutdown_handles) {
2411
0
            ThreadHandle *cur = llist_data(node, ThreadHandle, shutdown_node);
2412
0
            if (cur->ident != ident) {
2413
0
                ThreadHandle_incref(cur);
2414
0
                handle = cur;
2415
0
                break;
2416
0
            }
2417
0
        }
2418
0
        HEAD_UNLOCK(&_PyRuntime);
2419
2420
0
        if (!handle) {
2421
            // No more threads to wait on!
2422
0
            break;
2423
0
        }
2424
2425
        // Wait for the thread to finish. If we're interrupted, such
2426
        // as by a ctrl-c we print the error and exit early.
2427
0
        if (ThreadHandle_join(handle, -1) < 0) {
2428
0
            PyErr_FormatUnraisable("Exception ignored while joining a thread "
2429
0
                                   "in _thread._shutdown()");
2430
0
            ThreadHandle_decref(handle);
2431
0
            Py_RETURN_NONE;
2432
0
        }
2433
2434
0
        ThreadHandle_decref(handle);
2435
0
    }
2436
2437
0
    Py_RETURN_NONE;
2438
0
}
2439
2440
PyDoc_STRVAR(shutdown_doc,
2441
"_shutdown($module, /)\n\
2442
--\n\
2443
\n\
2444
Wait for all non-daemon threads (other than the calling thread) to stop.");
2445
2446
static PyObject *
2447
thread__make_thread_handle(PyObject *module, PyObject *identobj)
2448
0
{
2449
0
    thread_module_state *state = get_thread_state(module);
2450
0
    if (!PyLong_Check(identobj)) {
2451
0
        PyErr_SetString(PyExc_TypeError, "ident must be an integer");
2452
0
        return NULL;
2453
0
    }
2454
0
    PyThread_ident_t ident = PyLong_AsUnsignedLongLong(identobj);
2455
0
    if (PyErr_Occurred()) {
2456
0
        return NULL;
2457
0
    }
2458
0
    PyThreadHandleObject *hobj =
2459
0
        PyThreadHandleObject_new(state->thread_handle_type);
2460
0
    if (hobj == NULL) {
2461
0
        return NULL;
2462
0
    }
2463
0
    PyMutex_Lock(&hobj->handle->mutex);
2464
0
    hobj->handle->ident = ident;
2465
0
    hobj->handle->state = THREAD_HANDLE_RUNNING;
2466
0
    PyMutex_Unlock(&hobj->handle->mutex);
2467
0
    return (PyObject*) hobj;
2468
0
}
2469
2470
PyDoc_STRVAR(thread__make_thread_handle_doc,
2471
"_make_thread_handle($module, ident, /)\n\
2472
--\n\
2473
\n\
2474
Internal only. Make a thread handle for threads not spawned\n\
2475
by the _thread or threading module.");
2476
2477
static PyObject *
2478
thread__get_main_thread_ident(PyObject *module, PyObject *Py_UNUSED(ignored))
2479
0
{
2480
0
    return PyLong_FromUnsignedLongLong(_PyRuntime.main_thread);
2481
0
}
2482
2483
PyDoc_STRVAR(thread__get_main_thread_ident_doc,
2484
"_get_main_thread_ident($module, /)\n\
2485
--\n\
2486
\n\
2487
Internal only. Return a non-zero integer that uniquely identifies the main thread\n\
2488
of the main interpreter.");
2489
2490
#if defined(__OpenBSD__)
2491
    /* pthread_*_np functions, especially pthread_{get,set}_name_np().
2492
       pthread_np.h exists on both OpenBSD and FreeBSD but the latter declares
2493
       pthread_getname_np() and pthread_setname_np() in pthread.h as long as
2494
       __BSD_VISIBLE remains set.
2495
     */
2496
#   include <pthread_np.h>
2497
#endif
2498
2499
#if defined(HAVE_PTHREAD_GETNAME_NP) || defined(HAVE_PTHREAD_GET_NAME_NP) || defined(MS_WINDOWS)
2500
/*[clinic input]
2501
_thread._get_name
2502
2503
Get the name of the current thread.
2504
[clinic start generated code]*/
2505
2506
static PyObject *
2507
_thread__get_name_impl(PyObject *module)
2508
/*[clinic end generated code: output=20026e7ee3da3dd7 input=35cec676833d04c8]*/
2509
0
{
2510
0
#ifndef MS_WINDOWS
2511
    // Linux and macOS are limited to respectively 16 and 64 bytes
2512
0
    char name[100];
2513
0
    pthread_t thread = pthread_self();
2514
0
#ifdef HAVE_PTHREAD_GETNAME_NP
2515
0
    int rc = pthread_getname_np(thread, name, Py_ARRAY_LENGTH(name));
2516
#else /* defined(HAVE_PTHREAD_GET_NAME_NP) */
2517
    int rc = 0; /* pthread_get_name_np() returns void */
2518
    pthread_get_name_np(thread, name, Py_ARRAY_LENGTH(name));
2519
#endif
2520
0
    if (rc) {
2521
0
        errno = rc;
2522
0
        return PyErr_SetFromErrno(PyExc_OSError);
2523
0
    }
2524
2525
#ifdef __sun
2526
    // gh-138004: Decode Solaris/Illumos (e.g. OpenIndiana) thread names
2527
    // from ASCII, since OpenIndiana only supports ASCII names.
2528
    return PyUnicode_DecodeASCII(name, strlen(name), "surrogateescape");
2529
#else
2530
0
    return PyUnicode_DecodeFSDefault(name);
2531
0
#endif
2532
#else
2533
    // Windows implementation
2534
    assert(pGetThreadDescription != NULL);
2535
2536
    wchar_t *name;
2537
    HRESULT hr = pGetThreadDescription(GetCurrentThread(), &name);
2538
    if (FAILED(hr)) {
2539
        PyErr_SetFromWindowsErr(0);
2540
        return NULL;
2541
    }
2542
2543
    PyObject *name_obj = PyUnicode_FromWideChar(name, -1);
2544
    LocalFree(name);
2545
    return name_obj;
2546
#endif
2547
0
}
2548
#endif  // HAVE_PTHREAD_GETNAME_NP || HAVE_PTHREAD_GET_NAME_NP || MS_WINDOWS
2549
2550
2551
#if defined(HAVE_PTHREAD_SETNAME_NP) || defined(HAVE_PTHREAD_SET_NAME_NP) || defined(MS_WINDOWS)
2552
/*[clinic input]
2553
_thread.set_name
2554
2555
    name as name_obj: unicode
2556
2557
Set the name of the current thread.
2558
[clinic start generated code]*/
2559
2560
static PyObject *
2561
_thread_set_name_impl(PyObject *module, PyObject *name_obj)
2562
/*[clinic end generated code: output=402b0c68e0c0daed input=7e7acd98261be82f]*/
2563
0
{
2564
0
#ifndef MS_WINDOWS
2565
#ifdef __sun
2566
    // gh-138004: Encode Solaris/Illumos thread names to ASCII,
2567
    // since OpenIndiana does not support non-ASCII names.
2568
    const char *encoding = "ascii";
2569
#else
2570
    // Encode the thread name to the filesystem encoding using the "replace"
2571
    // error handler
2572
0
    PyInterpreterState *interp = _PyInterpreterState_GET();
2573
0
    const char *encoding = interp->unicode.fs_codec.encoding;
2574
0
#endif
2575
0
    PyObject *name_encoded;
2576
0
    name_encoded = PyUnicode_AsEncodedString(name_obj, encoding, "replace");
2577
0
    if (name_encoded == NULL) {
2578
0
        return NULL;
2579
0
    }
2580
2581
0
#ifdef _PYTHREAD_NAME_MAXLEN
2582
    // Truncate to _PYTHREAD_NAME_MAXLEN bytes + the NUL byte if needed
2583
0
    if (PyBytes_GET_SIZE(name_encoded) > _PYTHREAD_NAME_MAXLEN) {
2584
0
        PyObject *truncated;
2585
0
        truncated = PyBytes_FromStringAndSize(PyBytes_AS_STRING(name_encoded),
2586
0
                                              _PYTHREAD_NAME_MAXLEN);
2587
0
        if (truncated == NULL) {
2588
0
            Py_DECREF(name_encoded);
2589
0
            return NULL;
2590
0
        }
2591
0
        Py_SETREF(name_encoded, truncated);
2592
0
    }
2593
0
#endif
2594
2595
0
    const char *name = PyBytes_AS_STRING(name_encoded);
2596
#ifdef __APPLE__
2597
    int rc = pthread_setname_np(name);
2598
#elif defined(__NetBSD__)
2599
    pthread_t thread = pthread_self();
2600
    int rc = pthread_setname_np(thread, "%s", (void *)name);
2601
#elif defined(HAVE_PTHREAD_SETNAME_NP)
2602
    pthread_t thread = pthread_self();
2603
0
    int rc = pthread_setname_np(thread, name);
2604
#else /* defined(HAVE_PTHREAD_SET_NAME_NP) */
2605
    pthread_t thread = pthread_self();
2606
    int rc = 0; /* pthread_set_name_np() returns void */
2607
    pthread_set_name_np(thread, name);
2608
#endif
2609
0
    Py_DECREF(name_encoded);
2610
0
    if (rc) {
2611
0
        errno = rc;
2612
0
        return PyErr_SetFromErrno(PyExc_OSError);
2613
0
    }
2614
0
    Py_RETURN_NONE;
2615
#else
2616
    // Windows implementation
2617
    assert(pSetThreadDescription != NULL);
2618
2619
    Py_ssize_t len;
2620
    wchar_t *name = PyUnicode_AsWideCharString(name_obj, &len);
2621
    if (name == NULL) {
2622
        return NULL;
2623
    }
2624
2625
    if (len > _PYTHREAD_NAME_MAXLEN) {
2626
        // Truncate the name
2627
        Py_UCS4 ch = name[_PYTHREAD_NAME_MAXLEN-1];
2628
        if (Py_UNICODE_IS_HIGH_SURROGATE(ch)) {
2629
            name[_PYTHREAD_NAME_MAXLEN-1] = 0;
2630
        }
2631
        else {
2632
            name[_PYTHREAD_NAME_MAXLEN] = 0;
2633
        }
2634
    }
2635
2636
    HRESULT hr = pSetThreadDescription(GetCurrentThread(), name);
2637
    PyMem_Free(name);
2638
    if (FAILED(hr)) {
2639
        PyErr_SetFromWindowsErr((int)hr);
2640
        return NULL;
2641
    }
2642
    Py_RETURN_NONE;
2643
#endif
2644
0
}
2645
#endif  // HAVE_PTHREAD_SETNAME_NP || HAVE_PTHREAD_SET_NAME_NP || MS_WINDOWS
2646
2647
2648
static PyMethodDef thread_methods[] = {
2649
    {"start_new_thread",        thread_PyThread_start_new_thread,
2650
     METH_VARARGS, start_new_thread_doc},
2651
    {"start_new",               thread_PyThread_start_new_thread,
2652
     METH_VARARGS, start_new_doc},
2653
    {"start_joinable_thread",   _PyCFunction_CAST(thread_PyThread_start_joinable_thread),
2654
     METH_VARARGS | METH_KEYWORDS, start_joinable_doc},
2655
    {"daemon_threads_allowed",  thread_daemon_threads_allowed,
2656
     METH_NOARGS, daemon_threads_allowed_doc},
2657
    {"allocate_lock",           thread_PyThread_allocate_lock,
2658
     METH_NOARGS, allocate_lock_doc},
2659
    {"allocate",                thread_PyThread_allocate_lock,
2660
     METH_NOARGS, allocate_doc},
2661
    {"exit_thread",             thread_PyThread_exit_thread,
2662
     METH_NOARGS, exit_thread_doc},
2663
    {"exit",                    thread_PyThread_exit_thread,
2664
     METH_NOARGS, exit_doc},
2665
    {"interrupt_main",          thread_PyThread_interrupt_main,
2666
     METH_VARARGS, interrupt_doc},
2667
    {"get_ident",               thread_get_ident,
2668
     METH_NOARGS, get_ident_doc},
2669
#ifdef PY_HAVE_THREAD_NATIVE_ID
2670
    {"get_native_id",           thread_get_native_id,
2671
     METH_NOARGS, get_native_id_doc},
2672
#endif
2673
    {"_count",                  thread__count,
2674
     METH_NOARGS, _count_doc},
2675
    {"stack_size",              thread_stack_size,
2676
     METH_VARARGS, stack_size_doc},
2677
    {"_excepthook",             thread_excepthook,
2678
     METH_O, excepthook_doc},
2679
    {"_is_main_interpreter",    thread__is_main_interpreter,
2680
     METH_NOARGS, thread__is_main_interpreter_doc},
2681
    {"_shutdown",               thread_shutdown,
2682
     METH_NOARGS, shutdown_doc},
2683
    {"_make_thread_handle", thread__make_thread_handle,
2684
     METH_O, thread__make_thread_handle_doc},
2685
    {"_get_main_thread_ident", thread__get_main_thread_ident,
2686
     METH_NOARGS, thread__get_main_thread_ident_doc},
2687
    _THREAD_SET_NAME_METHODDEF
2688
    _THREAD__GET_NAME_METHODDEF
2689
    {NULL,                      NULL}           /* sentinel */
2690
};
2691
2692
2693
/* Initialization function */
2694
2695
static int
2696
thread_module_exec(PyObject *module)
2697
16
{
2698
16
    thread_module_state *state = get_thread_state(module);
2699
16
    PyObject *d = PyModule_GetDict(module);
2700
2701
    // Initialize the C thread library
2702
16
    PyThread_init_thread();
2703
2704
    // _ThreadHandle
2705
16
    state->thread_handle_type = (PyTypeObject *)PyType_FromSpec(&ThreadHandle_Type_spec);
2706
16
    if (state->thread_handle_type == NULL) {
2707
0
        return -1;
2708
0
    }
2709
16
    if (PyDict_SetItemString(d, "_ThreadHandle", (PyObject *)state->thread_handle_type) < 0) {
2710
0
        return -1;
2711
0
    }
2712
2713
    // Lock
2714
16
    state->lock_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, &lock_type_spec, NULL);
2715
16
    if (state->lock_type == NULL) {
2716
0
        return -1;
2717
0
    }
2718
16
    if (PyModule_AddType(module, state->lock_type) < 0) {
2719
0
        return -1;
2720
0
    }
2721
    // Old alias: lock -> LockType
2722
16
    if (PyDict_SetItemString(d, "LockType", (PyObject *)state->lock_type) < 0) {
2723
0
        return -1;
2724
0
    }
2725
2726
    // RLock
2727
16
    state->rlock_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, &rlock_type_spec, NULL);
2728
16
    if (state->rlock_type == NULL) {
2729
0
        return -1;
2730
0
    }
2731
16
    if (PyModule_AddType(module, state->rlock_type) < 0) {
2732
0
        return -1;
2733
0
    }
2734
2735
    // Local dummy
2736
16
    state->local_dummy_type = (PyTypeObject *)PyType_FromSpec(&local_dummy_type_spec);
2737
16
    if (state->local_dummy_type == NULL) {
2738
0
        return -1;
2739
0
    }
2740
2741
    // Local
2742
16
    state->local_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, &local_type_spec, NULL);
2743
16
    if (state->local_type == NULL) {
2744
0
        return -1;
2745
0
    }
2746
16
    if (PyModule_AddType(module, state->local_type) < 0) {
2747
0
        return -1;
2748
0
    }
2749
2750
    // Add module attributes
2751
16
    if (PyDict_SetItemString(d, "error", ThreadError) < 0) {
2752
0
        return -1;
2753
0
    }
2754
2755
    // _ExceptHookArgs type
2756
16
    state->excepthook_type = PyStructSequence_NewType(&ExceptHookArgs_desc);
2757
16
    if (state->excepthook_type == NULL) {
2758
0
        return -1;
2759
0
    }
2760
16
    if (PyModule_AddType(module, state->excepthook_type) < 0) {
2761
0
        return -1;
2762
0
    }
2763
2764
    // TIMEOUT_MAX
2765
16
    double timeout_max = (double)PY_TIMEOUT_MAX * 1e-6;
2766
16
    double time_max = PyTime_AsSecondsDouble(PyTime_MAX);
2767
16
    timeout_max = Py_MIN(timeout_max, time_max);
2768
    // Round towards minus infinity
2769
16
    timeout_max = floor(timeout_max);
2770
2771
16
    if (PyModule_Add(module, "TIMEOUT_MAX",
2772
16
                        PyFloat_FromDouble(timeout_max)) < 0) {
2773
0
        return -1;
2774
0
    }
2775
2776
16
    llist_init(&state->shutdown_handles);
2777
2778
16
#ifdef _PYTHREAD_NAME_MAXLEN
2779
16
    if (PyModule_AddIntConstant(module, "_NAME_MAXLEN",
2780
16
                                _PYTHREAD_NAME_MAXLEN) < 0) {
2781
0
        return -1;
2782
0
    }
2783
16
#endif
2784
2785
#ifdef MS_WINDOWS
2786
    HMODULE kernelbase = GetModuleHandleW(L"kernelbase.dll");
2787
    if (kernelbase != NULL) {
2788
        if (pGetThreadDescription == NULL) {
2789
            pGetThreadDescription = (PF_GET_THREAD_DESCRIPTION)GetProcAddress(
2790
                                        kernelbase, "GetThreadDescription");
2791
        }
2792
        if (pSetThreadDescription == NULL) {
2793
            pSetThreadDescription = (PF_SET_THREAD_DESCRIPTION)GetProcAddress(
2794
                                        kernelbase, "SetThreadDescription");
2795
        }
2796
    }
2797
2798
    if (pGetThreadDescription == NULL) {
2799
        if (PyObject_DelAttrString(module, "_get_name") < 0) {
2800
            return -1;
2801
        }
2802
    }
2803
    if (pSetThreadDescription == NULL) {
2804
        if (PyObject_DelAttrString(module, "set_name") < 0) {
2805
            return -1;
2806
        }
2807
    }
2808
#endif
2809
2810
16
    return 0;
2811
16
}
2812
2813
2814
static int
2815
thread_module_traverse(PyObject *module, visitproc visit, void *arg)
2816
5.28k
{
2817
5.28k
    thread_module_state *state = get_thread_state(module);
2818
5.28k
    Py_VISIT(state->excepthook_type);
2819
5.28k
    Py_VISIT(state->lock_type);
2820
5.28k
    Py_VISIT(state->rlock_type);
2821
5.28k
    Py_VISIT(state->local_type);
2822
5.28k
    Py_VISIT(state->local_dummy_type);
2823
5.28k
    Py_VISIT(state->thread_handle_type);
2824
5.28k
    return 0;
2825
5.28k
}
2826
2827
static int
2828
thread_module_clear(PyObject *module)
2829
0
{
2830
0
    thread_module_state *state = get_thread_state(module);
2831
0
    Py_CLEAR(state->excepthook_type);
2832
0
    Py_CLEAR(state->lock_type);
2833
0
    Py_CLEAR(state->rlock_type);
2834
0
    Py_CLEAR(state->local_type);
2835
0
    Py_CLEAR(state->local_dummy_type);
2836
0
    Py_CLEAR(state->thread_handle_type);
2837
    // Remove any remaining handles (e.g. if shutdown exited early due to
2838
    // interrupt) so that attempts to unlink the handle after our module state
2839
    // is destroyed do not crash.
2840
0
    clear_shutdown_handles(state);
2841
0
    return 0;
2842
0
}
2843
2844
static void
2845
thread_module_free(void *module)
2846
0
{
2847
0
    (void)thread_module_clear((PyObject *)module);
2848
0
}
2849
2850
2851
2852
PyDoc_STRVAR(thread_doc,
2853
"This module provides primitive operations to write multi-threaded programs.\n\
2854
The 'threading' module provides a more convenient interface.");
2855
2856
static PyModuleDef_Slot thread_module_slots[] = {
2857
    {Py_mod_exec, thread_module_exec},
2858
    {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
2859
    {Py_mod_gil, Py_MOD_GIL_NOT_USED},
2860
    {0, NULL}
2861
};
2862
2863
static struct PyModuleDef thread_module = {
2864
    PyModuleDef_HEAD_INIT,
2865
    .m_name = "_thread",
2866
    .m_doc = thread_doc,
2867
    .m_size = sizeof(thread_module_state),
2868
    .m_methods = thread_methods,
2869
    .m_traverse = thread_module_traverse,
2870
    .m_clear = thread_module_clear,
2871
    .m_free = thread_module_free,
2872
    .m_slots = thread_module_slots,
2873
};
2874
2875
PyMODINIT_FUNC
2876
PyInit__thread(void)
2877
16
{
2878
16
    return PyModuleDef_Init(&thread_module);
2879
16
}