diff options
-rw-r--r-- | Misc/NEWS | 11 | ||||
-rw-r--r-- | Python/thread_nt.h | 53 |
2 files changed, 41 insertions, 23 deletions
@@ -10,6 +10,17 @@ What's New in Python 2.3 release candidate? Core and builtins ----------------- +- The Windows implementation of PyThread_start_new_thread() never + checked error returns from Windows functions correctly. As a result, + it could claim to start a new thread even when the Microsoft + _beginthread() function failed (due to "too many threads" -- this is + on the order of thousands when it happens). In these cases, the + Python exception :: + + thread.error: can't start new thread + + is raised now. + Extension modules ----------------- diff --git a/Python/thread_nt.h b/Python/thread_nt.h index 44814c6..7d2290e 100644 --- a/Python/thread_nt.h +++ b/Python/thread_nt.h @@ -148,7 +148,7 @@ static void PyThread__init_thread(void) typedef struct { void (*func)(void*); - void *arg; + void *arg; long id; HANDLE done; } callobj; @@ -167,35 +167,42 @@ bootstrap(void *call) return 0; } -long PyThread_start_new_thread(void (*func)(void *), void *arg) +long +PyThread_start_new_thread(void (*func)(void *), void *arg) { unsigned long rv; - int success = 0; - callobj *obj; - int id; + callobj obj; - dprintf(("%ld: PyThread_start_new_thread called\n", PyThread_get_thread_ident())); + dprintf(("%ld: PyThread_start_new_thread called\n", + PyThread_get_thread_ident())); if (!initialized) PyThread_init_thread(); - obj = malloc(sizeof(callobj)); - obj->func = func; - obj->arg = arg; - obj->done = CreateSemaphore(NULL, 0, 1, NULL); - - rv = _beginthread(bootstrap, 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)); + obj.id = -1; /* guilty until proved innocent */ + obj.func = func; + obj.arg = arg; + obj.done = CreateSemaphore(NULL, 0, 1, NULL); + if (obj.done == NULL) + return -1; + + rv = _beginthread(bootstrap, 0, &obj); /* use default stack size */ + if (rv == (unsigned long)-1) { + /* I've seen errno == EAGAIN here, which means "there are + * too many threads". + */ + dprintf(("%ld: PyThread_start_new_thread failed: %p errno %d\n", + PyThread_get_thread_ident(), rv, errno)); + obj.id = -1; } - - /* wait for thread to initialize and retrieve id */ - WaitForSingleObject(obj->done, 5000); /* maybe INFINITE instead of 5000? */ - CloseHandle((HANDLE)obj->done); - id = obj->id; - free(obj); - return id; + else { + dprintf(("%ld: PyThread_start_new_thread succeeded: %p\n", + PyThread_get_thread_ident(), rv)); + /* wait for thread to initialize, so we can get its id */ + WaitForSingleObject(obj.done, INFINITE); + assert(obj.id != -1); + } + CloseHandle((HANDLE)obj.done); + return obj.id; } /* |