=== modified file 'Include/pythread.h' --- Include/pythread.h 2006-06-13 15:04:24 +0000 +++ Include/pythread.h 2008-06-11 23:12:47 +0000 @@ -40,6 +40,9 @@ PyAPI_FUNC(void *) PyThread_get_key_value(int); PyAPI_FUNC(void) PyThread_delete_key_value(int key); +/* Cleanup after a fork */ +PyAPI_FUNC(void) PyThread_ReInitTLS(void); + #ifdef __cplusplus } #endif === modified file 'Modules/signalmodule.c' --- Modules/signalmodule.c 2008-03-24 13:54:23 +0000 +++ Modules/signalmodule.c 2008-06-11 23:10:32 +0000 @@ -925,5 +925,6 @@ main_thread = PyThread_get_thread_ident(); main_pid = getpid(); _PyImport_ReInitLock(); + PyThread_ReInitTLS(); #endif } === modified file 'Parser/intrcheck.c' --- Parser/intrcheck.c 2004-10-13 14:48:50 +0000 +++ Parser/intrcheck.c 2008-06-11 23:16:55 +0000 @@ -2,6 +2,7 @@ /* Check for interrupts */ #include "Python.h" +#include "pythread.h" #ifdef QUICKWIN @@ -172,5 +173,6 @@ { #ifdef WITH_THREAD PyEval_ReInitThreads(); + PyThread_ReInitTLS(); #endif } === modified file 'Python/thread.c' --- Python/thread.c 2008-01-07 17:25:53 +0000 +++ Python/thread.c 2008-06-11 23:10:32 +0000 @@ -381,4 +381,35 @@ PyThread_release_lock(keymutex); } +/* Forget everything not associated with the current thread id. + * This function is called from PyOS_AfterFork(). It is necessary + * because other thread ids which were in use at the time of the fork + * may be reused for new threads created in the forked process. + */ +void +PyThread_ReInitTLS(void) +{ + long id = PyThread_get_thread_ident(); + struct key *p, **q; + + if (!keymutex) + return; + + /* As with interpreter_lock in PyEval_ReInitThreads() + we just create a new lock without freeing the old one */ + keymutex = PyThread_allocate_lock(); + + /* Delete all keys which do not match the current thread id */ + q = &keyhead; + while ((p = *q) != NULL) { + if (p->id != id) { + *q = p->next; + free((void *)p); + /* NB This does *not* free p->value! */ + } + else + q = &p->next; + } +} + #endif /* Py_HAVE_NATIVE_TLS */