Coverage Report

Created: 2025-07-04 06:49

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