summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin v. Löwis <martin@v.loewis.de>2008-12-13 14:59:04 +0000
committerMartin v. Löwis <martin@v.loewis.de>2008-12-13 14:59:04 +0000
commit8a64048a22b42426cc45dfb2d713e295e97c768c (patch)
tree67b558f89948b345a433ae1045f8c0bfa22be24d
parente9859df7980e87f1dbad63fa22250a2e212327a4 (diff)
downloadcpython-git-8a64048a22b42426cc45dfb2d713e295e97c768c.tar.gz
Backport of r64212
Issue #1683: prevent forking from interfering in threading storage.
-rw-r--r--Include/pythread.h3
-rw-r--r--Misc/NEWS2
-rw-r--r--Modules/signalmodule.c1
-rw-r--r--Parser/intrcheck.c2
-rw-r--r--Python/thread.c31
5 files changed, 39 insertions, 0 deletions
diff --git a/Include/pythread.h b/Include/pythread.h
index f26db160bf..b5a6ec38a6 100644
--- a/Include/pythread.h
+++ b/Include/pythread.h
@@ -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
diff --git a/Misc/NEWS b/Misc/NEWS
index 99936660cf..b83c73169c 100644
--- 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.
diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c
index 9d223d575a..352e739a30 100644
--- a/Modules/signalmodule.c
+++ b/Modules/signalmodule.c
@@ -693,5 +693,6 @@ PyOS_AfterFork(void)
main_thread = PyThread_get_thread_ident();
main_pid = getpid();
_PyImport_ReInitLock();
+ PyThread_ReInitTLS();
#endif
}
diff --git a/Parser/intrcheck.c b/Parser/intrcheck.c
index e0f3252db6..1356191436 100644
--- a/Parser/intrcheck.c
+++ b/Parser/intrcheck.c
@@ -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
}
diff --git a/Python/thread.c b/Python/thread.c
index be4d092bcc..9cf509c84d 100644
--- a/Python/thread.c
+++ b/Python/thread.c
@@ -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 */