]> granicus.if.org Git - python/commitdiff
Backport of r64212
authorMartin v. Löwis <martin@v.loewis.de>
Sat, 13 Dec 2008 14:59:04 +0000 (14:59 +0000)
committerMartin v. Löwis <martin@v.loewis.de>
Sat, 13 Dec 2008 14:59:04 +0000 (14:59 +0000)
Issue #1683: prevent forking from interfering in threading storage.

Include/pythread.h
Misc/NEWS
Modules/signalmodule.c
Parser/intrcheck.c
Python/thread.c

index f26db160bf4bea53cca0c9f564850c64ab52c7b3..b5a6ec38a6efda9608a739f11e432252a1d861bd 100644 (file)
@@ -40,6 +40,9 @@ PyAPI_FUNC(int) PyThread_set_key_value(int, void *);
 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
index 99936660cf711d7d323bb08cf0a52ba7ac736fa5..b83c73169c9466ab8499c51ded5e33f7cec2130f 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,8 @@ What's New in Python 2.5.3?
 Core and builtins
 -----------------
 
+- Issue #1683: prevent forking from interfering in threading storage.
+
 - Issue #4597: Fixed several opcodes that weren't always propagating
   exceptions.
 
index 9d223d575a707f81a4952cf8962a0cacdf4d8fc5..352e739a30e3265ea553412a35599db185fcc854 100644 (file)
@@ -693,5 +693,6 @@ PyOS_AfterFork(void)
        main_thread = PyThread_get_thread_ident();
        main_pid = getpid();
        _PyImport_ReInitLock();
+       PyThread_ReInitTLS();
 #endif
 }
index e0f3252db6c44be3e2d24a324909d75fc5f28446..1356191436cfa1cd62c82fc4cbfc5e470fe2f78d 100644 (file)
@@ -2,6 +2,7 @@
 /* Check for interrupts */
 
 #include "Python.h"
+#include "pythread.h"
 
 #ifdef QUICKWIN
 
@@ -172,5 +173,6 @@ PyOS_AfterFork(void)
 {
 #ifdef WITH_THREAD
        PyEval_ReInitThreads();
+       PyThread_ReInitTLS();
 #endif
 }
index be4d092bccda88933001eeffa3cd4d0e1f3c3f7f..9cf509c84d726d6a075c868e67b9643d3cbe357c 100644 (file)
@@ -391,4 +391,35 @@ PyThread_delete_key_value(int key)
        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 */