@@ -35,14 +35,13 @@ PERFORMANCE OF THIS SOFTWARE.
3535#include "Python.h"
36363737#ifndef WITH_THREAD
38-Error! The rest of Python is not compiled with thread support.
39-Rerun configure, adding a --with-thread option.
38+#error "Error! The rest of Python is not compiled with thread support."
39+#error "Rerun configure, adding a --with-thread option."
40+#error "Then run `make clean' followed by `make'."
4041#endif
41424243#include "thread.h"
434444-extern int _PyThread_Started;
45-4645static PyObject *ThreadError;
47464847@@ -192,52 +191,90 @@ static PyTypeObject Locktype = {
192191193192/* Module functions */
194193194+struct bootstate {
195+PyInterpreterState *interp;
196+PyObject *func;
197+PyObject *args;
198+PyObject *keyw;
199+};
200+195201static void
196-t_bootstrap(args_raw)
197-void *args_raw;
202+t_bootstrap(boot_raw)
203+void *boot_raw;
198204{
199-PyObject *args = (PyObject *) args_raw;
200-PyObject *func, *arg, *res;
201-202-_PyThread_Started++;
205+struct bootstate *boot = (struct bootstate *) boot_raw;
206+PyThreadState *alttstate, *tstate;
207+PyObject *res;
203208209+tstate = PyThreadState_New(boot->interp);
204210PyEval_RestoreThread((void *)NULL);
205-func = PyTuple_GetItem(args, 0);
206-arg = PyTuple_GetItem(args, 1);
207-res = PyEval_CallObject(func, arg);
208-Py_DECREF(args); /* Matches the INCREF(args) in thread_start_new_thread */
211+alttstate = PyThreadState_Swap(tstate);
212+res = PyEval_CallObjectWithKeywords(
213+boot->func, boot->args, boot->keyw);
214+Py_DECREF(boot->func);
215+Py_DECREF(boot->args);
216+Py_XDECREF(boot->keyw);
217+PyMem_DEL(boot_raw);
209218if (res == NULL) {
210219if (PyErr_Occurred() == PyExc_SystemExit)
211220PyErr_Clear();
212221else {
213222fprintf(stderr, "Unhandled exception in thread:\n");
214-PyErr_Print(); /* From pythonmain.c */
223+PyErr_Print();
215224 }
216225 }
217226else
218227Py_DECREF(res);
219- (void) PyEval_SaveThread(); /* Should always be NULL */
228+ (void) PyThreadState_Swap(alttstate);
229+ (void) PyEval_SaveThread();
230+PyThreadState_Delete(tstate);
220231exit_thread();
221232}
222233223234static PyObject *
224-thread_start_new_thread(self, args)
235+thread_start_new_thread(self, fargs)
225236PyObject *self; /* Not used */
226-PyObject *args;
237+PyObject *fargs;
227238{
228-PyObject *func, *arg;
239+PyObject *func, *args = NULL, *keyw = NULL;
240+struct bootstate *boot;
229241230-if (!PyArg_Parse(args, "(OO)", &func, &arg))
242+if (!PyArg_ParseTuple(fargs, "OO|O", &func, &args, &keyw))
243+return NULL;
244+if (!PyCallable_Check(func)) {
245+PyErr_SetString(PyExc_TypeError,
246+"first arg must be callable");
231247return NULL;
248+ }
249+if (!PyTuple_Check(args)) {
250+PyErr_SetString(PyExc_TypeError,
251+"optional 2nd arg must be a tuple");
252+return NULL;
253+ }
254+if (keyw != NULL && !PyDict_Check(keyw)) {
255+PyErr_SetString(PyExc_TypeError,
256+"optional 3rd arg must be a dictionary");
257+return NULL;
258+ }
259+boot = PyMem_NEW(struct bootstate, 1);
260+if (boot == NULL)
261+return PyErr_NoMemory();
262+boot->interp = PyThreadState_Get()->interpreter_state;
263+boot->func = func;
264+boot->args = args;
265+boot->keyw = keyw;
266+Py_INCREF(func);
232267Py_INCREF(args);
233-/* Initialize the interpreter's stack save/restore mechanism */
234-PyEval_InitThreads();
235-if (!start_new_thread(t_bootstrap, (void*) args)) {
236-Py_DECREF(args);
268+Py_XINCREF(keyw);
269+PyEval_InitThreads(); /* Start the interpreter's thread-awareness */
270+if (!start_new_thread(t_bootstrap, (void*) boot)) {
237271PyErr_SetString(ThreadError, "can't start new thread\n");
272+Py_DECREF(func);
273+Py_DECREF(args);
274+Py_XDECREF(keyw);
275+PyMem_DEL(boot);
238276return NULL;
239277 }
240-/* Otherwise the DECREF(args) is done by t_bootstrap */
241278Py_INCREF(Py_None);
242279return Py_None;
243280}
@@ -294,8 +331,8 @@ thread_get_ident(self, args)
294331}
295332296333static PyMethodDef thread_methods[] = {
297- {"start_new_thread", (PyCFunction)thread_start_new_thread},
298- {"start_new", (PyCFunction)thread_start_new_thread},
334+ {"start_new_thread", (PyCFunction)thread_start_new_thread, 1},
335+ {"start_new", (PyCFunction)thread_start_new_thread, 1},
299336 {"allocate_lock", (PyCFunction)thread_allocate_lock},
300337 {"allocate", (PyCFunction)thread_allocate_lock},
301338 {"exit_thread", (PyCFunction)thread_exit_thread},