@@ -35,14 +35,13 @@ PERFORMANCE OF THIS SOFTWARE.
3535#include "Python.h"
3636
3737#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
4142
4243#include "thread.h"
4344
44- extern int _PyThread_Started ;
45-
4645static PyObject * ThreadError ;
4746
4847
@@ -192,52 +191,90 @@ static PyTypeObject Locktype = {
192191
193192/* Module functions */
194193
194+ 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 ;
203208
209+ tstate = PyThreadState_New (boot -> interp );
204210 PyEval_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 );
209218 if (res == NULL ) {
210219 if (PyErr_Occurred () == PyExc_SystemExit )
211220 PyErr_Clear ();
212221 else {
213222 fprintf (stderr , "Unhandled exception in thread:\n" );
214- PyErr_Print (); /* From pythonmain.c */
223+ PyErr_Print ();
215224 }
216225 }
217226 else
218227 Py_DECREF (res );
219- (void ) PyEval_SaveThread (); /* Should always be NULL */
228+ (void ) PyThreadState_Swap (alttstate );
229+ (void ) PyEval_SaveThread ();
230+ PyThreadState_Delete (tstate );
220231 exit_thread ();
221232}
222233
223234static PyObject *
224- thread_start_new_thread (self , args )
235+ thread_start_new_thread (self , fargs )
225236 PyObject * 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 ;
229241
230- 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" );
231247 return 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 );
232267 Py_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 )) {
237271 PyErr_SetString (ThreadError , "can't start new thread\n" );
272+ Py_DECREF (func );
273+ Py_DECREF (args );
274+ Py_XDECREF (keyw );
275+ PyMem_DEL (boot );
238276 return NULL ;
239277 }
240- /* Otherwise the DECREF(args) is done by t_bootstrap */
241278 Py_INCREF (Py_None );
242279 return Py_None ;
243280}
@@ -294,8 +331,8 @@ thread_get_ident(self, args)
294331}
295332
296333static 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 },
0 commit comments