Coverage Report

Created: 2025-10-10 06:33

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