Python-2.7.3/Modules/threadmodule.c

No issues found

  1 /* Thread module */
  2 /* Interface to Sjoerd's portable C thread library */
  3 
  4 #include "Python.h"
  5 #include "structmember.h" /* offsetof */
  6 
  7 #ifndef WITH_THREAD
  8 #error "Error!  The rest of Python is not compiled with thread support."
  9 #error "Rerun configure, adding a --with-threads option."
 10 #error "Then run `make clean' followed by `make'."
 11 #endif
 12 
 13 #include "pythread.h"
 14 
 15 static PyObject *ThreadError;
 16 static PyObject *str_dict;
 17 static long nb_threads = 0;
 18 
 19 /* Lock objects */
 20 
 21 typedef struct {
 22     PyObject_HEAD
 23     PyThread_type_lock lock_lock;
 24     PyObject *in_weakreflist;
 25 } lockobject;
 26 
 27 static void
 28 lock_dealloc(lockobject *self)
 29 {
 30     if (self->in_weakreflist != NULL)
 31         PyObject_ClearWeakRefs((PyObject *) self);
 32     if (self->lock_lock != NULL) {
 33         /* Unlock the lock so it's safe to free it */
 34         PyThread_acquire_lock(self->lock_lock, 0);
 35         PyThread_release_lock(self->lock_lock);
 36 
 37         PyThread_free_lock(self->lock_lock);
 38     }
 39     PyObject_Del(self);
 40 }
 41 
 42 static PyObject *
 43 lock_PyThread_acquire_lock(lockobject *self, PyObject *args)
 44 {
 45     int i = 1;
 46 
 47     if (!PyArg_ParseTuple(args, "|i:acquire", &i))
 48         return NULL;
 49 
 50     Py_BEGIN_ALLOW_THREADS
 51     i = PyThread_acquire_lock(self->lock_lock, i);
 52     Py_END_ALLOW_THREADS
 53 
 54     return PyBool_FromLong((long)i);
 55 }
 56 
 57 PyDoc_STRVAR(acquire_doc,
 58 "acquire([wait]) -> None or bool\n\
 59 (acquire_lock() is an obsolete synonym)\n\
 60 \n\
 61 Lock the lock.  Without argument, this blocks if the lock is already\n\
 62 locked (even by the same thread), waiting for another thread to release\n\
 63 the lock, and return None once the lock is acquired.\n\
 64 With an argument, this will only block if the argument is true,\n\
 65 and the return value reflects whether the lock is acquired.\n\
 66 The blocking operation is not interruptible.");
 67 
 68 static PyObject *
 69 lock_PyThread_release_lock(lockobject *self)
 70 {
 71     /* Sanity check: the lock must be locked */
 72     if (PyThread_acquire_lock(self->lock_lock, 0)) {
 73         PyThread_release_lock(self->lock_lock);
 74         PyErr_SetString(ThreadError, "release unlocked lock");
 75         return NULL;
 76     }
 77 
 78     PyThread_release_lock(self->lock_lock);
 79     Py_INCREF(Py_None);
 80     return Py_None;
 81 }
 82 
 83 PyDoc_STRVAR(release_doc,
 84 "release()\n\
 85 (release_lock() is an obsolete synonym)\n\
 86 \n\
 87 Release the lock, allowing another thread that is blocked waiting for\n\
 88 the lock to acquire the lock.  The lock must be in the locked state,\n\
 89 but it needn't be locked by the same thread that unlocks it.");
 90 
 91 static PyObject *
 92 lock_locked_lock(lockobject *self)
 93 {
 94     if (PyThread_acquire_lock(self->lock_lock, 0)) {
 95         PyThread_release_lock(self->lock_lock);
 96         return PyBool_FromLong(0L);
 97     }
 98     return PyBool_FromLong(1L);
 99 }
