Skip to content

Commit 5dff0d7

Browse files
author
benjamin.peterson
committed
#1683 prevent forking from interfering in threading storage
This should prevent some test_multiprocessing failures git-svn-id: http://svn.python.org/projects/python/trunk@64212 6015fed2-1504-0410-9fe1-9d1591cc4771
1 parent 6c0bb21 commit 5dff0d7

4 files changed

Lines changed: 37 additions & 0 deletions

File tree

Include/pythread.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ PyAPI_FUNC(int) PyThread_set_key_value(int, void *);
4040
PyAPI_FUNC(void *) PyThread_get_key_value(int);
4141
PyAPI_FUNC(void) PyThread_delete_key_value(int key);
4242

43+
/* Cleanup after a fork */
44+
PyAPI_FUNC(void) PyThread_ReInitTLS(void);
45+
4346
#ifdef __cplusplus
4447
}
4548
#endif

Modules/signalmodule.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -925,5 +925,6 @@ PyOS_AfterFork(void)
925925
main_thread = PyThread_get_thread_ident();
926926
main_pid = getpid();
927927
_PyImport_ReInitLock();
928+
PyThread_ReInitTLS();
928929
#endif
929930
}

Parser/intrcheck.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
/* Check for interrupts */
33

44
#include "Python.h"
5+
#include "pythread.h"
56

67
#ifdef QUICKWIN
78

@@ -172,5 +173,6 @@ PyOS_AfterFork(void)
172173
{
173174
#ifdef WITH_THREAD
174175
PyEval_ReInitThreads();
176+
PyThread_ReInitTLS();
175177
#endif
176178
}

Python/thread.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,4 +381,35 @@ PyThread_delete_key_value(int key)
381381
PyThread_release_lock(keymutex);
382382
}
383383

384+
/* Forget everything not associated with the current thread id.
385+
* This function is called from PyOS_AfterFork(). It is necessary
386+
* because other thread ids which were in use at the time of the fork
387+
* may be reused for new threads created in the forked process.
388+
*/
389+
void
390+
PyThread_ReInitTLS(void)
391+
{
392+
long id = PyThread_get_thread_ident();
393+
struct key *p, **q;
394+
395+
if (!keymutex)
396+
return;
397+
398+
/* As with interpreter_lock in PyEval_ReInitThreads()
399+
we just create a new lock without freeing the old one */
400+
keymutex = PyThread_allocate_lock();
401+
402+
/* Delete all keys which do not match the current thread id */
403+
q = &keyhead;
404+
while ((p = *q) != NULL) {
405+
if (p->id != id) {
406+
*q = p->next;
407+
free((void *)p);
408+
/* NB This does *not* free p->value! */
409+
}
410+
else
411+
q = &p->next;
412+
}
413+
}
414+
384415
#endif /* Py_HAVE_NATIVE_TLS */

0 commit comments

Comments
 (0)