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