100 
101 PyDoc_STRVAR(locked_doc,
102 "locked() -> bool\n\
103 (locked_lock() is an obsolete synonym)\n\
104 \n\
105 Return whether the lock is in the locked state.");
106 
107 static PyMethodDef lock_methods[] = {
108     {"acquire_lock", (PyCFunction)lock_PyThread_acquire_lock,
109      METH_VARARGS, acquire_doc},
110     {"acquire",      (PyCFunction)lock_PyThread_acquire_lock,
111      METH_VARARGS, acquire_doc},
112     {"release_lock", (PyCFunction)lock_PyThread_release_lock,
113      METH_NOARGS, release_doc},
114     {"release",      (PyCFunction)lock_PyThread_release_lock,
115      METH_NOARGS, release_doc},
116     {"locked_lock",  (PyCFunction)lock_locked_lock,
117      METH_NOARGS, locked_doc},
118     {"locked",       (PyCFunction)lock_locked_lock,
119      METH_NOARGS, locked_doc},
120     {"__enter__",    (PyCFunction)lock_PyThread_acquire_lock,
121      METH_VARARGS, acquire_doc},
122     {"__exit__",    (PyCFunction)lock_PyThread_release_lock,
123      METH_VARARGS, release_doc},
124     {NULL}              /* sentinel */
125 };
126 
127 static PyTypeObject Locktype = {
128     PyVarObject_HEAD_INIT(&PyType_Type, 0)
129     "thread.lock",                      /*tp_name*/
130     sizeof(lockobject),                 /*tp_size*/
131     0,                                  /*tp_itemsize*/
132     /* methods */
133     (destructor)lock_dealloc,           /*tp_dealloc*/
134     0,                                  /*tp_print*/
135     0,                                  /*tp_getattr*/
136     0,                                  /*tp_setattr*/
137     0,                                  /*tp_compare*/
138     0,                                  /*tp_repr*/
139     0,                                  /* tp_as_number */
140     0,                                  /* tp_as_sequence */
141     0,                                  /* tp_as_mapping */
142     0,                                  /* tp_hash */
143     0,                                  /* tp_call */
144     0,                                  /* tp_str */
145     0,                                  /* tp_getattro */
146     0,                                  /* tp_setattro */
147     0,                                  /* tp_as_buffer */
148     Py_TPFLAGS_HAVE_WEAKREFS,       /* tp_flags */
149     0,                                  /* tp_doc */
150     0,                                  /* tp_traverse */
151     0,                                  /* tp_clear */
152     0,                                  /* tp_richcompare */
153     offsetof(lockobject, in_weakreflist),       /* tp_weaklistoffset */
154     0,                                  /* tp_iter */
155     0,                                  /* tp_iternext */
156     lock_methods,                       /* tp_methods */
157 };
158 
159 static lockobject *
160 newlockobject(void)
161 {
162     lockobject *self;
163     self = PyObject_New(lockobject, &Locktype);
164     if (self == NULL)
165         return NULL;
166     self->lock_lock = PyThread_allocate_lock();
167     self->in_weakreflist = NULL;
168     if (self->lock_lock == NULL) {
169         Py_DECREF(self);
170         PyErr_SetString(ThreadError, "can't allocate lock");
171         return NULL;
172     }
173     return self;
174 }
175 
176 /* Thread-local objects */
177 
178 #include "structmember.h"
179 
180 /* Quick overview:
181 
182    We need to be able to reclaim reference cycles as soon as possible
183    (both when a thread is being terminated, or a thread-local object
184     becomes unreachable from user data).  Constraints:
185    - it must not be possible for thread-state dicts to be involved in
186      reference cycles (otherwise the cyclic GC will refuse to consider
187      objects referenced from a reachable thread-state dict, even though
188      local_dealloc would clear them)
189    - the death of a thread-state dict must still imply destruction of the
190      corresponding local dicts in all thread-local objects.
191 
192    Our implementation uses small "localdummy" objects in order to break
193    the reference chain. These trivial objects are hashable (using the
194    default scheme of identity hashing) and weakrefable.
195    Each thread-state holds a separate localdummy for each local object
196    (as a /strong reference/),
197    and each thread-local object holds a dict mapping /weak references/
198    of localdummies to local dicts.
199 
200    Therefore:
201    - only the thread-state dict holds a strong reference to the dummies
202    - only the thread-local object holds a strong reference to the local dicts
203    - only outside objects (application- or library-level) hold strong
204      references to the thread-local objects
205    - as soon as a thread-state dict is destroyed, the weakref callbacks of all
206      dummies attached to that thread are called, and destroy the corresponding
207      local dicts from thread-local objects
208    - as soon as a thread-local object is destroyed, its local dicts are
209      destroyed and its dummies are manually removed from all thread states
210    - the GC can do its work correctly when a thread-local object is dangling,
211      without any interference from the thread-state dicts
212 
213    As an additional optimization, each localdummy holds a borrowed reference
214    to the corresponding localdict.  This borrowed reference is only used
215    by the thread-local object which has created the localdummy, which should
216    guarantee that the localdict still exists when accessed.
217 */
218 
219 typedef struct {
220     PyObject_HEAD
221     PyObject *localdict;        /* Borrowed reference! */
222     PyObject *weakreflist;      /* List of weak references to self */
223 } localdummyobject;
224 
225 static void
226 localdummy_dealloc(localdummyobject *self)
227 {
228     if (self->weakreflist != NULL)
229         PyObject_ClearWeakRefs((PyObject *) self);
230     Py_TYPE(self)->tp_free((PyObject*)self);
231 }
232 
233 static PyTypeObject localdummytype = {
234     PyVarObject_HEAD_INIT(NULL, 0)
235     /* tp_name           */ "_thread._localdummy",
236     /* tp_basicsize      */ sizeof(localdummyobject),
237     /* tp_itemsize       */ 0,
238     /* tp_dealloc        */ (destructor)localdummy_dealloc,
239     /* tp_print          */ 0,
240     /* tp_getattr        */ 0,
241     /* tp_setattr        */ 0,
242     /* tp_reserved       */ 0,
243     /* tp_repr           */ 0,
244     /* tp_as_number      */ 0,
245     /* tp_as_sequence    */ 0,
246     /* tp_as_mapping     */ 0,
247     /* tp_hash           */ 0,
248     /* tp_call           */ 0,
249     /* tp_str            */ 0,
250     /* tp_getattro       */ 0,
251     /* tp_setattro       */ 0,
252     /* tp_as_buffer      */ 0,
253     /* tp_flags          */ Py_TPFLAGS_DEFAULT,
254     /* tp_doc            */ "Thread-local dummy",
255     /* tp_traverse       */ 0,
256     /* tp_clear          */ 0,
257     /* tp_richcompare    */ 0,
258     /* tp_weaklistoffset */ offsetof(localdummyobject, weakreflist)
259 };
260 
261 
262 typedef struct {
263     PyObject_HEAD
264     PyObject *key;
265     PyObject *args;
266     PyObject *kw;
267     PyObject *weakreflist;      /* List of weak references to self */
268     /* A {localdummy weakref -> localdict} dict */
269     PyObject *dummies;
270     /* The callback for weakrefs to localdummies */
271     PyObject *wr_callback;
272 } localobject;
273 
274 /* Forward declaration */
275 static PyObject *_ldict(localobject *self);
276 static PyObject *_localdummy_destroyed(PyObject *meth_self, PyObject *dummyweakref);
277 
278 /* Create and register the dummy for the current thread.
279    Returns a borrowed reference of the corresponding local dict */
280 static PyObject *
281 _local_create_dummy(localobject *self)
282 {
283     PyObject *tdict, *ldict = NULL, *wr = NULL;
284     localdummyobject *dummy = NULL;
285     int r;
286 
287     tdict = PyThreadState_GetDict();
288     if (tdict == NULL) {
289         PyErr_SetString(PyExc_SystemError,
290                         "Couldn't get thread-state dictionary");
291         goto err;
292     }
293 
294     ldict = PyDict_New();
295     if (ldict == NULL)
296         goto err;
297     dummy = (localdummyobject *) localdummytype.tp_alloc(&localdummytype, 0);
298     if (dummy == NULL)
299         goto err;
300     dummy->localdict = ldict;
301     wr = PyWeakref_NewRef((PyObject *) dummy, self->wr_callback);
302     if (wr == NULL)
303         goto err;
304 
305     /* As a side-effect, this will cache the weakref's hash before the
306        dummy gets deleted */
307     r = PyDict_SetItem(self->dummies, wr, ldict);
308     if (r < 0)
309         goto err;
310     Py_CLEAR(wr);
311     r = PyDict_SetItem(tdict, self->key, (PyObject *) dummy);
312     if (r < 0)
313         goto err;
314     Py_CLEAR(dummy);
315 
316     Py_DECREF(ldict);
317     return ldict;
318 
319 err:
320     Py_XDECREF(ldict);
321     Py_XDECREF(wr);
322     Py_XDECREF(dummy);
323     return NULL;
324 }
325 
326 static PyObject *
327 local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
328 {
329     localobject *self;
330     PyObject *wr;
331     static PyMethodDef wr_callback_def = {
332         "_localdummy_destroyed", (PyCFunction) _localdummy_destroyed, METH_O
333     };
334 
335     if (type->tp_init == PyBaseObject_Type.tp_init
336         && ((args && PyObject_IsTrue(args))
337         || (kw && PyObject_IsTrue(kw)))) {
338         PyErr_SetString(PyExc_TypeError,
339                   "Initialization arguments are not supported");
340         return NULL;
341     }
342 
343     self = (localobject *)type->tp_alloc(type, 0);
344     if (self == NULL)
345         return NULL;
346 
347     Py_XINCREF(args);
348     self->args = args;
349     Py_XINCREF(kw);
350     self->kw = kw;
351     self->key = PyString_FromFormat("thread.local.%p", self);
352     if (self->key == NULL)
353         goto err;
354 
355     self->dummies = PyDict_New();
356     if (self->dummies == NULL)
357         goto err;
358 
359     /* We use a weak reference to self in the callback closure
360        in order to avoid spurious reference cycles */
361     wr = PyWeakref_NewRef((PyObject *) self, NULL);
362     if (wr == NULL)
363         goto err;
364     self->wr_callback = PyCFunction_New(&wr_callback_def, wr);
365     Py_DECREF(wr);
366     if (self->wr_callback == NULL)
367         goto err;
368 
369     if (_local_create_dummy(self) == NULL)
370         goto err;
371 
372     return (PyObject *)self;
373 
374   err:
375     Py_DECREF(self);
376     return NULL;
377 }
378 
379 static int
380 local_traverse(localobject *self, visitproc visit, void *arg)
381 {
382     Py_VISIT(self->args);
383     Py_VISIT(self->kw);
384     Py_VISIT(self->dummies);
385     return 0;
386 }
387 
388 static int
389 local_clear(localobject *self)
390 {
391     PyThreadState *tstate;
392     Py_CLEAR(self->args);
393     Py_CLEAR(self->kw);
394     Py_CLEAR(self->dummies);
395     Py_CLEAR(self->wr_callback);
396     /* Remove all strong references to dummies from the thread states */
397     if (self->key
398         && (tstate = PyThreadState_Get())
399         && tstate->interp) {
400         for(tstate = PyInterpreterState_ThreadHead(tstate->interp);
401             tstate;
402             tstate = PyThreadState_Next(tstate))
403             if (tstate->dict &&
404                 PyDict_GetItem(tstate->dict, self->key))
405                 PyDict_DelItem(tstate->dict, self->key);
406     }
407     return 0;
408 }
409 
410 static void
411 local_dealloc(localobject *self)
412 {
413     /* Weakrefs must be invalidated right now, otherwise they can be used
414        from code called below, which is very dangerous since Py_REFCNT(self) == 0 */
415     if (self->weakreflist != NULL)
416         PyObject_ClearWeakRefs((PyObject *) self);
417 
418     PyObject_GC_UnTrack(self);
419 
420     local_clear(self);
421     Py_XDECREF(self->key);
422     Py_TYPE(self)->tp_free((PyObject*)self);
423 }
424 
425 /* Returns a borrowed reference to the local dict, creating it if necessary */
426 static PyObject *
427 _ldict(localobject *self)
428 {
429     PyObject *tdict, *ldict, *dummy;
430 
431     tdict = PyThreadState_GetDict();
432     if (tdict == NULL) {
433         PyErr_SetString(PyExc_SystemError,
434                         "Couldn't get thread-state dictionary");
435         return NULL;
436     }
437 
438     dummy = PyDict_GetItem(tdict, self->key);
439     if (dummy == NULL) {
440         ldict = _local_create_dummy(self);
441         if (ldict == NULL)
442             return NULL;
443 
444         if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init &&
445             Py_TYPE(self)->tp_init((PyObject*)self,
446                                    self->args, self->kw) < 0) {
447             /* we need to get rid of ldict from thread so
448                we create a new one the next time we do an attr
449                access */
450             PyDict_DelItem(tdict, self->key);
451             return NULL;
452         }
453     }
454     else {
455         assert(Py_TYPE(dummy) == &localdummytype);
456         ldict = ((localdummyobject *) dummy)->localdict;
457     }
458 
459     return ldict;
460 }
461 
462 static int
463 local_setattro(localobject *self, PyObject *name, PyObject *v)
464 {
465     PyObject *ldict;
466     int r;
467 
468     ldict = _ldict(self);
469     if (ldict == NULL)
470         return -1;
471 
472     r = PyObject_RichCompareBool(name, str_dict, Py_EQ);
473     if (r == 1) {
474         PyErr_Format(PyExc_AttributeError,
475                      "'%.50s' object attribute '__dict__' is read-only",
476                      Py_TYPE(self)->tp_name);
477         return -1;
478     }
479     if (r == -1)
480         return -1;
481 
482     return _PyObject_GenericSetAttrWithDict((PyObject *)self, name, v, ldict);
483 }
484 
485 static PyObject *local_getattro(localobject *, PyObject *);
486 
487 static PyTypeObject localtype = {
488     PyVarObject_HEAD_INIT(NULL, 0)
489     /* tp_name           */ "thread._local",
490     /* tp_basicsize      */ sizeof(localobject),
491     /* tp_itemsize       */ 0,
492     /* tp_dealloc        */ (destructor)local_dealloc,
493     /* tp_print          */ 0,
494     /* tp_getattr        */ 0,
495     /* tp_setattr        */ 0,
496     /* tp_compare        */ 0,
497     /* tp_repr           */ 0,
498     /* tp_as_number      */ 0,
499     /* tp_as_sequence    */ 0,
500     /* tp_as_mapping     */ 0,
501     /* tp_hash           */ 0,
502     /* tp_call           */ 0,
503     /* tp_str            */ 0,
504     /* tp_getattro       */ (getattrofunc)local_getattro,
505     /* tp_setattro       */ (setattrofunc)local_setattro,
506     /* tp_as_buffer      */ 0,
507     /* tp_flags          */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
508                                                | Py_TPFLAGS_HAVE_GC,
509     /* tp_doc            */ "Thread-local data",
510     /* tp_traverse       */ (traverseproc)local_traverse,
511     /* tp_clear          */ (inquiry)local_clear,
512     /* tp_richcompare    */ 0,
513     /* tp_weaklistoffset */ offsetof(localobject, weakreflist),
514     /* tp_iter           */ 0,
515     /* tp_iternext       */ 0,
516     /* tp_methods        */ 0,
517     /* tp_members        */ 0,
518     /* tp_getset         */ 0,
519     /* tp_base           */ 0,
520     /* tp_dict           */ 0, /* internal use */
521     /* tp_descr_get      */ 0,
522     /* tp_descr_set      */ 0,
523     /* tp_dictoffset     */ 0,
524     /* tp_init           */ 0,
525     /* tp_alloc          */ 0,
526     /* tp_new            */ local_new,
527     /* tp_free           */ 0, /* Low-level free-mem routine */
528     /* tp_is_gc          */ 0, /* For PyObject_IS_GC */
529 };
530 
531 static PyObject *
532 local_getattro(localobject *self, PyObject *name)
533 {
534     PyObject *ldict, *value;
535     int r;
536 
537     ldict = _ldict(self);
538     if (ldict == NULL)
539         return NULL;
540 
541     r = PyObject_RichCompareBool(name, str_dict, Py_EQ);
542     if (r == 1) {
543         Py_INCREF(ldict);
544         return ldict;
545     }
546     if (r == -1)
547         return NULL;
548 
549     if (Py_TYPE(self) != &localtype)
550         /* use generic lookup for subtypes */
551         return _PyObject_GenericGetAttrWithDict((PyObject *)self, name, ldict);
552 
553     /* Optimization: just look in dict ourselves */
554     value = PyDict_GetItem(ldict, name);
555     if (value == NULL)
556         /* Fall back on generic to get __class__ and __dict__ */
557         return _PyObject_GenericGetAttrWithDict((PyObject *)self, name, ldict);
558 
559     Py_INCREF(value);
560     return value;
561 }
562 
563 /* Called when a dummy is destroyed. */
564 static PyObject *
565 _localdummy_destroyed(PyObject *localweakref, PyObject *dummyweakref)
566 {
567     PyObject *obj;
568     localobject *self;
569     assert(PyWeakref_CheckRef(localweakref));
570     obj = PyWeakref_GET_OBJECT(localweakref);
571     if (obj == Py_None)
572         Py_RETURN_NONE;
573     Py_INCREF(obj);
574     assert(PyObject_TypeCheck(obj, &localtype));
575     /* If the thread-local object is still alive and not being cleared,
576        remove the corresponding local dict */
577     self = (localobject *) obj;
578     if (self->dummies != NULL) {
579         PyObject *ldict;
580         ldict = PyDict_GetItem(self->dummies, dummyweakref);
581         if (ldict != NULL) {
582             PyDict_DelItem(self->dummies, dummyweakref);
583         }
584         if (PyErr_Occurred())
585             PyErr_WriteUnraisable(obj);
586     }
587     Py_DECREF(obj);
588     Py_RETURN_NONE;
589 }
590 
591 /* Module functions */
592 
593 struct bootstate {
594     PyInterpreterState *interp;
595     PyObject *func;
596     PyObject *args;
597     PyObject *keyw;
598     PyThreadState *tstate;
599 };
600 
601 static void
602 t_bootstrap(void *boot_raw)
603 {
604     struct bootstate *boot = (struct bootstate *) boot_raw;
605     PyThreadState *tstate;
606     PyObject *res;
607 
608     tstate = boot->tstate;
609     tstate->thread_id = PyThread_get_thread_ident();
610     _PyThreadState_Init(tstate);
611     PyEval_AcquireThread(tstate);
612     nb_threads++;
613     res = PyEval_CallObjectWithKeywords(
614         boot->func, boot->args, boot->keyw);
615     if (res == NULL) {
616         if (PyErr_ExceptionMatches(PyExc_SystemExit))
617             PyErr_Clear();
618         else {
619             PyObject *file;
620             PySys_WriteStderr(
621                 "Unhandled exception in thread started by ");
622             file = PySys_GetObject("stderr");
623             if (file)
624                 PyFile_WriteObject(boot->func, file, 0);
625             else
626                 PyObject_Print(boot->func, stderr, 0);
627             PySys_WriteStderr("\n");
628             PyErr_PrintEx(0);
629         }
630     }
631     else
632         Py_DECREF(res);
633     Py_DECREF(boot->func);
634     Py_DECREF(boot->args);
635     Py_XDECREF(boot->keyw);
636     PyMem_DEL(boot_raw);
637     nb_threads--;
638     PyThreadState_Clear(tstate);
639     PyThreadState_DeleteCurrent();
640     PyThread_exit_thread();
641 }
642 
643 static PyObject *
644 thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
645 {
646     PyObject *func, *args, *keyw = NULL;
647     struct bootstate *boot;
648     long ident;
649 
650     if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3,
651                            &func, &args, &keyw))
652         return NULL;
653     if (!PyCallable_Check(func)) {
654         PyErr_SetString(PyExc_TypeError,
655                         "first arg must be callable");
656         return NULL;
657     }
658     if (!PyTuple_Check(args)) {
659         PyErr_SetString(PyExc_TypeError,
660                         "2nd arg must be a tuple");
661         return NULL;
662     }
663     if (keyw != NULL && !PyDict_Check(keyw)) {
664         PyErr_SetString(PyExc_TypeError,
665                         "optional 3rd arg must be a dictionary");
666         return NULL;
667     }
668     boot = PyMem_NEW(struct bootstate, 1);
669     if (boot == NULL)
670         return PyErr_NoMemory();
671     boot->interp = PyThreadState_GET()->interp;
672     boot->func = func;
673     boot->args = args;
674     boot->keyw = keyw;
675     boot->tstate = _PyThreadState_Prealloc(boot->interp);
676     if (boot->tstate == NULL) {
677         PyMem_DEL(boot);
678         return PyErr_NoMemory();
679     }
680     Py_INCREF(func);
681     Py_INCREF(args);
682     Py_XINCREF(keyw);
683     PyEval_InitThreads(); /* Start the interpreter's thread-awareness */
684     ident = PyThread_start_new_thread(t_bootstrap, (void*) boot);
685     if (ident == -1) {
686         PyErr_SetString(ThreadError, "can't start new thread");
687         Py_DECREF(func);
688         Py_DECREF(args);
689         Py_XDECREF(keyw);
690         PyThreadState_Clear(boot->tstate);
691         PyMem_DEL(boot);
692         return NULL;
693     }
694     return PyInt_FromLong(ident);
695 }
696 
697 PyDoc_STRVAR(start_new_doc,
698 "start_new_thread(function, args[, kwargs])\n\
699 (start_new() is an obsolete synonym)\n\
700 \n\
701 Start a new thread and return its identifier.  The thread will call the\n\
702 function with positional arguments from the tuple args and keyword arguments\n\
703 taken from the optional dictionary kwargs.  The thread exits when the\n\
704 function returns; the return value is ignored.  The thread will also exit\n\
705 when the function raises an unhandled exception; a stack trace will be\n\
706 printed unless the exception is SystemExit.\n");
707 
708 static PyObject *
709 thread_PyThread_exit_thread(PyObject *self)
710 {
711     PyErr_SetNone(PyExc_SystemExit);
712     return NULL;
713 }
714 
715 PyDoc_STRVAR(exit_doc,
716 "exit()\n\
717 (exit_thread() is an obsolete synonym)\n\
718 \n\
719 This is synonymous to ``raise SystemExit''.  It will cause the current\n\
720 thread to exit silently unless the exception is caught.");
721 
722 static PyObject *
723 thread_PyThread_interrupt_main(PyObject * self)
724 {
725     PyErr_SetInterrupt();
726     Py_INCREF(Py_None);
727     return Py_None;
728 }
729 
730 PyDoc_STRVAR(interrupt_doc,
731 "interrupt_main()\n\
732 \n\
733 Raise a KeyboardInterrupt in the main thread.\n\
734 A subthread can use this function to interrupt the main thread."
735 );
736 
737 static lockobject *newlockobject(void);
738 
739 static PyObject *
740 thread_PyThread_allocate_lock(PyObject *self)
741 {
742     return (PyObject *) newlockobject();
743 }
744 
745 PyDoc_STRVAR(allocate_doc,
746 "allocate_lock() -> lock object\n\
747 (allocate() is an obsolete synonym)\n\
748 \n\
749 Create a new lock object.  See help(LockType) for information about locks.");
750 
751 static PyObject *
752 thread_get_ident(PyObject *self)
753 {
754     long ident;
755     ident = PyThread_get_thread_ident();
756     if (ident == -1) {
757         PyErr_SetString(ThreadError, "no current thread ident");
758         return NULL;
759     }
760     return PyInt_FromLong(ident);
761 }
762 
763 PyDoc_STRVAR(get_ident_doc,
764 "get_ident() -> integer\n\
765 \n\
766 Return a non-zero integer that uniquely identifies the current thread\n\
767 amongst other threads that exist simultaneously.\n\
768 This may be used to identify per-thread resources.\n\
769 Even though on some platforms threads identities may appear to be\n\
770 allocated consecutive numbers starting at 1, this behavior should not\n\
771 be relied upon, and the number should be seen purely as a magic cookie.\n\
772 A thread's identity may be reused for another thread after it exits.");
773 
774 static PyObject *
775 thread__count(PyObject *self)
776 {
777     return PyInt_FromLong(nb_threads);
778 }
779 
780 PyDoc_STRVAR(_count_doc,
781 "_count() -> integer\n\
782 \n\
783 \
784 Return the number of currently running Python threads, excluding \n\
785 the main thread. The returned number comprises all threads created\n\
786 through `start_new_thread()` as well as `threading.Thread`, and not\n\
787 yet finished.\n\
788 \n\
789 This function is meant for internal and specialized purposes only.\n\
790 In most applications `threading.enumerate()` should be used instead.");
791 
792 static PyObject *
793 thread_stack_size(PyObject *self, PyObject *args)
794 {
795     size_t old_size;
796     Py_ssize_t new_size = 0;
797     int rc;
798 
799     if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size))
800         return NULL;
801 
802     if (new_size < 0) {
803         PyErr_SetString(PyExc_ValueError,
804                         "size must be 0 or a positive value");
805         return NULL;
806     }
807 
808     old_size = PyThread_get_stacksize();
809 
810     rc = PyThread_set_stacksize((size_t) new_size);
811     if (rc == -1) {
812         PyErr_Format(PyExc_ValueError,
813                      "size not valid: %zd bytes",
814                      new_size);
815         return NULL;
816     }
817     if (rc == -2) {
818         PyErr_SetString(ThreadError,
819                         "setting stack size not supported");
820         return NULL;
821     }
822 
823     return PyInt_FromSsize_t((Py_ssize_t) old_size);
824 }
825 
826 PyDoc_STRVAR(stack_size_doc,
827 "stack_size([size]) -> size\n\
828 \n\
829 Return the thread stack size used when creating new threads.  The\n\
830 optional size argument specifies the stack size (in bytes) to be used\n\
831 for subsequently created threads, and must be 0 (use platform or\n\
832 configured default) or a positive integer value of at least 32,768 (32k).\n\
833 If changing the thread stack size is unsupported, a ThreadError\n\
834 exception is raised.  If the specified size is invalid, a ValueError\n\
835 exception is raised, and the stack size is unmodified.  32k bytes\n\
836  currently the minimum supported stack size value to guarantee\n\
837 sufficient stack space for the interpreter itself.\n\
838 \n\
839 Note that some platforms may have particular restrictions on values for\n\
840 the stack size, such as requiring a minimum stack size larger than 32kB or\n\
841 requiring allocation in multiples of the system memory page size\n\
842 - platform documentation should be referred to for more information\n\
843 (4kB pages are common; using multiples of 4096 for the stack size is\n\
844 the suggested approach in the absence of more specific information).");
845 
846 static PyMethodDef thread_methods[] = {
847     {"start_new_thread",        (PyCFunction)thread_PyThread_start_new_thread,
848                             METH_VARARGS,
849                             start_new_doc},
850     {"start_new",               (PyCFunction)thread_PyThread_start_new_thread,
851                             METH_VARARGS,
852                             start_new_doc},
853     {"allocate_lock",           (PyCFunction)thread_PyThread_allocate_lock,
854      METH_NOARGS, allocate_doc},
855     {"allocate",                (PyCFunction)thread_PyThread_allocate_lock,
856      METH_NOARGS, allocate_doc},
857     {"exit_thread",             (PyCFunction)thread_PyThread_exit_thread,
858      METH_NOARGS, exit_doc},
859     {"exit",                    (PyCFunction)thread_PyThread_exit_thread,
860      METH_NOARGS, exit_doc},
861     {"interrupt_main",          (PyCFunction)thread_PyThread_interrupt_main,
862      METH_NOARGS, interrupt_doc},
863     {"get_ident",               (PyCFunction)thread_get_ident,
864      METH_NOARGS, get_ident_doc},
865     {"_count",                  (PyCFunction)thread__count,
866      METH_NOARGS, _count_doc},
867     {"stack_size",              (PyCFunction)thread_stack_size,
868                             METH_VARARGS,
869                             stack_size_doc},
870     {NULL,                      NULL}           /* sentinel */
871 };
872 
873 
874 /* Initialization function */
875 
876 PyDoc_STRVAR(thread_doc,
877 "This module provides primitive operations to write multi-threaded programs.\n\
878 The 'threading' module provides a more convenient interface.");
879 
880 PyDoc_STRVAR(lock_doc,
881 "A lock object is a synchronization primitive.  To create a lock,\n\
882 call the PyThread_allocate_lock() function.  Methods are:\n\
883 \n\
884 acquire() -- lock the lock, possibly blocking until it can be obtained\n\
885 release() -- unlock of the lock\n\
886 locked() -- test whether the lock is currently locked\n\
887 \n\
888 A lock is not owned by the thread that locked it; another thread may\n\
889 unlock it.  A thread attempting to lock a lock that it has already locked\n\
890 will block until another thread unlocks it.  Deadlocks may ensue.");
891 
892 PyMODINIT_FUNC
893 initthread(void)
894 {
895     PyObject *m, *d;
896 
897     /* Initialize types: */
898     if (PyType_Ready(&localdummytype) < 0)
899         return;
900     if (PyType_Ready(&localtype) < 0)
901         return;
902 
903     /* Create the module and add the functions */
904     m = Py_InitModule3("thread", thread_methods, thread_doc);
905     if (m == NULL)
906         return;
907 
908     /* Add a symbolic constant */
909     d = PyModule_GetDict(m);
910     ThreadError = PyErr_NewException("thread.error", NULL, NULL);
911     PyDict_SetItemString(d, "error", ThreadError);
912     Locktype.tp_doc = lock_doc;
913     if (PyType_Ready(&Locktype) < 0)
914         return;
915     Py_INCREF(&Locktype);
916     PyDict_SetItemString(d, "LockType", (PyObject *)&Locktype);
917 
918     Py_INCREF(&localtype);
919     if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0)
920         return;
921 
922     nb_threads = 0;
923 
924     str_dict = PyString_InternFromString("__dict__");
925     if (str_dict == NULL)
926         return;
927 
928     /* Initialize the C thread library */
929     PyThread_init_thread();
930 }