(root)/
Python-3.11.7/
Modules/
_threadmodule.c
       1  
       2  /* Thread module */
       3  /* Interface to Sjoerd's portable C thread library */
       4  
       5  #include "Python.h"
       6  #include "pycore_interp.h"        // _PyInterpreterState.threads.count
       7  #include "pycore_moduleobject.h"  // _PyModule_GetState()
       8  #include "pycore_pylifecycle.h"
       9  #include "pycore_pystate.h"       // _PyThreadState_SetCurrent()
      10  #include <stddef.h>               // offsetof()
      11  #include "structmember.h"         // PyMemberDef
      12  
      13  #ifdef HAVE_SIGNAL_H
      14  #  include <signal.h>             // SIGINT
      15  #endif
      16  
      17  // ThreadError is just an alias to PyExc_RuntimeError
      18  #define ThreadError PyExc_RuntimeError
      19  
      20  
      21  // Forward declarations
      22  static struct PyModuleDef thread_module;
      23  
      24  
      25  typedef struct {
      26      PyTypeObject *excepthook_type;
      27      PyTypeObject *lock_type;
      28      PyTypeObject *local_type;
      29      PyTypeObject *local_dummy_type;
      30  } thread_module_state;
      31  
      32  static inline thread_module_state*
      33  get_thread_state(PyObject *module)
      34  {
      35      void *state = _PyModule_GetState(module);
      36      assert(state != NULL);
      37      return (thread_module_state *)state;
      38  }
      39  
      40  
      41  /* Lock objects */
      42  
      43  typedef struct {
      44      PyObject_HEAD
      45      PyThread_type_lock lock_lock;
      46      PyObject *in_weakreflist;
      47      char locked; /* for sanity checking */
      48  } lockobject;
      49  
      50  static int
      51  lock_traverse(lockobject *self, visitproc visit, void *arg)
      52  {
      53      Py_VISIT(Py_TYPE(self));
      54      return 0;
      55  }
      56  
      57  static void
      58  lock_dealloc(lockobject *self)
      59  {
      60      PyObject_GC_UnTrack(self);
      61      if (self->in_weakreflist != NULL) {
      62          PyObject_ClearWeakRefs((PyObject *) self);
      63      }
      64      if (self->lock_lock != NULL) {
      65          /* Unlock the lock so it's safe to free it */
      66          if (self->locked)
      67              PyThread_release_lock(self->lock_lock);
      68          PyThread_free_lock(self->lock_lock);
      69      }
      70      PyTypeObject *tp = Py_TYPE(self);
      71      tp->tp_free((PyObject*)self);
      72      Py_DECREF(tp);
      73  }
      74  
      75  /* Helper to acquire an interruptible lock with a timeout.  If the lock acquire
      76   * is interrupted, signal handlers are run, and if they raise an exception,
      77   * PY_LOCK_INTR is returned.  Otherwise, PY_LOCK_ACQUIRED or PY_LOCK_FAILURE
      78   * are returned, depending on whether the lock can be acquired within the
      79   * timeout.
      80   */
      81  static PyLockStatus
      82  acquire_timed(PyThread_type_lock lock, _PyTime_t timeout)
      83  {
      84      _PyTime_t endtime = 0;
      85      if (timeout > 0) {
      86          endtime = _PyDeadline_Init(timeout);
      87      }
      88  
      89      PyLockStatus r;
      90      do {
      91          _PyTime_t microseconds;
      92          microseconds = _PyTime_AsMicroseconds(timeout, _PyTime_ROUND_CEILING);
      93  
      94          /* first a simple non-blocking try without releasing the GIL */
      95          r = PyThread_acquire_lock_timed(lock, 0, 0);
      96          if (r == PY_LOCK_FAILURE && microseconds != 0) {
      97              Py_BEGIN_ALLOW_THREADS
      98              r = PyThread_acquire_lock_timed(lock, microseconds, 1);
      99              Py_END_ALLOW_THREADS
     100          }
     101  
     102          if (r == PY_LOCK_INTR) {
     103              /* Run signal handlers if we were interrupted.  Propagate
     104               * exceptions from signal handlers, such as KeyboardInterrupt, by
     105               * passing up PY_LOCK_INTR.  */
     106              if (Py_MakePendingCalls() < 0) {
     107                  return PY_LOCK_INTR;
     108              }
     109  
     110              /* If we're using a timeout, recompute the timeout after processing
     111               * signals, since those can take time.  */
     112              if (timeout > 0) {
     113                  timeout = _PyDeadline_Get(endtime);
     114  
     115                  /* Check for negative values, since those mean block forever.
     116                   */
     117                  if (timeout < 0) {
     118                      r = PY_LOCK_FAILURE;
     119                  }
     120              }
     121          }
     122      } while (r == PY_LOCK_INTR);  /* Retry if we were interrupted. */
     123  
     124      return r;
     125  }
     126  
     127  static int
     128  lock_acquire_parse_args(PyObject *args, PyObject *kwds,
     129                          _PyTime_t *timeout)
     130  {
     131      char *kwlist[] = {"blocking", "timeout", NULL};
     132      int blocking = 1;
     133      PyObject *timeout_obj = NULL;
     134      const _PyTime_t unset_timeout = _PyTime_FromSeconds(-1);
     135  
     136      *timeout = unset_timeout ;
     137  
     138      if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iO:acquire", kwlist,
     139                                       &blocking, &timeout_obj))
     140          return -1;
     141  
     142      if (timeout_obj
     143          && _PyTime_FromSecondsObject(timeout,
     144                                       timeout_obj, _PyTime_ROUND_TIMEOUT) < 0)
     145          return -1;
     146  
     147      if (!blocking && *timeout != unset_timeout ) {
     148          PyErr_SetString(PyExc_ValueError,
     149                          "can't specify a timeout for a non-blocking call");
     150          return -1;
     151      }
     152      if (*timeout < 0 && *timeout != unset_timeout) {
     153          PyErr_SetString(PyExc_ValueError,
     154                          "timeout value must be positive");
     155          return -1;
     156      }
     157      if (!blocking)
     158          *timeout = 0;
     159      else if (*timeout != unset_timeout) {
     160          _PyTime_t microseconds;
     161  
     162          microseconds = _PyTime_AsMicroseconds(*timeout, _PyTime_ROUND_TIMEOUT);
     163          if (microseconds > PY_TIMEOUT_MAX) {
     164              PyErr_SetString(PyExc_OverflowError,
     165                              "timeout value is too large");
     166              return -1;
     167          }
     168      }
     169      return 0;
     170  }
     171  
     172  static PyObject *
     173  lock_PyThread_acquire_lock(lockobject *self, PyObject *args, PyObject *kwds)
     174  {
     175      _PyTime_t timeout;
     176      if (lock_acquire_parse_args(args, kwds, &timeout) < 0)
     177          return NULL;
     178  
     179      PyLockStatus r = acquire_timed(self->lock_lock, timeout);
     180      if (r == PY_LOCK_INTR) {
     181          return NULL;
     182      }
     183  
     184      if (r == PY_LOCK_ACQUIRED)
     185          self->locked = 1;
     186      return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
     187  }
     188  
     189  PyDoc_STRVAR(acquire_doc,
     190  "acquire(blocking=True, timeout=-1) -> bool\n\
     191  (acquire_lock() is an obsolete synonym)\n\
     192  \n\
     193  Lock the lock.  Without argument, this blocks if the lock is already\n\
     194  locked (even by the same thread), waiting for another thread to release\n\
     195  the lock, and return True once the lock is acquired.\n\
     196  With an argument, this will only block if the argument is true,\n\
     197  and the return value reflects whether the lock is acquired.\n\
     198  The blocking operation is interruptible.");
     199  
     200  static PyObject *
     201  lock_PyThread_release_lock(lockobject *self, PyObject *Py_UNUSED(ignored))
     202  {
     203      /* Sanity check: the lock must be locked */
     204      if (!self->locked) {
     205          PyErr_SetString(ThreadError, "release unlocked lock");
     206          return NULL;
     207      }
     208  
     209      PyThread_release_lock(self->lock_lock);
     210      self->locked = 0;
     211      Py_RETURN_NONE;
     212  }
     213  
     214  PyDoc_STRVAR(release_doc,
     215  "release()\n\
     216  (release_lock() is an obsolete synonym)\n\
     217  \n\
     218  Release the lock, allowing another thread that is blocked waiting for\n\
     219  the lock to acquire the lock.  The lock must be in the locked state,\n\
     220  but it needn't be locked by the same thread that unlocks it.");
     221  
     222  static PyObject *
     223  lock_locked_lock(lockobject *self, PyObject *Py_UNUSED(ignored))
     224  {
     225      return PyBool_FromLong((long)self->locked);
     226  }
     227  
     228  PyDoc_STRVAR(locked_doc,
     229  "locked() -> bool\n\
     230  (locked_lock() is an obsolete synonym)\n\
     231  \n\
     232  Return whether the lock is in the locked state.");
     233  
     234  static PyObject *
     235  lock_repr(lockobject *self)
     236  {
     237      return PyUnicode_FromFormat("<%s %s object at %p>",
     238          self->locked ? "locked" : "unlocked", Py_TYPE(self)->tp_name, self);
     239  }
     240  
     241  #ifdef HAVE_FORK
     242  static PyObject *
     243  lock__at_fork_reinit(lockobject *self, PyObject *Py_UNUSED(args))
     244  {
     245      if (_PyThread_at_fork_reinit(&self->lock_lock) < 0) {
     246          PyErr_SetString(ThreadError, "failed to reinitialize lock at fork");
     247          return NULL;
     248      }
     249  
     250      self->locked = 0;
     251  
     252      Py_RETURN_NONE;
     253  }
     254  #endif  /* HAVE_FORK */
     255  
     256  
     257  static PyMethodDef lock_methods[] = {
     258      {"acquire_lock", _PyCFunction_CAST(lock_PyThread_acquire_lock),
     259       METH_VARARGS | METH_KEYWORDS, acquire_doc},
     260      {"acquire",      _PyCFunction_CAST(lock_PyThread_acquire_lock),
     261       METH_VARARGS | METH_KEYWORDS, acquire_doc},
     262      {"release_lock", (PyCFunction)lock_PyThread_release_lock,
     263       METH_NOARGS, release_doc},
     264      {"release",      (PyCFunction)lock_PyThread_release_lock,
     265       METH_NOARGS, release_doc},
     266      {"locked_lock",  (PyCFunction)lock_locked_lock,
     267       METH_NOARGS, locked_doc},
     268      {"locked",       (PyCFunction)lock_locked_lock,
     269       METH_NOARGS, locked_doc},
     270      {"__enter__",    _PyCFunction_CAST(lock_PyThread_acquire_lock),
     271       METH_VARARGS | METH_KEYWORDS, acquire_doc},
     272      {"__exit__",    (PyCFunction)lock_PyThread_release_lock,
     273       METH_VARARGS, release_doc},
     274  #ifdef HAVE_FORK
     275      {"_at_fork_reinit",    (PyCFunction)lock__at_fork_reinit,
     276       METH_NOARGS, NULL},
     277  #endif
     278      {NULL,           NULL}              /* sentinel */
     279  };
     280  
     281  PyDoc_STRVAR(lock_doc,
     282  "A lock object is a synchronization primitive.  To create a lock,\n\
     283  call threading.Lock().  Methods are:\n\
     284  \n\
     285  acquire() -- lock the lock, possibly blocking until it can be obtained\n\
     286  release() -- unlock of the lock\n\
     287  locked() -- test whether the lock is currently locked\n\
     288  \n\
     289  A lock is not owned by the thread that locked it; another thread may\n\
     290  unlock it.  A thread attempting to lock a lock that it has already locked\n\
     291  will block until another thread unlocks it.  Deadlocks may ensue.");
     292  
     293  static PyMemberDef lock_type_members[] = {
     294      {"__weaklistoffset__", T_PYSSIZET, offsetof(lockobject, in_weakreflist), READONLY},
     295      {NULL},
     296  };
     297  
     298  static PyType_Slot lock_type_slots[] = {
     299      {Py_tp_dealloc, (destructor)lock_dealloc},
     300      {Py_tp_repr, (reprfunc)lock_repr},
     301      {Py_tp_doc, (void *)lock_doc},
     302      {Py_tp_methods, lock_methods},
     303      {Py_tp_traverse, lock_traverse},
     304      {Py_tp_members, lock_type_members},
     305      {0, 0}
     306  };
     307  
     308  static PyType_Spec lock_type_spec = {
     309      .name = "_thread.lock",
     310      .basicsize = sizeof(lockobject),
     311      .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
     312                Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE),
     313      .slots = lock_type_slots,
     314  };
     315  
     316  /* Recursive lock objects */
     317  
     318  typedef struct {
     319      PyObject_HEAD
     320      PyThread_type_lock rlock_lock;
     321      unsigned long rlock_owner;
     322      unsigned long rlock_count;
     323      PyObject *in_weakreflist;
     324  } rlockobject;
     325  
     326  static int
     327  rlock_traverse(rlockobject *self, visitproc visit, void *arg)
     328  {
     329      Py_VISIT(Py_TYPE(self));
     330      return 0;
     331  }
     332  
     333  
     334  static void
     335  rlock_dealloc(rlockobject *self)
     336  {
     337      PyObject_GC_UnTrack(self);
     338      if (self->in_weakreflist != NULL)
     339          PyObject_ClearWeakRefs((PyObject *) self);
     340      /* self->rlock_lock can be NULL if PyThread_allocate_lock() failed
     341         in rlock_new() */
     342      if (self->rlock_lock != NULL) {
     343          /* Unlock the lock so it's safe to free it */
     344          if (self->rlock_count > 0)
     345              PyThread_release_lock(self->rlock_lock);
     346  
     347          PyThread_free_lock(self->rlock_lock);
     348      }
     349      PyTypeObject *tp = Py_TYPE(self);
     350      tp->tp_free(self);
     351      Py_DECREF(tp);
     352  }
     353  
     354  static PyObject *
     355  rlock_acquire(rlockobject *self, PyObject *args, PyObject *kwds)
     356  {
     357      _PyTime_t timeout;
     358      unsigned long tid;
     359      PyLockStatus r = PY_LOCK_ACQUIRED;
     360  
     361      if (lock_acquire_parse_args(args, kwds, &timeout) < 0)
     362          return NULL;
     363  
     364      tid = PyThread_get_thread_ident();
     365      if (self->rlock_count > 0 && tid == self->rlock_owner) {
     366          unsigned long count = self->rlock_count + 1;
     367          if (count <= self->rlock_count) {
     368              PyErr_SetString(PyExc_OverflowError,
     369                              "Internal lock count overflowed");
     370              return NULL;
     371          }
     372          self->rlock_count = count;
     373          Py_RETURN_TRUE;
     374      }
     375      r = acquire_timed(self->rlock_lock, timeout);
     376      if (r == PY_LOCK_ACQUIRED) {
     377          assert(self->rlock_count == 0);
     378          self->rlock_owner = tid;
     379          self->rlock_count = 1;
     380      }
     381      else if (r == PY_LOCK_INTR) {
     382          return NULL;
     383      }
     384  
     385      return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
     386  }
     387  
     388  PyDoc_STRVAR(rlock_acquire_doc,
     389  "acquire(blocking=True) -> bool\n\
     390  \n\
     391  Lock the lock.  `blocking` indicates whether we should wait\n\
     392  for the lock to be available or not.  If `blocking` is False\n\
     393  and another thread holds the lock, the method will return False\n\
     394  immediately.  If `blocking` is True and another thread holds\n\
     395  the lock, the method will wait for the lock to be released,\n\
     396  take it and then return True.\n\
     397  (note: the blocking operation is interruptible.)\n\
     398  \n\
     399  In all other cases, the method will return True immediately.\n\
     400  Precisely, if the current thread already holds the lock, its\n\
     401  internal counter is simply incremented. If nobody holds the lock,\n\
     402  the lock is taken and its internal counter initialized to 1.");
     403  
     404  static PyObject *
     405  rlock_release(rlockobject *self, PyObject *Py_UNUSED(ignored))
     406  {
     407      unsigned long tid = PyThread_get_thread_ident();
     408  
     409      if (self->rlock_count == 0 || self->rlock_owner != tid) {
     410          PyErr_SetString(PyExc_RuntimeError,
     411                          "cannot release un-acquired lock");
     412          return NULL;
     413      }
     414      if (--self->rlock_count == 0) {
     415          self->rlock_owner = 0;
     416          PyThread_release_lock(self->rlock_lock);
     417      }
     418      Py_RETURN_NONE;
     419  }
     420  
     421  PyDoc_STRVAR(rlock_release_doc,
     422  "release()\n\
     423  \n\
     424  Release the lock, allowing another thread that is blocked waiting for\n\
     425  the lock to acquire the lock.  The lock must be in the locked state,\n\
     426  and must be locked by the same thread that unlocks it; otherwise a\n\
     427  `RuntimeError` is raised.\n\
     428  \n\
     429  Do note that if the lock was acquire()d several times in a row by the\n\
     430  current thread, release() needs to be called as many times for the lock\n\
     431  to be available for other threads.");
     432  
     433  static PyObject *
     434  rlock_acquire_restore(rlockobject *self, PyObject *args)
     435  {
     436      unsigned long owner;
     437      unsigned long count;
     438      int r = 1;
     439  
     440      if (!PyArg_ParseTuple(args, "(kk):_acquire_restore", &count, &owner))
     441          return NULL;
     442  
     443      if (!PyThread_acquire_lock(self->rlock_lock, 0)) {
     444          Py_BEGIN_ALLOW_THREADS
     445          r = PyThread_acquire_lock(self->rlock_lock, 1);
     446          Py_END_ALLOW_THREADS
     447      }
     448      if (!r) {
     449          PyErr_SetString(ThreadError, "couldn't acquire lock");
     450          return NULL;
     451      }
     452      assert(self->rlock_count == 0);
     453      self->rlock_owner = owner;
     454      self->rlock_count = count;
     455      Py_RETURN_NONE;
     456  }
     457  
     458  PyDoc_STRVAR(rlock_acquire_restore_doc,
     459  "_acquire_restore(state) -> None\n\
     460  \n\
     461  For internal use by `threading.Condition`.");
     462  
     463  static PyObject *
     464  rlock_release_save(rlockobject *self, PyObject *Py_UNUSED(ignored))
     465  {
     466      unsigned long owner;
     467      unsigned long count;
     468  
     469      if (self->rlock_count == 0) {
     470          PyErr_SetString(PyExc_RuntimeError,
     471                          "cannot release un-acquired lock");
     472          return NULL;
     473      }
     474  
     475      owner = self->rlock_owner;
     476      count = self->rlock_count;
     477      self->rlock_count = 0;
     478      self->rlock_owner = 0;
     479      PyThread_release_lock(self->rlock_lock);
     480      return Py_BuildValue("kk", count, owner);
     481  }
     482  
     483  PyDoc_STRVAR(rlock_release_save_doc,
     484  "_release_save() -> tuple\n\
     485  \n\
     486  For internal use by `threading.Condition`.");
     487  
     488  static PyObject *
     489  rlock_recursion_count(rlockobject *self, PyObject *Py_UNUSED(ignored))
     490  {
     491      unsigned long tid = PyThread_get_thread_ident();
     492      return PyLong_FromUnsignedLong(
     493          self->rlock_owner == tid ? self->rlock_count : 0UL);
     494  }
     495  
     496  PyDoc_STRVAR(rlock_recursion_count_doc,
     497  "_recursion_count() -> int\n\
     498  \n\
     499  For internal use by reentrancy checks.");
     500  
     501  static PyObject *
     502  rlock_is_owned(rlockobject *self, PyObject *Py_UNUSED(ignored))
     503  {
     504      unsigned long tid = PyThread_get_thread_ident();
     505  
     506      if (self->rlock_count > 0 && self->rlock_owner == tid) {
     507          Py_RETURN_TRUE;
     508      }
     509      Py_RETURN_FALSE;
     510  }
     511  
     512  PyDoc_STRVAR(rlock_is_owned_doc,
     513  "_is_owned() -> bool\n\
     514  \n\
     515  For internal use by `threading.Condition`.");
     516  
     517  static PyObject *
     518  rlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     519  {
     520      rlockobject *self = (rlockobject *) type->tp_alloc(type, 0);
     521      if (self == NULL) {
     522          return NULL;
     523      }
     524      self->in_weakreflist = NULL;
     525      self->rlock_owner = 0;
     526      self->rlock_count = 0;
     527  
     528      self->rlock_lock = PyThread_allocate_lock();
     529      if (self->rlock_lock == NULL) {
     530          Py_DECREF(self);
     531          PyErr_SetString(ThreadError, "can't allocate lock");
     532          return NULL;
     533      }
     534      return (PyObject *) self;
     535  }
     536  
     537  static PyObject *
     538  rlock_repr(rlockobject *self)
     539  {
     540      return PyUnicode_FromFormat("<%s %s object owner=%ld count=%lu at %p>",
     541          self->rlock_count ? "locked" : "unlocked",
     542          Py_TYPE(self)->tp_name, self->rlock_owner,
     543          self->rlock_count, self);
     544  }
     545  
     546  
     547  #ifdef HAVE_FORK
     548  static PyObject *
     549  rlock__at_fork_reinit(rlockobject *self, PyObject *Py_UNUSED(args))
     550  {
     551      if (_PyThread_at_fork_reinit(&self->rlock_lock) < 0) {
     552          PyErr_SetString(ThreadError, "failed to reinitialize lock at fork");
     553          return NULL;
     554      }
     555  
     556      self->rlock_owner = 0;
     557      self->rlock_count = 0;
     558  
     559      Py_RETURN_NONE;
     560  }
     561  #endif  /* HAVE_FORK */
     562  
     563  
     564  static PyMethodDef rlock_methods[] = {
     565      {"acquire",      _PyCFunction_CAST(rlock_acquire),
     566       METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
     567      {"release",      (PyCFunction)rlock_release,
     568       METH_NOARGS, rlock_release_doc},
     569      {"_is_owned",     (PyCFunction)rlock_is_owned,
     570       METH_NOARGS, rlock_is_owned_doc},
     571      {"_acquire_restore", (PyCFunction)rlock_acquire_restore,
     572       METH_VARARGS, rlock_acquire_restore_doc},
     573      {"_release_save", (PyCFunction)rlock_release_save,
     574       METH_NOARGS, rlock_release_save_doc},
     575      {"_recursion_count", (PyCFunction)rlock_recursion_count,
     576       METH_NOARGS, rlock_recursion_count_doc},
     577      {"__enter__",    _PyCFunction_CAST(rlock_acquire),
     578       METH_VARARGS | METH_KEYWORDS, rlock_acquire_doc},
     579      {"__exit__",    (PyCFunction)rlock_release,
     580       METH_VARARGS, rlock_release_doc},
     581  #ifdef HAVE_FORK
     582      {"_at_fork_reinit",    (PyCFunction)rlock__at_fork_reinit,
     583       METH_NOARGS, NULL},
     584  #endif
     585      {NULL,           NULL}              /* sentinel */
     586  };
     587  
     588  
     589  static PyMemberDef rlock_type_members[] = {
     590      {"__weaklistoffset__", T_PYSSIZET, offsetof(rlockobject, in_weakreflist), READONLY},
     591      {NULL},
     592  };
     593  
     594  static PyType_Slot rlock_type_slots[] = {
     595      {Py_tp_dealloc, (destructor)rlock_dealloc},
     596      {Py_tp_repr, (reprfunc)rlock_repr},
     597      {Py_tp_methods, rlock_methods},
     598      {Py_tp_alloc, PyType_GenericAlloc},
     599      {Py_tp_new, rlock_new},
     600      {Py_tp_members, rlock_type_members},
     601      {Py_tp_traverse, rlock_traverse},
     602      {0, 0},
     603  };
     604  
     605  static PyType_Spec rlock_type_spec = {
     606      .name = "_thread.RLock",
     607      .basicsize = sizeof(rlockobject),
     608      .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
     609                Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_IMMUTABLETYPE),
     610      .slots = rlock_type_slots,
     611  };
     612  
     613  static lockobject *
     614  newlockobject(PyObject *module)
     615  {
     616      thread_module_state *state = get_thread_state(module);
     617  
     618      PyTypeObject *type = state->lock_type;
     619      lockobject *self = (lockobject *)type->tp_alloc(type, 0);
     620      if (self == NULL) {
     621          return NULL;
     622      }
     623  
     624      self->lock_lock = PyThread_allocate_lock();
     625      self->locked = 0;
     626      self->in_weakreflist = NULL;
     627  
     628      if (self->lock_lock == NULL) {
     629          Py_DECREF(self);
     630          PyErr_SetString(ThreadError, "can't allocate lock");
     631          return NULL;
     632      }
     633      return self;
     634  }
     635  
     636  /* Thread-local objects */
     637  
     638  /* Quick overview:
     639  
     640     We need to be able to reclaim reference cycles as soon as possible
     641     (both when a thread is being terminated, or a thread-local object
     642      becomes unreachable from user data).  Constraints:
     643     - it must not be possible for thread-state dicts to be involved in
     644       reference cycles (otherwise the cyclic GC will refuse to consider
     645       objects referenced from a reachable thread-state dict, even though
     646       local_dealloc would clear them)
     647     - the death of a thread-state dict must still imply destruction of the
     648       corresponding local dicts in all thread-local objects.
     649  
     650     Our implementation uses small "localdummy" objects in order to break
     651     the reference chain. These trivial objects are hashable (using the
     652     default scheme of identity hashing) and weakrefable.
     653     Each thread-state holds a separate localdummy for each local object
     654     (as a /strong reference/),
     655     and each thread-local object holds a dict mapping /weak references/
     656     of localdummies to local dicts.
     657  
     658     Therefore:
     659     - only the thread-state dict holds a strong reference to the dummies
     660     - only the thread-local object holds a strong reference to the local dicts
     661     - only outside objects (application- or library-level) hold strong
     662       references to the thread-local objects
     663     - as soon as a thread-state dict is destroyed, the weakref callbacks of all
     664       dummies attached to that thread are called, and destroy the corresponding
     665       local dicts from thread-local objects
     666     - as soon as a thread-local object is destroyed, its local dicts are
     667       destroyed and its dummies are manually removed from all thread states
     668     - the GC can do its work correctly when a thread-local object is dangling,
     669       without any interference from the thread-state dicts
     670  
     671     As an additional optimization, each localdummy holds a borrowed reference
     672     to the corresponding localdict.  This borrowed reference is only used
     673     by the thread-local object which has created the localdummy, which should
     674     guarantee that the localdict still exists when accessed.
     675  */
     676  
     677  typedef struct {
     678      PyObject_HEAD
     679      PyObject *localdict;        /* Borrowed reference! */
     680      PyObject *weakreflist;      /* List of weak references to self */
     681  } localdummyobject;
     682  
     683  static void
     684  localdummy_dealloc(localdummyobject *self)
     685  {
     686      if (self->weakreflist != NULL)
     687          PyObject_ClearWeakRefs((PyObject *) self);
     688      PyTypeObject *tp = Py_TYPE(self);
     689      tp->tp_free((PyObject*)self);
     690      Py_DECREF(tp);
     691  }
     692  
     693  static PyMemberDef local_dummy_type_members[] = {
     694      {"__weaklistoffset__", T_PYSSIZET, offsetof(localdummyobject, weakreflist), READONLY},
     695      {NULL},
     696  };
     697  
     698  static PyType_Slot local_dummy_type_slots[] = {
     699      {Py_tp_dealloc, (destructor)localdummy_dealloc},
     700      {Py_tp_doc, "Thread-local dummy"},
     701      {Py_tp_members, local_dummy_type_members},
     702      {0, 0}
     703  };
     704  
     705  static PyType_Spec local_dummy_type_spec = {
     706      .name = "_thread._localdummy",
     707      .basicsize = sizeof(localdummyobject),
     708      .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION |
     709                Py_TPFLAGS_IMMUTABLETYPE),
     710      .slots = local_dummy_type_slots,
     711  };
     712  
     713  
     714  typedef struct {
     715      PyObject_HEAD
     716      PyObject *key;
     717      PyObject *args;
     718      PyObject *kw;
     719      PyObject *weakreflist;      /* List of weak references to self */
     720      /* A {localdummy weakref -> localdict} dict */
     721      PyObject *dummies;
     722      /* The callback for weakrefs to localdummies */
     723      PyObject *wr_callback;
     724  } localobject;
     725  
     726  /* Forward declaration */
     727  static PyObject *_ldict(localobject *self, thread_module_state *state);
     728  static PyObject *_localdummy_destroyed(PyObject *meth_self, PyObject *dummyweakref);
     729  
     730  /* Create and register the dummy for the current thread.
     731     Returns a borrowed reference of the corresponding local dict */
     732  static PyObject *
     733  _local_create_dummy(localobject *self, thread_module_state *state)
     734  {
     735      PyObject *ldict = NULL, *wr = NULL;
     736      localdummyobject *dummy = NULL;
     737      PyTypeObject *type = state->local_dummy_type;
     738  
     739      PyObject *tdict = PyThreadState_GetDict();
     740      if (tdict == NULL) {
     741          PyErr_SetString(PyExc_SystemError,
     742                          "Couldn't get thread-state dictionary");
     743          goto err;
     744      }
     745  
     746      ldict = PyDict_New();
     747      if (ldict == NULL) {
     748          goto err;
     749      }
     750      dummy = (localdummyobject *) type->tp_alloc(type, 0);
     751      if (dummy == NULL) {
     752          goto err;
     753      }
     754      dummy->localdict = ldict;
     755      wr = PyWeakref_NewRef((PyObject *) dummy, self->wr_callback);
     756      if (wr == NULL) {
     757          goto err;
     758      }
     759  
     760      /* As a side-effect, this will cache the weakref's hash before the
     761         dummy gets deleted */
     762      int r = PyDict_SetItem(self->dummies, wr, ldict);
     763      if (r < 0) {
     764          goto err;
     765      }
     766      Py_CLEAR(wr);
     767      r = PyDict_SetItem(tdict, self->key, (PyObject *) dummy);
     768      if (r < 0) {
     769          goto err;
     770      }
     771      Py_CLEAR(dummy);
     772  
     773      Py_DECREF(ldict);
     774      return ldict;
     775  
     776  err:
     777      Py_XDECREF(ldict);
     778      Py_XDECREF(wr);
     779      Py_XDECREF(dummy);
     780      return NULL;
     781  }
     782  
     783  static PyObject *
     784  local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
     785  {
     786      static PyMethodDef wr_callback_def = {
     787          "_localdummy_destroyed", (PyCFunction) _localdummy_destroyed, METH_O
     788      };
     789  
     790      if (type->tp_init == PyBaseObject_Type.tp_init) {
     791          int rc = 0;
     792          if (args != NULL)
     793              rc = PyObject_IsTrue(args);
     794          if (rc == 0 && kw != NULL)
     795              rc = PyObject_IsTrue(kw);
     796          if (rc != 0) {
     797              if (rc > 0) {
     798                  PyErr_SetString(PyExc_TypeError,
     799                            "Initialization arguments are not supported");
     800              }
     801              return NULL;
     802          }
     803      }
     804  
     805      PyObject *module = PyType_GetModuleByDef(type, &thread_module);
     806      thread_module_state *state = get_thread_state(module);
     807  
     808      localobject *self = (localobject *)type->tp_alloc(type, 0);
     809      if (self == NULL) {
     810          return NULL;
     811      }
     812  
     813      self->args = Py_XNewRef(args);
     814      self->kw = Py_XNewRef(kw);
     815      self->key = PyUnicode_FromFormat("thread.local.%p", self);
     816      if (self->key == NULL) {
     817          goto err;
     818      }
     819  
     820      self->dummies = PyDict_New();
     821      if (self->dummies == NULL) {
     822          goto err;
     823      }
     824  
     825      /* We use a weak reference to self in the callback closure
     826         in order to avoid spurious reference cycles */
     827      PyObject *wr = PyWeakref_NewRef((PyObject *) self, NULL);
     828      if (wr == NULL) {
     829          goto err;
     830      }
     831      self->wr_callback = PyCFunction_NewEx(&wr_callback_def, wr, NULL);
     832      Py_DECREF(wr);
     833      if (self->wr_callback == NULL) {
     834          goto err;
     835      }
     836      if (_local_create_dummy(self, state) == NULL) {
     837          goto err;
     838      }
     839      return (PyObject *)self;
     840  
     841    err:
     842      Py_DECREF(self);
     843      return NULL;
     844  }
     845  
     846  static int
     847  local_traverse(localobject *self, visitproc visit, void *arg)
     848  {
     849      Py_VISIT(Py_TYPE(self));
     850      Py_VISIT(self->args);
     851      Py_VISIT(self->kw);
     852      Py_VISIT(self->dummies);
     853      return 0;
     854  }
     855  
     856  #define HEAD_LOCK(runtime) \
     857      PyThread_acquire_lock((runtime)->interpreters.mutex, WAIT_LOCK)
     858  #define HEAD_UNLOCK(runtime) \
     859      PyThread_release_lock((runtime)->interpreters.mutex)
     860  
     861  static int
     862  local_clear(localobject *self)
     863  {
     864      Py_CLEAR(self->args);
     865      Py_CLEAR(self->kw);
     866      Py_CLEAR(self->dummies);
     867      Py_CLEAR(self->wr_callback);
     868      /* Remove all strong references to dummies from the thread states */
     869      if (self->key) {
     870          PyInterpreterState *interp = _PyInterpreterState_GET();
     871          _PyRuntimeState *runtime = &_PyRuntime;
     872          HEAD_LOCK(runtime);
     873          PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
     874          HEAD_UNLOCK(runtime);
     875          while (tstate) {
     876              if (tstate->dict) {
     877                  PyObject *v = _PyDict_Pop(tstate->dict, self->key, Py_None);
     878                  if (v != NULL) {
     879                      Py_DECREF(v);
     880                  }
     881                  else {
     882                      PyErr_Clear();
     883                  }
     884              }
     885              HEAD_LOCK(runtime);
     886              tstate = PyThreadState_Next(tstate);
     887              HEAD_UNLOCK(runtime);
     888          }
     889      }
     890      return 0;
     891  }
     892  
     893  static void
     894  local_dealloc(localobject *self)
     895  {
     896      /* Weakrefs must be invalidated right now, otherwise they can be used
     897         from code called below, which is very dangerous since Py_REFCNT(self) == 0 */
     898      if (self->weakreflist != NULL) {
     899          PyObject_ClearWeakRefs((PyObject *) self);
     900      }
     901  
     902      PyObject_GC_UnTrack(self);
     903  
     904      local_clear(self);
     905      Py_XDECREF(self->key);
     906  
     907      PyTypeObject *tp = Py_TYPE(self);
     908      tp->tp_free((PyObject*)self);
     909      Py_DECREF(tp);
     910  }
     911  
     912  /* Returns a borrowed reference to the local dict, creating it if necessary */
     913  static PyObject *
     914  _ldict(localobject *self, thread_module_state *state)
     915  {
     916      PyObject *tdict = PyThreadState_GetDict();
     917      if (tdict == NULL) {
     918          PyErr_SetString(PyExc_SystemError,
     919                          "Couldn't get thread-state dictionary");
     920          return NULL;
     921      }
     922  
     923      PyObject *ldict;
     924      PyObject *dummy = PyDict_GetItemWithError(tdict, self->key);
     925      if (dummy == NULL) {
     926          if (PyErr_Occurred()) {
     927              return NULL;
     928          }
     929          ldict = _local_create_dummy(self, state);
     930          if (ldict == NULL)
     931              return NULL;
     932  
     933          if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init &&
     934              Py_TYPE(self)->tp_init((PyObject*)self,
     935                                     self->args, self->kw) < 0) {
     936              /* we need to get rid of ldict from thread so
     937                 we create a new one the next time we do an attr
     938                 access */
     939              PyDict_DelItem(tdict, self->key);
     940              return NULL;
     941          }
     942      }
     943      else {
     944          assert(Py_IS_TYPE(dummy, state->local_dummy_type));
     945          ldict = ((localdummyobject *) dummy)->localdict;
     946      }
     947  
     948      return ldict;
     949  }
     950  
     951  static int
     952  local_setattro(localobject *self, PyObject *name, PyObject *v)
     953  {
     954      PyObject *module = PyType_GetModuleByDef(Py_TYPE(self), &thread_module);
     955      thread_module_state *state = get_thread_state(module);
     956  
     957      PyObject *ldict = _ldict(self, state);
     958      if (ldict == NULL) {
     959          return -1;
     960      }
     961  
     962      int r = PyObject_RichCompareBool(name, &_Py_ID(__dict__), Py_EQ);
     963      if (r == -1) {
     964          return -1;
     965      }
     966      if (r == 1) {
     967          PyErr_Format(PyExc_AttributeError,
     968                       "'%.50s' object attribute '%U' is read-only",
     969                       Py_TYPE(self)->tp_name, name);
     970          return -1;
     971      }
     972  
     973      return _PyObject_GenericSetAttrWithDict((PyObject *)self, name, v, ldict);
     974  }
     975  
     976  static PyObject *local_getattro(localobject *, PyObject *);
     977  
     978  static PyMemberDef local_type_members[] = {
     979      {"__weaklistoffset__", T_PYSSIZET, offsetof(localobject, weakreflist), READONLY},
     980      {NULL},
     981  };
     982  
     983  static PyType_Slot local_type_slots[] = {
     984      {Py_tp_dealloc, (destructor)local_dealloc},
     985      {Py_tp_getattro, (getattrofunc)local_getattro},
     986      {Py_tp_setattro, (setattrofunc)local_setattro},
     987      {Py_tp_doc, "Thread-local data"},
     988      {Py_tp_traverse, (traverseproc)local_traverse},
     989      {Py_tp_clear, (inquiry)local_clear},
     990      {Py_tp_new, local_new},
     991      {Py_tp_members, local_type_members},
     992      {0, 0}
     993  };
     994  
     995  static PyType_Spec local_type_spec = {
     996      .name = "_thread._local",
     997      .basicsize = sizeof(localobject),
     998      .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
     999                Py_TPFLAGS_IMMUTABLETYPE),
    1000      .slots = local_type_slots,
    1001  };
    1002  
    1003  static PyObject *
    1004  local_getattro(localobject *self, PyObject *name)
    1005  {
    1006      PyObject *module = PyType_GetModuleByDef(Py_TYPE(self), &thread_module);
    1007      thread_module_state *state = get_thread_state(module);
    1008  
    1009      PyObject *ldict = _ldict(self, state);
    1010      if (ldict == NULL)
    1011          return NULL;
    1012  
    1013      int r = PyObject_RichCompareBool(name, &_Py_ID(__dict__), Py_EQ);
    1014      if (r == 1) {
    1015          return Py_NewRef(ldict);
    1016      }
    1017      if (r == -1) {
    1018          return NULL;
    1019      }
    1020  
    1021      if (!Py_IS_TYPE(self, state->local_type)) {
    1022          /* use generic lookup for subtypes */
    1023          return _PyObject_GenericGetAttrWithDict((PyObject *)self, name,
    1024                                                  ldict, 0);
    1025      }
    1026  
    1027      /* Optimization: just look in dict ourselves */
    1028      PyObject *value = PyDict_GetItemWithError(ldict, name);
    1029      if (value != NULL) {
    1030          return Py_NewRef(value);
    1031      }
    1032      if (PyErr_Occurred()) {
    1033          return NULL;
    1034      }
    1035  
    1036      /* Fall back on generic to get __class__ and __dict__ */
    1037      return _PyObject_GenericGetAttrWithDict(
    1038          (PyObject *)self, name, ldict, 0);
    1039  }
    1040  
    1041  /* Called when a dummy is destroyed. */
    1042  static PyObject *
    1043  _localdummy_destroyed(PyObject *localweakref, PyObject *dummyweakref)
    1044  {
    1045      assert(PyWeakref_CheckRef(localweakref));
    1046      PyObject *obj = PyWeakref_GET_OBJECT(localweakref);
    1047      if (obj == Py_None) {
    1048          Py_RETURN_NONE;
    1049      }
    1050  
    1051      /* If the thread-local object is still alive and not being cleared,
    1052         remove the corresponding local dict */
    1053      localobject *self = (localobject *)Py_NewRef(obj);
    1054      if (self->dummies != NULL) {
    1055          PyObject *ldict;
    1056          ldict = PyDict_GetItemWithError(self->dummies, dummyweakref);
    1057          if (ldict != NULL) {
    1058              PyDict_DelItem(self->dummies, dummyweakref);
    1059          }
    1060          if (PyErr_Occurred())
    1061              PyErr_WriteUnraisable(obj);
    1062      }
    1063      Py_DECREF(obj);
    1064      Py_RETURN_NONE;
    1065  }
    1066  
    1067  /* Module functions */
    1068  
    1069  struct bootstate {
    1070      PyThreadState *tstate;
    1071      PyObject *func;
    1072      PyObject *args;
    1073      PyObject *kwargs;
    1074  };
    1075  
    1076  
    1077  static void
    1078  thread_bootstate_free(struct bootstate *boot, int decref)
    1079  {
    1080      if (decref) {
    1081          Py_DECREF(boot->func);
    1082          Py_DECREF(boot->args);
    1083          Py_XDECREF(boot->kwargs);
    1084      }
    1085      PyMem_RawFree(boot);
    1086  }
    1087  
    1088  
    1089  static void
    1090  thread_run(void *boot_raw)
    1091  {
    1092      struct bootstate *boot = (struct bootstate *) boot_raw;
    1093      PyThreadState *tstate = boot->tstate;
    1094  
    1095      // gh-108987: If _thread.start_new_thread() is called before or while
    1096      // Python is being finalized, thread_run() can called *after*.
    1097      // _PyRuntimeState_SetFinalizing() is called. At this point, all Python
    1098      // threads must exit, except of the thread calling Py_Finalize() whch holds
    1099      // the GIL and must not exit.
    1100      //
    1101      // At this stage, tstate can be a dangling pointer (point to freed memory),
    1102      // it's ok to call _PyThreadState_MustExit() with a dangling pointer.
    1103      if (_PyThreadState_MustExit(tstate)) {
    1104          // Don't call PyThreadState_Clear() nor _PyThreadState_DeleteCurrent().
    1105          // These functions are called on tstate indirectly by Py_Finalize()
    1106          // which calls _PyInterpreterState_Clear().
    1107          //
    1108          // Py_DECREF() cannot be called because the GIL is not held: leak
    1109          // references on purpose. Python is being finalized anyway.
    1110          thread_bootstate_free(boot, 0);
    1111          goto exit;
    1112      }
    1113  
    1114      tstate->thread_id = PyThread_get_thread_ident();
    1115  #ifdef PY_HAVE_THREAD_NATIVE_ID
    1116      tstate->native_thread_id = PyThread_get_thread_native_id();
    1117  #else
    1118      tstate->native_thread_id = 0;
    1119  #endif
    1120      _PyThreadState_SetCurrent(tstate);
    1121      PyEval_AcquireThread(tstate);
    1122      tstate->interp->threads.count++;
    1123  
    1124      PyObject *res = PyObject_Call(boot->func, boot->args, boot->kwargs);
    1125      if (res == NULL) {
    1126          if (PyErr_ExceptionMatches(PyExc_SystemExit))
    1127              /* SystemExit is ignored silently */
    1128              PyErr_Clear();
    1129          else {
    1130              _PyErr_WriteUnraisableMsg("in thread started by", boot->func);
    1131          }
    1132      }
    1133      else {
    1134          Py_DECREF(res);
    1135      }
    1136  
    1137      thread_bootstate_free(boot, 1);
    1138  
    1139      tstate->interp->threads.count--;
    1140      PyThreadState_Clear(tstate);
    1141      _PyThreadState_DeleteCurrent(tstate);
    1142  
    1143  exit:
    1144      // bpo-44434: Don't call explicitly PyThread_exit_thread(). On Linux with
    1145      // the glibc, pthread_exit() can abort the whole process if dlopen() fails
    1146      // to open the libgcc_s.so library (ex: EMFILE error).
    1147      return;
    1148  }
    1149  
    1150  static PyObject *
    1151  thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
    1152  {
    1153      PyObject *func, *args, *kwargs = NULL;
    1154  
    1155      if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3,
    1156                             &func, &args, &kwargs))
    1157          return NULL;
    1158      if (!PyCallable_Check(func)) {
    1159          PyErr_SetString(PyExc_TypeError,
    1160                          "first arg must be callable");
    1161          return NULL;
    1162      }
    1163      if (!PyTuple_Check(args)) {
    1164          PyErr_SetString(PyExc_TypeError,
    1165                          "2nd arg must be a tuple");
    1166          return NULL;
    1167      }
    1168      if (kwargs != NULL && !PyDict_Check(kwargs)) {
    1169          PyErr_SetString(PyExc_TypeError,
    1170                          "optional 3rd arg must be a dictionary");
    1171          return NULL;
    1172      }
    1173  
    1174      PyInterpreterState *interp = _PyInterpreterState_GET();
    1175      if (interp->config._isolated_interpreter) {
    1176          PyErr_SetString(PyExc_RuntimeError,
    1177                          "thread is not supported for isolated subinterpreters");
    1178          return NULL;
    1179      }
    1180  
    1181      // gh-109795: Use PyMem_RawMalloc() instead of PyMem_Malloc(),
    1182      // because it should be possible to call thread_bootstate_free()
    1183      // without holding the GIL.
    1184      struct bootstate *boot = PyMem_RawMalloc(sizeof(struct bootstate));
    1185      if (boot == NULL) {
    1186          return PyErr_NoMemory();
    1187      }
    1188      boot->tstate = _PyThreadState_Prealloc(interp);
    1189      if (boot->tstate == NULL) {
    1190          PyMem_RawFree(boot);
    1191          return PyErr_NoMemory();
    1192      }
    1193      boot->func = Py_NewRef(func);
    1194      boot->args = Py_NewRef(args);
    1195      boot->kwargs = Py_XNewRef(kwargs);
    1196  
    1197      unsigned long ident = PyThread_start_new_thread(thread_run, (void*) boot);
    1198      if (ident == PYTHREAD_INVALID_THREAD_ID) {
    1199          PyErr_SetString(ThreadError, "can't start new thread");
    1200          PyThreadState_Clear(boot->tstate);
    1201          thread_bootstate_free(boot, 1);
    1202          return NULL;
    1203      }
    1204      return PyLong_FromUnsignedLong(ident);
    1205  }
    1206  
    1207  PyDoc_STRVAR(start_new_doc,
    1208  "start_new_thread(function, args[, kwargs])\n\
    1209  (start_new() is an obsolete synonym)\n\
    1210  \n\
    1211  Start a new thread and return its identifier.  The thread will call the\n\
    1212  function with positional arguments from the tuple args and keyword arguments\n\
    1213  taken from the optional dictionary kwargs.  The thread exits when the\n\
    1214  function returns; the return value is ignored.  The thread will also exit\n\
    1215  when the function raises an unhandled exception; a stack trace will be\n\
    1216  printed unless the exception is SystemExit.\n");
    1217  
    1218  static PyObject *
    1219  thread_PyThread_exit_thread(PyObject *self, PyObject *Py_UNUSED(ignored))
    1220  {
    1221      PyErr_SetNone(PyExc_SystemExit);
    1222      return NULL;
    1223  }
    1224  
    1225  PyDoc_STRVAR(exit_doc,
    1226  "exit()\n\
    1227  (exit_thread() is an obsolete synonym)\n\
    1228  \n\
    1229  This is synonymous to ``raise SystemExit''.  It will cause the current\n\
    1230  thread to exit silently unless the exception is caught.");
    1231  
    1232  static PyObject *
    1233  thread_PyThread_interrupt_main(PyObject *self, PyObject *args)
    1234  {
    1235      int signum = SIGINT;
    1236      if (!PyArg_ParseTuple(args, "|i:signum", &signum)) {
    1237          return NULL;
    1238      }
    1239  
    1240      if (PyErr_SetInterruptEx(signum)) {
    1241          PyErr_SetString(PyExc_ValueError, "signal number out of range");
    1242          return NULL;
    1243      }
    1244      Py_RETURN_NONE;
    1245  }
    1246  
    1247  PyDoc_STRVAR(interrupt_doc,
    1248  "interrupt_main(signum=signal.SIGINT, /)\n\
    1249  \n\
    1250  Simulate the arrival of the given signal in the main thread,\n\
    1251  where the corresponding signal handler will be executed.\n\
    1252  If *signum* is omitted, SIGINT is assumed.\n\
    1253  A subthread can use this function to interrupt the main thread.\n\
    1254  \n\
    1255  Note: the default signal handler for SIGINT raises ``KeyboardInterrupt``."
    1256  );
    1257  
    1258  static lockobject *newlockobject(PyObject *module);
    1259  
    1260  static PyObject *
    1261  thread_PyThread_allocate_lock(PyObject *module, PyObject *Py_UNUSED(ignored))
    1262  {
    1263      return (PyObject *) newlockobject(module);
    1264  }
    1265  
    1266  PyDoc_STRVAR(allocate_doc,
    1267  "allocate_lock() -> lock object\n\
    1268  (allocate() is an obsolete synonym)\n\
    1269  \n\
    1270  Create a new lock object. See help(type(threading.Lock())) for\n\
    1271  information about locks.");
    1272  
    1273  static PyObject *
    1274  thread_get_ident(PyObject *self, PyObject *Py_UNUSED(ignored))
    1275  {
    1276      unsigned long ident = PyThread_get_thread_ident();
    1277      if (ident == PYTHREAD_INVALID_THREAD_ID) {
    1278          PyErr_SetString(ThreadError, "no current thread ident");
    1279          return NULL;
    1280      }
    1281      return PyLong_FromUnsignedLong(ident);
    1282  }
    1283  
    1284  PyDoc_STRVAR(get_ident_doc,
    1285  "get_ident() -> integer\n\
    1286  \n\
    1287  Return a non-zero integer that uniquely identifies the current thread\n\
    1288  amongst other threads that exist simultaneously.\n\
    1289  This may be used to identify per-thread resources.\n\
    1290  Even though on some platforms threads identities may appear to be\n\
    1291  allocated consecutive numbers starting at 1, this behavior should not\n\
    1292  be relied upon, and the number should be seen purely as a magic cookie.\n\
    1293  A thread's identity may be reused for another thread after it exits.");
    1294  
    1295  #ifdef PY_HAVE_THREAD_NATIVE_ID
    1296  static PyObject *
    1297  thread_get_native_id(PyObject *self, PyObject *Py_UNUSED(ignored))
    1298  {
    1299      unsigned long native_id = PyThread_get_thread_native_id();
    1300      return PyLong_FromUnsignedLong(native_id);
    1301  }
    1302  
    1303  PyDoc_STRVAR(get_native_id_doc,
    1304  "get_native_id() -> integer\n\
    1305  \n\
    1306  Return a non-negative integer identifying the thread as reported\n\
    1307  by the OS (kernel). This may be used to uniquely identify a\n\
    1308  particular thread within a system.");
    1309  #endif
    1310  
    1311  static PyObject *
    1312  thread__count(PyObject *self, PyObject *Py_UNUSED(ignored))
    1313  {
    1314      PyInterpreterState *interp = _PyInterpreterState_GET();
    1315      return PyLong_FromLong(interp->threads.count);
    1316  }
    1317  
    1318  PyDoc_STRVAR(_count_doc,
    1319  "_count() -> integer\n\
    1320  \n\
    1321  \
    1322  Return the number of currently running Python threads, excluding\n\
    1323  the main thread. The returned number comprises all threads created\n\
    1324  through `start_new_thread()` as well as `threading.Thread`, and not\n\
    1325  yet finished.\n\
    1326  \n\
    1327  This function is meant for internal and specialized purposes only.\n\
    1328  In most applications `threading.enumerate()` should be used instead.");
    1329  
    1330  static void
    1331  release_sentinel(void *wr_raw)
    1332  {
    1333      PyObject *wr = _PyObject_CAST(wr_raw);
    1334      /* Tricky: this function is called when the current thread state
    1335         is being deleted.  Therefore, only simple C code can safely
    1336         execute here. */
    1337      PyObject *obj = PyWeakref_GET_OBJECT(wr);
    1338      lockobject *lock;
    1339      if (obj != Py_None) {
    1340          lock = (lockobject *) obj;
    1341          if (lock->locked) {
    1342              PyThread_release_lock(lock->lock_lock);
    1343              lock->locked = 0;
    1344          }
    1345      }
    1346      /* Deallocating a weakref with a NULL callback only calls
    1347         PyObject_GC_Del(), which can't call any Python code. */
    1348      Py_DECREF(wr);
    1349  }
    1350  
    1351  static PyObject *
    1352  thread__set_sentinel(PyObject *module, PyObject *Py_UNUSED(ignored))
    1353  {
    1354      PyObject *wr;
    1355      PyThreadState *tstate = _PyThreadState_GET();
    1356      lockobject *lock;
    1357  
    1358      if (tstate->on_delete_data != NULL) {
    1359          /* We must support the re-creation of the lock from a
    1360             fork()ed child. */
    1361          assert(tstate->on_delete == &release_sentinel);
    1362          wr = (PyObject *) tstate->on_delete_data;
    1363          tstate->on_delete = NULL;
    1364          tstate->on_delete_data = NULL;
    1365          Py_DECREF(wr);
    1366      }
    1367      lock = newlockobject(module);
    1368      if (lock == NULL)
    1369          return NULL;
    1370      /* The lock is owned by whoever called _set_sentinel(), but the weakref
    1371         hangs to the thread state. */
    1372      wr = PyWeakref_NewRef((PyObject *) lock, NULL);
    1373      if (wr == NULL) {
    1374          Py_DECREF(lock);
    1375          return NULL;
    1376      }
    1377      tstate->on_delete_data = (void *) wr;
    1378      tstate->on_delete = &release_sentinel;
    1379      return (PyObject *) lock;
    1380  }
    1381  
    1382  PyDoc_STRVAR(_set_sentinel_doc,
    1383  "_set_sentinel() -> lock\n\
    1384  \n\
    1385  Set a sentinel lock that will be released when the current thread\n\
    1386  state is finalized (after it is untied from the interpreter).\n\
    1387  \n\
    1388  This is a private API for the threading module.");
    1389  
    1390  static PyObject *
    1391  thread_stack_size(PyObject *self, PyObject *args)
    1392  {
    1393      size_t old_size;
    1394      Py_ssize_t new_size = 0;
    1395      int rc;
    1396  
    1397      if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size))
    1398          return NULL;
    1399  
    1400      if (new_size < 0) {
    1401          PyErr_SetString(PyExc_ValueError,
    1402                          "size must be 0 or a positive value");
    1403          return NULL;
    1404      }
    1405  
    1406      old_size = PyThread_get_stacksize();
    1407  
    1408      rc = PyThread_set_stacksize((size_t) new_size);
    1409      if (rc == -1) {
    1410          PyErr_Format(PyExc_ValueError,
    1411                       "size not valid: %zd bytes",
    1412                       new_size);
    1413          return NULL;
    1414      }
    1415      if (rc == -2) {
    1416          PyErr_SetString(ThreadError,
    1417                          "setting stack size not supported");
    1418          return NULL;
    1419      }
    1420  
    1421      return PyLong_FromSsize_t((Py_ssize_t) old_size);
    1422  }
    1423  
    1424  PyDoc_STRVAR(stack_size_doc,
    1425  "stack_size([size]) -> size\n\
    1426  \n\
    1427  Return the thread stack size used when creating new threads.  The\n\
    1428  optional size argument specifies the stack size (in bytes) to be used\n\
    1429  for subsequently created threads, and must be 0 (use platform or\n\
    1430  configured default) or a positive integer value of at least 32,768 (32k).\n\
    1431  If changing the thread stack size is unsupported, a ThreadError\n\
    1432  exception is raised.  If the specified size is invalid, a ValueError\n\
    1433  exception is raised, and the stack size is unmodified.  32k bytes\n\
    1434   currently the minimum supported stack size value to guarantee\n\
    1435  sufficient stack space for the interpreter itself.\n\
    1436  \n\
    1437  Note that some platforms may have particular restrictions on values for\n\
    1438  the stack size, such as requiring a minimum stack size larger than 32 KiB or\n\
    1439  requiring allocation in multiples of the system memory page size\n\
    1440  - platform documentation should be referred to for more information\n\
    1441  (4 KiB pages are common; using multiples of 4096 for the stack size is\n\
    1442  the suggested approach in the absence of more specific information).");
    1443  
    1444  static int
    1445  thread_excepthook_file(PyObject *file, PyObject *exc_type, PyObject *exc_value,
    1446                         PyObject *exc_traceback, PyObject *thread)
    1447  {
    1448      /* print(f"Exception in thread {thread.name}:", file=file) */
    1449      if (PyFile_WriteString("Exception in thread ", file) < 0) {
    1450          return -1;
    1451      }
    1452  
    1453      PyObject *name = NULL;
    1454      if (thread != Py_None) {
    1455          if (_PyObject_LookupAttr(thread, &_Py_ID(name), &name) < 0) {
    1456              return -1;
    1457          }
    1458      }
    1459      if (name != NULL) {
    1460          if (PyFile_WriteObject(name, file, Py_PRINT_RAW) < 0) {
    1461              Py_DECREF(name);
    1462              return -1;
    1463          }
    1464          Py_DECREF(name);
    1465      }
    1466      else {
    1467          unsigned long ident = PyThread_get_thread_ident();
    1468          PyObject *str = PyUnicode_FromFormat("%lu", ident);
    1469          if (str != NULL) {
    1470              if (PyFile_WriteObject(str, file, Py_PRINT_RAW) < 0) {
    1471                  Py_DECREF(str);
    1472                  return -1;
    1473              }
    1474              Py_DECREF(str);
    1475          }
    1476          else {
    1477              PyErr_Clear();
    1478  
    1479              if (PyFile_WriteString("<failed to get thread name>", file) < 0) {
    1480                  return -1;
    1481              }
    1482          }
    1483      }
    1484  
    1485      if (PyFile_WriteString(":\n", file) < 0) {
    1486          return -1;
    1487      }
    1488  
    1489      /* Display the traceback */
    1490      _PyErr_Display(file, exc_type, exc_value, exc_traceback);
    1491  
    1492      /* Call file.flush() */
    1493      PyObject *res = PyObject_CallMethodNoArgs(file, &_Py_ID(flush));
    1494      if (!res) {
    1495          return -1;
    1496      }
    1497      Py_DECREF(res);
    1498  
    1499      return 0;
    1500  }
    1501  
    1502  
    1503  PyDoc_STRVAR(ExceptHookArgs__doc__,
    1504  "ExceptHookArgs\n\
    1505  \n\
    1506  Type used to pass arguments to threading.excepthook.");
    1507  
    1508  static PyStructSequence_Field ExceptHookArgs_fields[] = {
    1509      {"exc_type", "Exception type"},
    1510      {"exc_value", "Exception value"},
    1511      {"exc_traceback", "Exception traceback"},
    1512      {"thread", "Thread"},
    1513      {0}
    1514  };
    1515  
    1516  static PyStructSequence_Desc ExceptHookArgs_desc = {
    1517      .name = "_thread._ExceptHookArgs",
    1518      .doc = ExceptHookArgs__doc__,
    1519      .fields = ExceptHookArgs_fields,
    1520      .n_in_sequence = 4
    1521  };
    1522  
    1523  
    1524  static PyObject *
    1525  thread_excepthook(PyObject *module, PyObject *args)
    1526  {
    1527      thread_module_state *state = get_thread_state(module);
    1528  
    1529      if (!Py_IS_TYPE(args, state->excepthook_type)) {
    1530          PyErr_SetString(PyExc_TypeError,
    1531                          "_thread.excepthook argument type "
    1532                          "must be ExceptHookArgs");
    1533          return NULL;
    1534      }
    1535  
    1536      /* Borrowed reference */
    1537      PyObject *exc_type = PyStructSequence_GET_ITEM(args, 0);
    1538      if (exc_type == PyExc_SystemExit) {
    1539          /* silently ignore SystemExit */
    1540          Py_RETURN_NONE;
    1541      }
    1542  
    1543      /* Borrowed references */
    1544      PyObject *exc_value = PyStructSequence_GET_ITEM(args, 1);
    1545      PyObject *exc_tb = PyStructSequence_GET_ITEM(args, 2);
    1546      PyObject *thread = PyStructSequence_GET_ITEM(args, 3);
    1547  
    1548      PyThreadState *tstate = _PyThreadState_GET();
    1549      PyObject *file = _PySys_GetAttr(tstate, &_Py_ID(stderr));
    1550      if (file == NULL || file == Py_None) {
    1551          if (thread == Py_None) {
    1552              /* do nothing if sys.stderr is None and thread is None */
    1553              Py_RETURN_NONE;
    1554          }
    1555  
    1556          file = PyObject_GetAttrString(thread, "_stderr");
    1557          if (file == NULL) {
    1558              return NULL;
    1559          }
    1560          if (file == Py_None) {
    1561              Py_DECREF(file);
    1562              /* do nothing if sys.stderr is None and sys.stderr was None
    1563                 when the thread was created */
    1564              Py_RETURN_NONE;
    1565          }
    1566      }
    1567      else {
    1568          Py_INCREF(file);
    1569      }
    1570  
    1571      int res = thread_excepthook_file(file, exc_type, exc_value, exc_tb,
    1572                                       thread);
    1573      Py_DECREF(file);
    1574      if (res < 0) {
    1575          return NULL;
    1576      }
    1577  
    1578      Py_RETURN_NONE;
    1579  }
    1580  
    1581  PyDoc_STRVAR(excepthook_doc,
    1582  "excepthook(exc_type, exc_value, exc_traceback, thread)\n\
    1583  \n\
    1584  Handle uncaught Thread.run() exception.");
    1585  
    1586  static PyMethodDef thread_methods[] = {
    1587      {"start_new_thread",        (PyCFunction)thread_PyThread_start_new_thread,
    1588       METH_VARARGS, start_new_doc},
    1589      {"start_new",               (PyCFunction)thread_PyThread_start_new_thread,
    1590       METH_VARARGS, start_new_doc},
    1591      {"allocate_lock",           thread_PyThread_allocate_lock,
    1592       METH_NOARGS, allocate_doc},
    1593      {"allocate",                thread_PyThread_allocate_lock,
    1594       METH_NOARGS, allocate_doc},
    1595      {"exit_thread",             thread_PyThread_exit_thread,
    1596       METH_NOARGS, exit_doc},
    1597      {"exit",                    thread_PyThread_exit_thread,
    1598       METH_NOARGS, exit_doc},
    1599      {"interrupt_main",          (PyCFunction)thread_PyThread_interrupt_main,
    1600       METH_VARARGS, interrupt_doc},
    1601      {"get_ident",               thread_get_ident,
    1602       METH_NOARGS, get_ident_doc},
    1603  #ifdef PY_HAVE_THREAD_NATIVE_ID
    1604      {"get_native_id",           thread_get_native_id,
    1605       METH_NOARGS, get_native_id_doc},
    1606  #endif
    1607      {"_count",                  thread__count,
    1608       METH_NOARGS, _count_doc},
    1609      {"stack_size",              (PyCFunction)thread_stack_size,
    1610       METH_VARARGS, stack_size_doc},
    1611      {"_set_sentinel",           thread__set_sentinel,
    1612       METH_NOARGS, _set_sentinel_doc},
    1613      {"_excepthook",              thread_excepthook,
    1614       METH_O, excepthook_doc},
    1615      {NULL,                      NULL}           /* sentinel */
    1616  };
    1617  
    1618  
    1619  /* Initialization function */
    1620  
    1621  static int
    1622  thread_module_exec(PyObject *module)
    1623  {
    1624      thread_module_state *state = get_thread_state(module);
    1625      PyObject *d = PyModule_GetDict(module);
    1626  
    1627      // Initialize the C thread library
    1628      PyThread_init_thread();
    1629  
    1630      // Lock
    1631      state->lock_type = (PyTypeObject *)PyType_FromSpec(&lock_type_spec);
    1632      if (state->lock_type == NULL) {
    1633          return -1;
    1634      }
    1635      if (PyDict_SetItemString(d, "LockType", (PyObject *)state->lock_type) < 0) {
    1636          return -1;
    1637      }
    1638  
    1639      // RLock
    1640      PyTypeObject *rlock_type = (PyTypeObject *)PyType_FromSpec(&rlock_type_spec);
    1641      if (rlock_type == NULL) {
    1642          return -1;
    1643      }
    1644      if (PyModule_AddType(module, rlock_type) < 0) {
    1645          Py_DECREF(rlock_type);
    1646          return -1;
    1647      }
    1648      Py_DECREF(rlock_type);
    1649  
    1650      // Local dummy
    1651      state->local_dummy_type = (PyTypeObject *)PyType_FromSpec(&local_dummy_type_spec);
    1652      if (state->local_dummy_type == NULL) {
    1653          return -1;
    1654      }
    1655  
    1656      // Local
    1657      state->local_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, &local_type_spec, NULL);
    1658      if (state->local_type == NULL) {
    1659          return -1;
    1660      }
    1661      if (PyModule_AddType(module, state->local_type) < 0) {
    1662          return -1;
    1663      }
    1664  
    1665      // Add module attributes
    1666      if (PyDict_SetItemString(d, "error", ThreadError) < 0) {
    1667          return -1;
    1668      }
    1669  
    1670      // _ExceptHookArgs type
    1671      state->excepthook_type = PyStructSequence_NewType(&ExceptHookArgs_desc);
    1672      if (state->excepthook_type == NULL) {
    1673          return -1;
    1674      }
    1675      if (PyModule_AddType(module, state->excepthook_type) < 0) {
    1676          return -1;
    1677      }
    1678  
    1679      // TIMEOUT_MAX
    1680      double timeout_max = (double)PY_TIMEOUT_MAX * 1e-6;
    1681      double time_max = _PyTime_AsSecondsDouble(_PyTime_MAX);
    1682      timeout_max = Py_MIN(timeout_max, time_max);
    1683      // Round towards minus infinity
    1684      timeout_max = floor(timeout_max);
    1685  
    1686      if (_PyModule_Add(module, "TIMEOUT_MAX",
    1687                          PyFloat_FromDouble(timeout_max)) < 0) {
    1688          return -1;
    1689      }
    1690  
    1691      return 0;
    1692  }
    1693  
    1694  
    1695  static int
    1696  thread_module_traverse(PyObject *module, visitproc visit, void *arg)
    1697  {
    1698      thread_module_state *state = get_thread_state(module);
    1699      Py_VISIT(state->excepthook_type);
    1700      Py_VISIT(state->lock_type);
    1701      Py_VISIT(state->local_type);
    1702      Py_VISIT(state->local_dummy_type);
    1703      return 0;
    1704  }
    1705  
    1706  static int
    1707  thread_module_clear(PyObject *module)
    1708  {
    1709      thread_module_state *state = get_thread_state(module);
    1710      Py_CLEAR(state->excepthook_type);
    1711      Py_CLEAR(state->lock_type);
    1712      Py_CLEAR(state->local_type);
    1713      Py_CLEAR(state->local_dummy_type);
    1714      return 0;
    1715  }
    1716  
    1717  static void
    1718  thread_module_free(void *module)
    1719  {
    1720      thread_module_clear((PyObject *)module);
    1721  }
    1722  
    1723  
    1724  
    1725  PyDoc_STRVAR(thread_doc,
    1726  "This module provides primitive operations to write multi-threaded programs.\n\
    1727  The 'threading' module provides a more convenient interface.");
    1728  
    1729  static PyModuleDef_Slot thread_module_slots[] = {
    1730      {Py_mod_exec, thread_module_exec},
    1731      {0, NULL}
    1732  };
    1733  
    1734  static struct PyModuleDef thread_module = {
    1735      PyModuleDef_HEAD_INIT,
    1736      .m_name = "_thread",
    1737      .m_doc = thread_doc,
    1738      .m_size = sizeof(thread_module_state),
    1739      .m_methods = thread_methods,
    1740      .m_traverse = thread_module_traverse,
    1741      .m_clear = thread_module_clear,
    1742      .m_free = thread_module_free,
    1743      .m_slots = thread_module_slots,
    1744  };
    1745  
    1746  PyMODINIT_FUNC
    1747  PyInit__thread(void)
    1748  {
    1749      return PyModuleDef_Init(&thread_module);
    1750  }