summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Doc/lib/libthread.tex9
-rw-r--r--Include/pythread.h2
-rw-r--r--Misc/NEWS9
-rw-r--r--Modules/threadmodule.c19
-rw-r--r--Python/thread.c1
-rw-r--r--Python/thread_beos.h4
-rw-r--r--Python/thread_cthread.h4
-rw-r--r--Python/thread_foobar.h4
-rw-r--r--Python/thread_lwp.h4
-rw-r--r--Python/thread_nt.h48
-rw-r--r--Python/thread_os2.h6
-rw-r--r--Python/thread_pth.h4
-rw-r--r--Python/thread_pthread.h8
-rw-r--r--Python/thread_sgi.h4
-rw-r--r--Python/thread_solaris.h7
-rw-r--r--Python/thread_wince.h6
16 files changed, 97 insertions, 42 deletions
diff --git a/Doc/lib/libthread.tex b/Doc/lib/libthread.tex
index 652058da37..a2e5b7e4a0 100644
--- a/Doc/lib/libthread.tex
+++ b/Doc/lib/libthread.tex
@@ -32,11 +32,10 @@ This is the type of lock objects.
\end{datadesc}
\begin{funcdesc}{start_new_thread}{function, args\optional{, kwargs}}
-Start a new thread. The thread executes the function \var{function}
-with the argument list \var{args} (which must be a tuple). The
-optional \var{kwargs} argument specifies a dictionary of keyword
-arguments. When the
-function returns, the thread silently exits. When the function
+Start a new thread and return its identifier. The thread executes the function
+\var{function} with the argument list \var{args} (which must be a tuple). The
+optional \var{kwargs} argument specifies a dictionary of keyword arguments.
+When the function returns, the thread silently exits. When the function
terminates with an unhandled exception, a stack trace is printed and
then the thread exits (but other threads continue to run).
\end{funcdesc}
diff --git a/Include/pythread.h b/Include/pythread.h
index c0a718e5ad..514cdeafe0 100644
--- a/Include/pythread.h
+++ b/Include/pythread.h
@@ -13,7 +13,7 @@ extern "C" {
#endif
DL_IMPORT(void) PyThread_init_thread(void);
-DL_IMPORT(int) PyThread_start_new_thread(void (*)(void *), void *);
+DL_IMPORT(long) PyThread_start_new_thread(void (*)(void *), void *);
DL_IMPORT(void) PyThread_exit_thread(void);
DL_IMPORT(void) PyThread__PyThread_exit_thread(void);
DL_IMPORT(long) PyThread_get_thread_ident(void);
diff --git a/Misc/NEWS b/Misc/NEWS
index 690759b170..1d86a4313e 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -39,6 +39,8 @@ Core
Library
+- thread.start_new_thread() now returns the thread ID (previously None).
+
- doctest now excludes functions and classes not defined by the module
being tested, thanks to Tim Hochberg.
@@ -91,6 +93,13 @@ C API
Consequently, PyArg_ParseTuple's 'L' code also accepts int (as well
as long) arguments.
+- PyThread_start_new_thread() now returns a long int giving the thread
+ ID, if one can be calculated; it returns -1 for error, 0 if no
+ thread ID is calculated (this is an incompatible change, but only
+ the thread module used this API). This code has only really been
+ tested on Linux and Windows; other platforms please beware (and
+ report any bugs or strange behavior).
+
New platforms
Tests
diff --git a/Modules/threadmodule.c b/Modules/threadmodule.c
index 7050914b06..bdc7932c6e 100644
--- a/Modules/threadmodule.c
+++ b/Modules/threadmodule.c
@@ -213,6 +213,7 @@ thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
{
PyObject *func, *args, *keyw = NULL;
struct bootstate *boot;
+ long ident;
if (!PyArg_ParseTuple(fargs, "OO|O:start_new_thread", &func, &args, &keyw))
return NULL;
@@ -242,7 +243,8 @@ thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
Py_INCREF(args);
Py_XINCREF(keyw);
PyEval_InitThreads(); /* Start the interpreter's thread-awareness */
- if (!PyThread_start_new_thread(t_bootstrap, (void*) boot)) {
+ ident = PyThread_start_new_thread(t_bootstrap, (void*) boot);
+ if (ident == -1) {
PyErr_SetString(ThreadError, "can't start new thread\n");
Py_DECREF(func);
Py_DECREF(args);
@@ -250,20 +252,19 @@ thread_PyThread_start_new_thread(PyObject *self, PyObject *fargs)
PyMem_DEL(boot);
return NULL;
}
- Py_INCREF(Py_None);
- return Py_None;
+ return PyInt_FromLong(ident);
}
static char start_new_doc[] =
"start_new_thread(function, args[, kwargs])\n\
(start_new() is an obsolete synonym)\n\
\n\
-Start a new thread. The thread will call the function with positional\n\
-arguments from the tuple args and keyword arguments taken from the optional\n\
-dictionary kwargs. The thread exits when the function returns; the return\n\
-value is ignored. The thread will also exit when the function raises an\n\
-unhandled exception; a stack trace will be printed unless the exception is\n\
-SystemExit.";
+Start a new thread and return its identifier. The thread will call the\n\
+function with positional arguments from the tuple args and keyword arguments\n\
+taken from the optional dictionary kwargs. The thread exits when the\n\
+function returns; the return value is ignored. The thread will also exit\n\
+when the function raises an unhandled exception; a stack trace will be\n\
+printed unless the exception is SystemExit.\n";
static PyObject *
thread_PyThread_exit_thread(PyObject *self, PyObject *args)
diff --git a/Python/thread.c b/Python/thread.c
index 3558af0afc..df42f316be 100644
--- a/Python/thread.c
+++ b/Python/thread.c
@@ -111,7 +111,6 @@ void PyThread_init_thread(void)
#ifdef HAVE_PTH
#include "thread_pth.h"
-#undef _POSIX_THREADS
#endif
#ifdef _POSIX_THREADS
diff --git a/Python/thread_beos.h b/Python/thread_beos.h
index 046d37eea7..3f843474bf 100644
--- a/Python/thread_beos.h
+++ b/Python/thread_beos.h
@@ -112,7 +112,7 @@ static void PyThread__init_thread( void )
static int32 thread_count = 0;
-int PyThread_start_new_thread( void (*func)(void *), void *arg )
+long PyThread_start_new_thread( void (*func)(void *), void *arg )
{
status_t success = 0;
thread_id tid;
@@ -131,7 +131,7 @@ int PyThread_start_new_thread( void (*func)(void *), void *arg )
success = resume_thread( tid );
}
- return ( success == B_NO_ERROR ? 1 : 0 );
+ return ( success == B_NO_ERROR ? tid : -1 );
}
long PyThread_get_thread_ident( void )
diff --git a/Python/thread_cthread.h b/Python/thread_cthread.h
index 080505134d..8487cc295f 100644
--- a/Python/thread_cthread.h
+++ b/Python/thread_cthread.h
@@ -14,7 +14,7 @@ PyThread__init_thread(void)
/*
* Thread support.
*/
-int
+long
PyThread_start_new_thread(void (*func)(void *), void *arg)
{
int success = 0; /* init not needed when SOLARIS_THREADS and */
@@ -27,7 +27,7 @@ PyThread_start_new_thread(void (*func)(void *), void *arg)
* so well do it here
*/
cthread_detach(cthread_fork((cthread_fn_t) func, arg));
- return success < 0 ? 0 : 1;
+ return success < 0 ? -1 : 0;
}
long
diff --git a/Python/thread_foobar.h b/Python/thread_foobar.h
index 6edd0f93a5..4baf7e7846 100644
--- a/Python/thread_foobar.h
+++ b/Python/thread_foobar.h
@@ -10,7 +10,7 @@ PyThread__init_thread(void)
/*
* Thread support.
*/
-int
+long
PyThread_start_new_thread(void (*func)(void *), void *arg)
{
int success = 0; /* init not needed when SOLARIS_THREADS and */
@@ -19,7 +19,7 @@ PyThread_start_new_thread(void (*func)(void *), void *arg)
dprintf(("PyThread_start_new_thread called\n"));
if (!initialized)
PyThread_init_thread();
- return success < 0 ? 0 : 1;
+ return success < 0 ? -1 : 0;
}
long
diff --git a/Python/thread_lwp.h b/Python/thread_lwp.h
index bf44e0425c..f6e688568b 100644
--- a/Python/thread_lwp.h
+++ b/Python/thread_lwp.h
@@ -26,7 +26,7 @@ static void PyThread__init_thread(void)
*/
-int PyThread_start_new_thread(void (*func)(void *), void *arg)
+long PyThread_start_new_thread(void (*func)(void *), void *arg)
{
thread_t tid;
int success;
@@ -34,7 +34,7 @@ int PyThread_start_new_thread(void (*func)(void *), void *arg)
if (!initialized)
PyThread_init_thread();
success = lwp_create(&tid, func, MINPRIO, 0, lwp_newstk(), 1, arg);
- return success < 0 ? 0 : 1;
+ return success < 0 ? -1 : 0;
}
long PyThread_get_thread_ident(void)
diff --git a/Python/thread_nt.h b/Python/thread_nt.h
index 1d276274eb..21aac29a49 100644
--- a/Python/thread_nt.h
+++ b/Python/thread_nt.h
@@ -5,6 +5,7 @@
#include <windows.h>
#include <limits.h>
#include <process.h>
+#include <Python.h>
typedef struct NRMUTEX {
LONG owned ;
@@ -12,6 +13,8 @@ typedef struct NRMUTEX {
HANDLE hevent ;
} NRMUTEX, *PNRMUTEX ;
+/* dictionary to correlate thread ids with the handle needed to terminate them*/
+static PyObject *threads = NULL;
typedef PVOID WINAPI interlocked_cmp_xchg_t(PVOID *dest, PVOID exc, PVOID comperand) ;
@@ -145,28 +148,67 @@ long PyThread_get_thread_ident(void);
*/
static void PyThread__init_thread(void)
{
+ threads = PyDict_New();
}
/*
* Thread support.
*/
-int PyThread_start_new_thread(void (*func)(void *), void *arg)
+
+typedef struct {
+ void (*func)(void*);
+ void *arg;
+ long id;
+ HANDLE done;
+} callobj;
+
+static int
+bootstrap(void *call)
+{
+ callobj *obj = (callobj*)call;
+ /* copy callobj since other thread might free it before we're done */
+ void (*func)(void*) = obj->func;
+ void *arg = obj->arg;
+
+ obj->id = PyThread_get_thread_ident();
+ ReleaseSemaphore(obj->done, 1, NULL);
+ func(arg);
+ return 0;
+}
+
+long PyThread_start_new_thread(void (*func)(void *), void *arg)
{
unsigned long rv;
int success = 0;
+ callobj *obj;
+ int id;
+ PyObject *key, *val;
dprintf(("%ld: PyThread_start_new_thread called\n", PyThread_get_thread_ident()));
if (!initialized)
PyThread_init_thread();
- rv = _beginthread(func, 0, arg); /* use default stack size */
+ obj = malloc(sizeof(callobj));
+ obj->func = func;
+ obj->arg = arg;
+ obj->done = CreateSemaphore(NULL, 0, 1, NULL);
+
+ rv = _beginthread(func, 0, obj); /* use default stack size */
if (rv != (unsigned long)-1) {
success = 1;
dprintf(("%ld: PyThread_start_new_thread succeeded: %p\n", PyThread_get_thread_ident(), rv));
}
- return success;
+ /* wait for thread to initialize and retrieve id */
+ WaitForSingleObject(obj->done, 5000); /* maybe INFINITE instead of 5000? */
+ CloseHandle((HANDLE)obj->done);
+ key = PyLong_FromLong(obj->id);
+ val = PyLong_FromLong((long)rv);
+ PyDict_SetItem(threads, key, val);
+ id = obj->id;
+ free(obj);
+ return id;
}
/*
diff --git a/Python/thread_os2.h b/Python/thread_os2.h
index 3f913c5dbe..31800d6c26 100644
--- a/Python/thread_os2.h
+++ b/Python/thread_os2.h
@@ -21,16 +21,16 @@ PyThread__init_thread(void)
/*
* Thread support.
*/
-int
+long
PyThread_start_new_thread(void (*func)(void *), void *arg)
{
int aThread;
- int success = 1;
+ int success = 0;
aThread = _beginthread(func,NULL,65536,arg);
if( aThread == -1 ) {
- success = 0;
+ success = -1;
fprintf(stderr,"aThread failed == %d",aThread);
dprintf(("_beginthread failed. return %ld\n", errno));
}
diff --git a/Python/thread_pth.h b/Python/thread_pth.h
index 6596b1a8c7..71e0d042cf 100644
--- a/Python/thread_pth.h
+++ b/Python/thread_pth.h
@@ -44,7 +44,7 @@ static void PyThread__init_thread(void)
*/
-int PyThread_start_new_thread(void (*func)(void *), void *arg)
+long PyThread_start_new_thread(void (*func)(void *), void *arg)
{
pth_t th;
dprintf(("PyThread_start_new_thread called\n"));
@@ -56,7 +56,7 @@ int PyThread_start_new_thread(void (*func)(void *), void *arg)
(void *)arg
);
- return th == NULL ? 0 : 1;
+ return th;
}
long PyThread_get_thread_ident(void)
diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h
index 7170c8a812..0fbafdafc7 100644
--- a/Python/thread_pthread.h
+++ b/Python/thread_pthread.h
@@ -143,7 +143,7 @@ PyThread__init_thread(void)
*/
-int
+long
PyThread_start_new_thread(void (*func)(void *), void *arg)
{
pthread_t th;
@@ -210,7 +210,11 @@ PyThread_start_new_thread(void (*func)(void *), void *arg)
pthread_detach(th);
#endif
}
- return success != 0 ? 0 : 1;
+#if SIZEOF_PTHREAD_T <= SIZEOF_LONG
+ return (long) th;
+#else
+ return (long) *(long *) &th;
+#endif
}
/* XXX This implementation is considered (to quote Tim Peters) "inherently
diff --git a/Python/thread_sgi.h b/Python/thread_sgi.h
index 863284e412..eda79726f7 100644
--- a/Python/thread_sgi.h
+++ b/Python/thread_sgi.h
@@ -168,7 +168,7 @@ static void clean_threads(void)
}
}
-int PyThread_start_new_thread(void (*func)(void *), void *arg)
+long PyThread_start_new_thread(void (*func)(void *), void *arg)
{
#ifdef USE_DL
long addr, size;
@@ -223,7 +223,7 @@ int PyThread_start_new_thread(void (*func)(void *), void *arg)
}
if (usunsetlock(count_lock) < 0)
perror("usunsetlock (count_lock)");
- return success < 0 ? 0 : 1;
+ return success;
}
long PyThread_get_thread_ident(void)
diff --git a/Python/thread_solaris.h b/Python/thread_solaris.h
index 66bdfa25a3..4c958b915e 100644
--- a/Python/thread_solaris.h
+++ b/Python/thread_solaris.h
@@ -36,9 +36,10 @@ new_func(void *funcarg)
}
-int
+long
PyThread_start_new_thread(void (*func)(void *), void *arg)
{
+ thread_t tid;
struct func_arg *funcarg;
int success = 0; /* init not needed when SOLARIS_THREADS and */
/* C_THREADS implemented properly */
@@ -50,12 +51,12 @@ PyThread_start_new_thread(void (*func)(void *), void *arg)
funcarg->func = func;
funcarg->arg = arg;
if (thr_create(0, 0, new_func, funcarg,
- THR_DETACHED | THR_NEW_LWP, 0)) {
+ THR_DETACHED | THR_NEW_LWP, &tid)) {
perror("thr_create");
free((void *) funcarg);
success = -1;
}
- return success < 0 ? 0 : 1;
+ return tid;
}
long
diff --git a/Python/thread_wince.h b/Python/thread_wince.h
index 3790bdab7d..b5129b2149 100644
--- a/Python/thread_wince.h
+++ b/Python/thread_wince.h
@@ -22,10 +22,10 @@ static void PyThread__init_thread(void)
/*
* Thread support.
*/
-int PyThread_start_new_thread(void (*func)(void *), void *arg)
+long PyThread_start_new_thread(void (*func)(void *), void *arg)
{
long rv;
- int success = 0;
+ int success = -1;
dprintf(("%ld: PyThread_start_new_thread called\n", PyThread_get_thread_ident()));
if (!initialized)
@@ -34,7 +34,7 @@ int PyThread_start_new_thread(void (*func)(void *), void *arg)
rv = _beginthread(func, 0, arg); /* use default stack size */
if (rv != -1) {
- success = 1;
+ success = 0;
dprintf(("%ld: PyThread_start_new_thread succeeded:\n", PyThread_get_thread_ident()));
}