@@ -35,14 +35,13 @@ PERFORMANCE OF THIS SOFTWARE.
3535#include"Python.h"
36363737#ifndefWITH_THREAD
38-Error! TherestofPythonisnotcompiledwiththreadsupport.
39-Rerunconfigure, addinga--with-threadoption.
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-externint_PyThread_Started;
45-4645staticPyObject*ThreadError;
47464847@@ -192,52 +191,90 @@ static PyTypeObject Locktype = {
192191193192/* Module functions */
194193194+structbootstate {
195+PyInterpreterState*interp;
196+PyObject*func;
197+PyObject*args;
198+PyObject*keyw;
199+};
200+195201staticvoid
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+structbootstate*boot= (structbootstate*) 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}
222233223234staticPyObject*
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+structbootstate*boot;
229241230-if (!PyArg_Parse(args, "(OO)", &func, &arg))
242+if (!PyArg_ParseTuple(fargs, "OO|O", &func, &args, &keyw))
243+returnNULL;
244+if (!PyCallable_Check(func)) {
245+PyErr_SetString(PyExc_TypeError,
246+"first arg must be callable");
231247returnNULL;
248+ }
249+if (!PyTuple_Check(args)) {
250+PyErr_SetString(PyExc_TypeError,
251+"optional 2nd arg must be a tuple");
252+returnNULL;
253+ }
254+if (keyw!=NULL&& !PyDict_Check(keyw)) {
255+PyErr_SetString(PyExc_TypeError,
256+"optional 3rd arg must be a dictionary");
257+returnNULL;
258+ }
259+boot=PyMem_NEW(structbootstate, 1);
260+if (boot==NULL)
261+returnPyErr_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);
238276returnNULL;
239277 }
240-/* Otherwise the DECREF(args) is done by t_bootstrap */
241278Py_INCREF(Py_None);
242279returnPy_None;
243280}
@@ -294,8 +331,8 @@ thread_get_ident(self, args)
294331}
295332296333staticPyMethodDefthread_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},