Issue #5262: Improved fix.
[python.git] / Modules / threadmodule.c
blobe7638bbb6defecce373de2eb78a063b26b88b676
2 /* Thread module */
3 /* Interface to Sjoerd's portable C thread library */
5 #include "Python.h"
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
13 #include "pythread.h"
15 static PyObject *ThreadError;
18 /* Lock objects */
20 typedef struct {
21 PyObject_HEAD
22 PyThread_type_lock lock_lock;
23 } lockobject;
25 static void
26 lock_dealloc(lockobject *self)
28 assert(self->lock_lock);
29 /* Unlock the lock so it's safe to free it */
30 PyThread_acquire_lock(self->lock_lock, 0);
31 PyThread_release_lock(self->lock_lock);
33 PyThread_free_lock(self->lock_lock);
34 PyObject_Del(self);
37 static PyObject *
38 lock_PyThread_acquire_lock(lockobject *self, PyObject *args)
40 int i = 1;
42 if (!PyArg_ParseTuple(args, "|i:acquire", &i))
43 return NULL;
45 Py_BEGIN_ALLOW_THREADS
46 i = PyThread_acquire_lock(self->lock_lock, i);
47 Py_END_ALLOW_THREADS
49 return PyBool_FromLong((long)i);
52 PyDoc_STRVAR(acquire_doc,
53 "acquire([wait]) -> None or bool\n\
54 (acquire_lock() is an obsolete synonym)\n\
55 \n\
56 Lock the lock. Without argument, this blocks if the lock is already\n\
57 locked (even by the same thread), waiting for another thread to release\n\
58 the lock, and return None once the lock is acquired.\n\
59 With an argument, this will only block if the argument is true,\n\
60 and the return value reflects whether the lock is acquired.\n\
61 The blocking operation is not interruptible.");
63 static PyObject *
64 lock_PyThread_release_lock(lockobject *self)
66 /* Sanity check: the lock must be locked */
67 if (PyThread_acquire_lock(self->lock_lock, 0)) {
68 PyThread_release_lock(self->lock_lock);
69 PyErr_SetString(ThreadError, "release unlocked lock");
70 return NULL;
73 PyThread_release_lock(self->lock_lock);
74 Py_INCREF(Py_None);
75 return Py_None;
78 PyDoc_STRVAR(release_doc,
79 "release()\n\
80 (release_lock() is an obsolete synonym)\n\
81 \n\
82 Release the lock, allowing another thread that is blocked waiting for\n\
83 the lock to acquire the lock. The lock must be in the locked state,\n\
84 but it needn't be locked by the same thread that unlocks it.");
86 static PyObject *
87 lock_locked_lock(lockobject *self)
89 if (PyThread_acquire_lock(self->lock_lock, 0)) {
90 PyThread_release_lock(self->lock_lock);
91 return PyBool_FromLong(0L);
93 return PyBool_FromLong(1L);
96 PyDoc_STRVAR(locked_doc,
97 "locked() -> bool\n\
98 (locked_lock() is an obsolete synonym)\n\
99 \n\
100 Return whether the lock is in the locked state.");
102 static PyMethodDef lock_methods[] = {
103 {"acquire_lock", (PyCFunction)lock_PyThread_acquire_lock,
104 METH_VARARGS, acquire_doc},
105 {"acquire", (PyCFunction)lock_PyThread_acquire_lock,
106 METH_VARARGS, acquire_doc},
107 {"release_lock", (PyCFunction)lock_PyThread_release_lock,
108 METH_NOARGS, release_doc},
109 {"release", (PyCFunction)lock_PyThread_release_lock,
110 METH_NOARGS, release_doc},
111 {"locked_lock", (PyCFunction)lock_locked_lock,
112 METH_NOARGS, locked_doc},
113 {"locked", (PyCFunction)lock_locked_lock,
114 METH_NOARGS, locked_doc},
115 {"__enter__", (PyCFunction)lock_PyThread_acquire_lock,
116 METH_VARARGS, acquire_doc},
117 {"__exit__", (PyCFunction)lock_PyThread_release_lock,
118 METH_VARARGS, release_doc},
119 {NULL} /* sentinel */
122 static PyTypeObject Locktype = {
123 PyVarObject_HEAD_INIT(&PyType_Type, 0)
124 "thread.lock", /*tp_name*/
125 sizeof(lockobject), /*tp_size*/
126 0, /*tp_itemsize*/
127 /* methods */
128 (destructor)lock_dealloc, /*tp_dealloc*/
129 0, /*tp_print*/
130 0, /*tp_getattr*/
131 0, /*tp_setattr*/
132 0, /*tp_compare*/
133 0, /*tp_repr*/
134 0, /* tp_as_number */
135 0, /* tp_as_sequence */
136 0, /* tp_as_mapping */
137 0, /* tp_hash */
138 0, /* tp_call */
139 0, /* tp_str */
140 0, /* tp_getattro */
141 0, /* tp_setattro */
142 0, /* tp_as_buffer */
143 0, /* tp_flags */
144 0, /* tp_doc */
145 0, /* tp_traverse */
146 0, /* tp_clear */
147 0, /* tp_richcompare */
148 0, /* tp_weaklistoffset */
149 0, /* tp_iter */
150 0, /* tp_iternext */
151 lock_methods, /* tp_methods */
154 static lockobject *
155 newlockobject(void)
157 lockobject *self;
158 self = PyObject_New(lockobject, &Locktype);
159 if (self == NULL)
160 return NULL;
161 self->lock_lock = PyThread_allocate_lock();
162 if (self->lock_lock == NULL) {
163 PyObject_Del(self);
164 self = NULL;
165 PyErr_SetString(ThreadError, "can't allocate lock");
167 return self;
170 /* Thread-local objects */
172 #include "structmember.h"
174 typedef struct {
175 PyObject_HEAD
176 PyObject *key;
177 PyObject *args;
178 PyObject *kw;
179 PyObject *dict;
180 } localobject;
182 static PyObject *
183 local_new(PyTypeObject *type, PyObject *args, PyObject *kw)
185 localobject *self;
186 PyObject *tdict;
188 if (type->tp_init == PyBaseObject_Type.tp_init
189 && ((args && PyObject_IsTrue(args))
190 || (kw && PyObject_IsTrue(kw)))) {
191 PyErr_SetString(PyExc_TypeError,
192 "Initialization arguments are not supported");
193 return NULL;
196 self = (localobject *)type->tp_alloc(type, 0);
197 if (self == NULL)
198 return NULL;
200 Py_XINCREF(args);
201 self->args = args;
202 Py_XINCREF(kw);
203 self->kw = kw;
204 self->dict = NULL; /* making sure */
205 self->key = PyString_FromFormat("thread.local.%p", self);
206 if (self->key == NULL)
207 goto err;
209 self->dict = PyDict_New();
210 if (self->dict == NULL)
211 goto err;
213 tdict = PyThreadState_GetDict();
214 if (tdict == NULL) {
215 PyErr_SetString(PyExc_SystemError,
216 "Couldn't get thread-state dictionary");
217 goto err;
220 if (PyDict_SetItem(tdict, self->key, self->dict) < 0)
221 goto err;
223 return (PyObject *)self;
225 err:
226 Py_DECREF(self);
227 return NULL;
230 static int
231 local_traverse(localobject *self, visitproc visit, void *arg)
233 Py_VISIT(self->args);
234 Py_VISIT(self->kw);
235 Py_VISIT(self->dict);
236 return 0;
239 static int
240 local_clear(localobject *self)
242 Py_CLEAR(self->key);
243 Py_CLEAR(self->args);
244 Py_CLEAR(self->kw);
245 Py_CLEAR(self->dict);
246 return 0;
249 static void
250 local_dealloc(localobject *self)
252 PyThreadState *tstate;
253 if (self->key
254 && (tstate = PyThreadState_Get())
255 && tstate->interp) {
256 for(tstate = PyInterpreterState_ThreadHead(tstate->interp);
257 tstate;
258 tstate = PyThreadState_Next(tstate))
259 if (tstate->dict &&
260 PyDict_GetItem(tstate->dict, self->key))
261 PyDict_DelItem(tstate->dict, self->key);
264 local_clear(self);
265 Py_TYPE(self)->tp_free((PyObject*)self);
268 static PyObject *
269 _ldict(localobject *self)
271 PyObject *tdict, *ldict;
273 tdict = PyThreadState_GetDict();
274 if (tdict == NULL) {
275 PyErr_SetString(PyExc_SystemError,
276 "Couldn't get thread-state dictionary");
277 return NULL;
280 ldict = PyDict_GetItem(tdict, self->key);
281 if (ldict == NULL) {
282 ldict = PyDict_New(); /* we own ldict */
284 if (ldict == NULL)
285 return NULL;
286 else {
287 int i = PyDict_SetItem(tdict, self->key, ldict);
288 Py_DECREF(ldict); /* now ldict is borrowed */
289 if (i < 0)
290 return NULL;
293 Py_CLEAR(self->dict);
294 Py_INCREF(ldict);
295 self->dict = ldict; /* still borrowed */
297 if (Py_TYPE(self)->tp_init != PyBaseObject_Type.tp_init &&
298 Py_TYPE(self)->tp_init((PyObject*)self,
299 self->args, self->kw) < 0) {
300 /* we need to get rid of ldict from thread so
301 we create a new one the next time we do an attr
302 acces */
303 PyDict_DelItem(tdict, self->key);
304 return NULL;
309 /* The call to tp_init above may have caused another thread to run.
310 Install our ldict again. */
311 if (self->dict != ldict) {
312 Py_CLEAR(self->dict);
313 Py_INCREF(ldict);
314 self->dict = ldict;
317 return ldict;
320 static int
321 local_setattro(localobject *self, PyObject *name, PyObject *v)
323 PyObject *ldict;
325 ldict = _ldict(self);
326 if (ldict == NULL)
327 return -1;
329 return PyObject_GenericSetAttr((PyObject *)self, name, v);
332 static PyObject *
333 local_getdict(localobject *self, void *closure)
335 if (self->dict == NULL) {
336 PyErr_SetString(PyExc_AttributeError, "__dict__");
337 return NULL;
340 Py_INCREF(self->dict);
341 return self->dict;
344 static PyGetSetDef local_getset[] = {
345 {"__dict__", (getter)local_getdict, (setter)NULL,
346 "Local-data dictionary", NULL},
347 {NULL} /* Sentinel */
350 static PyObject *local_getattro(localobject *, PyObject *);
352 static PyTypeObject localtype = {
353 PyVarObject_HEAD_INIT(NULL, 0)
354 /* tp_name */ "thread._local",
355 /* tp_basicsize */ sizeof(localobject),
356 /* tp_itemsize */ 0,
357 /* tp_dealloc */ (destructor)local_dealloc,
358 /* tp_print */ 0,
359 /* tp_getattr */ 0,
360 /* tp_setattr */ 0,
361 /* tp_compare */ 0,
362 /* tp_repr */ 0,
363 /* tp_as_number */ 0,
364 /* tp_as_sequence */ 0,
365 /* tp_as_mapping */ 0,
366 /* tp_hash */ 0,
367 /* tp_call */ 0,
368 /* tp_str */ 0,
369 /* tp_getattro */ (getattrofunc)local_getattro,
370 /* tp_setattro */ (setattrofunc)local_setattro,
371 /* tp_as_buffer */ 0,
372 /* tp_flags */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
373 /* tp_doc */ "Thread-local data",
374 /* tp_traverse */ (traverseproc)local_traverse,
375 /* tp_clear */ (inquiry)local_clear,
376 /* tp_richcompare */ 0,
377 /* tp_weaklistoffset */ 0,
378 /* tp_iter */ 0,
379 /* tp_iternext */ 0,
380 /* tp_methods */ 0,
381 /* tp_members */ 0,
382 /* tp_getset */ local_getset,
383 /* tp_base */ 0,
384 /* tp_dict */ 0, /* internal use */
385 /* tp_descr_get */ 0,
386 /* tp_descr_set */ 0,
387 /* tp_dictoffset */ offsetof(localobject, dict),
388 /* tp_init */ 0,
389 /* tp_alloc */ 0,
390 /* tp_new */ local_new,
391 /* tp_free */ 0, /* Low-level free-mem routine */
392 /* tp_is_gc */ 0, /* For PyObject_IS_GC */
395 static PyObject *
396 local_getattro(localobject *self, PyObject *name)
398 PyObject *ldict, *value;
400 ldict = _ldict(self);
401 if (ldict == NULL)
402 return NULL;
404 if (Py_TYPE(self) != &localtype)
405 /* use generic lookup for subtypes */
406 return PyObject_GenericGetAttr((PyObject *)self, name);
408 /* Optimization: just look in dict ourselves */
409 value = PyDict_GetItem(ldict, name);
410 if (value == NULL)
411 /* Fall back on generic to get __class__ and __dict__ */
412 return PyObject_GenericGetAttr((PyObject *)self, name);
414 Py_INCREF(value);
415 return value;
418 /* Module functions */
420 struct bootstate {
421 PyInterpreterState *interp;
422 PyObject *func;
423 PyObject *args;
424 PyObject *keyw;
427 static void
428 t_bootstrap(void *boot_raw)
430 struct bootstate *boot = (struct bootstate *) boot_raw;
431 PyThreadState *tstate;
432 PyObject *res;
434 tstate = PyThreadState_New(boot->interp);
436 PyEval_AcquireThread(tstate);
437 res = PyEval_CallObjectWithKeywords(
438 boot->func, boot->args, boot->keyw);
439 if (res == NULL) {
440 if (PyErr_ExceptionMatches(PyExc_SystemExit))
441 PyErr_Clear();
442 else {
443 PyObject *file;
444 PySys_WriteStderr(
445 "Unhandled exception in thread started by ");
446 file = PySys_GetObject("stderr");
447 if (file)
448 PyFile_WriteObject(boot->func, file, 0);
449 else
450 PyObject_Print(boot->func, stderr, 0);
451 PySys_WriteStderr("\n");
452 PyErr_PrintEx(0);
455 else
456 Py_DECREF(res);
457 Py_DECREF(boot->func);
458 Py_DECREF(boot->args);
459 Py_XDECREF(boot->keyw);
460 PyMem_DEL(boot_raw);
461 PyThreadState_Clear(tstate);
462 PyThreadState_DeleteCurrent();
463 PyThread_exit_thread();
466 static PyObject *
467 thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
469 PyObject *func, *args, *keyw = NULL;
470 struct bootstate *boot;
471 long ident;
473 if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3,
474 &func, &args, &keyw))
475 return NULL;
476 if (!PyCallable_Check(func)) {
477 PyErr_SetString(PyExc_TypeError,
478 "first arg must be callable");
479 return NULL;
481 if (!PyTuple_Check(args)) {
482 PyErr_SetString(PyExc_TypeError,
483 "2nd arg must be a tuple");
484 return NULL;
486 if (keyw != NULL && !PyDict_Check(keyw)) {
487 PyErr_SetString(PyExc_TypeError,
488 "optional 3rd arg must be a dictionary");
489 return NULL;
491 boot = PyMem_NEW(struct bootstate, 1);
492 if (boot == NULL)
493 return PyErr_NoMemory();
494 boot->interp = PyThreadState_GET()->interp;
495 boot->func = func;
496 boot->args = args;
497 boot->keyw = keyw;
498 Py_INCREF(func);
499 Py_INCREF(args);
500 Py_XINCREF(keyw);
501 PyEval_InitThreads(); /* Start the interpreter's thread-awareness */
502 ident = PyThread_start_new_thread(t_bootstrap, (void*) boot);
503 if (ident == -1) {
504 PyErr_SetString(ThreadError, "can't start new thread");
505 Py_DECREF(func);
506 Py_DECREF(args);
507 Py_XDECREF(keyw);
508 PyMem_DEL(boot);
509 return NULL;
511 return PyInt_FromLong(ident);
514 PyDoc_STRVAR(start_new_doc,
515 "start_new_thread(function, args[, kwargs])\n\
516 (start_new() is an obsolete synonym)\n\
518 Start a new thread and return its identifier. The thread will call the\n\
519 function with positional arguments from the tuple args and keyword arguments\n\
520 taken from the optional dictionary kwargs. The thread exits when the\n\
521 function returns; the return value is ignored. The thread will also exit\n\
522 when the function raises an unhandled exception; a stack trace will be\n\
523 printed unless the exception is SystemExit.\n");
525 static PyObject *
526 thread_PyThread_exit_thread(PyObject *self)
528 PyErr_SetNone(PyExc_SystemExit);
529 return NULL;
532 PyDoc_STRVAR(exit_doc,
533 "exit()\n\
534 (PyThread_exit_thread() is an obsolete synonym)\n\
536 This is synonymous to ``raise SystemExit''. It will cause the current\n\
537 thread to exit silently unless the exception is caught.");
539 static PyObject *
540 thread_PyThread_interrupt_main(PyObject * self)
542 PyErr_SetInterrupt();
543 Py_INCREF(Py_None);
544 return Py_None;
547 PyDoc_STRVAR(interrupt_doc,
548 "interrupt_main()\n\
550 Raise a KeyboardInterrupt in the main thread.\n\
551 A subthread can use this function to interrupt the main thread."
554 #ifndef NO_EXIT_PROG
555 static PyObject *
556 thread_PyThread_exit_prog(PyObject *self, PyObject *args)
558 int sts;
559 if (!PyArg_ParseTuple(args, "i:exit_prog", &sts))
560 return NULL;
561 Py_Exit(sts); /* Calls PyThread_exit_prog(sts) or _PyThread_exit_prog(sts) */
562 for (;;) { } /* Should not be reached */
564 #endif
566 static lockobject *newlockobject(void);
568 static PyObject *
569 thread_PyThread_allocate_lock(PyObject *self)
571 return (PyObject *) newlockobject();
574 PyDoc_STRVAR(allocate_doc,
575 "allocate_lock() -> lock object\n\
576 (allocate() is an obsolete synonym)\n\
578 Create a new lock object. See LockType.__doc__ for information about locks.");
580 static PyObject *
581 thread_get_ident(PyObject *self)
583 long ident;
584 ident = PyThread_get_thread_ident();
585 if (ident == -1) {
586 PyErr_SetString(ThreadError, "no current thread ident");
587 return NULL;
589 return PyInt_FromLong(ident);
592 PyDoc_STRVAR(get_ident_doc,
593 "get_ident() -> integer\n\
595 Return a non-zero integer that uniquely identifies the current thread\n\
596 amongst other threads that exist simultaneously.\n\
597 This may be used to identify per-thread resources.\n\
598 Even though on some platforms threads identities may appear to be\n\
599 allocated consecutive numbers starting at 1, this behavior should not\n\
600 be relied upon, and the number should be seen purely as a magic cookie.\n\
601 A thread's identity may be reused for another thread after it exits.");
603 static PyObject *
604 thread_stack_size(PyObject *self, PyObject *args)
606 size_t old_size;
607 Py_ssize_t new_size = 0;
608 int rc;
610 if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size))
611 return NULL;
613 if (new_size < 0) {
614 PyErr_SetString(PyExc_ValueError,
615 "size must be 0 or a positive value");
616 return NULL;
619 old_size = PyThread_get_stacksize();
621 rc = PyThread_set_stacksize((size_t) new_size);
622 if (rc == -1) {
623 PyErr_Format(PyExc_ValueError,
624 "size not valid: %zd bytes",
625 new_size);
626 return NULL;
628 if (rc == -2) {
629 PyErr_SetString(ThreadError,
630 "setting stack size not supported");
631 return NULL;
634 return PyInt_FromSsize_t((Py_ssize_t) old_size);
637 PyDoc_STRVAR(stack_size_doc,
638 "stack_size([size]) -> size\n\
640 Return the thread stack size used when creating new threads. The\n\
641 optional size argument specifies the stack size (in bytes) to be used\n\
642 for subsequently created threads, and must be 0 (use platform or\n\
643 configured default) or a positive integer value of at least 32,768 (32k).\n\
644 If changing the thread stack size is unsupported, a ThreadError\n\
645 exception is raised. If the specified size is invalid, a ValueError\n\
646 exception is raised, and the stack size is unmodified. 32k bytes\n\
647 currently the minimum supported stack size value to guarantee\n\
648 sufficient stack space for the interpreter itself.\n\
650 Note that some platforms may have particular restrictions on values for\n\
651 the stack size, such as requiring a minimum stack size larger than 32kB or\n\
652 requiring allocation in multiples of the system memory page size\n\
653 - platform documentation should be referred to for more information\n\
654 (4kB pages are common; using multiples of 4096 for the stack size is\n\
655 the suggested approach in the absence of more specific information).");
657 static PyMethodDef thread_methods[] = {
658 {"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread,
659 METH_VARARGS,
660 start_new_doc},
661 {"start_new", (PyCFunction)thread_PyThread_start_new_thread,
662 METH_VARARGS,
663 start_new_doc},
664 {"allocate_lock", (PyCFunction)thread_PyThread_allocate_lock,
665 METH_NOARGS, allocate_doc},
666 {"allocate", (PyCFunction)thread_PyThread_allocate_lock,
667 METH_NOARGS, allocate_doc},
668 {"exit_thread", (PyCFunction)thread_PyThread_exit_thread,
669 METH_NOARGS, exit_doc},
670 {"exit", (PyCFunction)thread_PyThread_exit_thread,
671 METH_NOARGS, exit_doc},
672 {"interrupt_main", (PyCFunction)thread_PyThread_interrupt_main,
673 METH_NOARGS, interrupt_doc},
674 {"get_ident", (PyCFunction)thread_get_ident,
675 METH_NOARGS, get_ident_doc},
676 {"stack_size", (PyCFunction)thread_stack_size,
677 METH_VARARGS,
678 stack_size_doc},
679 #ifndef NO_EXIT_PROG
680 {"exit_prog", (PyCFunction)thread_PyThread_exit_prog,
681 METH_VARARGS},
682 #endif
683 {NULL, NULL} /* sentinel */
687 /* Initialization function */
689 PyDoc_STRVAR(thread_doc,
690 "This module provides primitive operations to write multi-threaded programs.\n\
691 The 'threading' module provides a more convenient interface.");
693 PyDoc_STRVAR(lock_doc,
694 "A lock object is a synchronization primitive. To create a lock,\n\
695 call the PyThread_allocate_lock() function. Methods are:\n\
697 acquire() -- lock the lock, possibly blocking until it can be obtained\n\
698 release() -- unlock of the lock\n\
699 locked() -- test whether the lock is currently locked\n\
701 A lock is not owned by the thread that locked it; another thread may\n\
702 unlock it. A thread attempting to lock a lock that it has already locked\n\
703 will block until another thread unlocks it. Deadlocks may ensue.");
705 PyMODINIT_FUNC
706 initthread(void)
708 PyObject *m, *d;
710 /* Initialize types: */
711 if (PyType_Ready(&localtype) < 0)
712 return;
714 /* Create the module and add the functions */
715 m = Py_InitModule3("thread", thread_methods, thread_doc);
716 if (m == NULL)
717 return;
719 /* Add a symbolic constant */
720 d = PyModule_GetDict(m);
721 ThreadError = PyErr_NewException("thread.error", NULL, NULL);
722 PyDict_SetItemString(d, "error", ThreadError);
723 Locktype.tp_doc = lock_doc;
724 if (PyType_Ready(&Locktype) < 0)
725 return;
726 Py_INCREF(&Locktype);
727 PyDict_SetItemString(d, "LockType", (PyObject *)&Locktype);
729 Py_INCREF(&localtype);
730 if (PyModule_AddObject(m, "_local", (PyObject *)&localtype) < 0)
731 return;
733 /* Initialize the C thread library */
734 PyThread_init_thread();