Commit fe075e7b authored by Kevin Modzelewski's avatar Kevin Modzelewski

Clear some of our thread state after a fork()

parent aadf86a1
......@@ -358,6 +358,23 @@ void finishMainThread() {
// TODO maybe this is the place to wait for non-daemon threads?
}
extern "C" void PyEval_ReInitThreads() {
pthread_t current_thread = pthread_self();
assert(current_threads.count(pthread_self()));
auto it = current_threads.begin();
while (it != current_threads.end()) {
if (it->second->pthread_id == current_thread) {
++it;
} else {
it = current_threads.erase(it);
}
}
// TODO we should clean up all created PerThreadSets, such as the one used in the heap for thread-local-caches.
}
// For the "AllowThreads" regions, let's save the thread state at the beginning of the region.
// This means that the thread won't get interrupted by the signals we would otherwise need to
// send to get the GC roots.
......
......@@ -923,6 +923,16 @@ extern "C" void PyOS_AfterFork(void) {
// - change the definition of the main thread to the current thread
// - call threading._after_fork
// Also see PyEval_ReInitThreads
// Should we disable finalizers after a fork?
// In CPython, I think all garbage from other threads will never be freed and
// their destructors never run. I think for us, we will presumably collect it
// and run the finalizers. It's probably just safer to run no finalizers?
// Our handling right now is pretty minimal... you better just call exec().
PyEval_ReInitThreads();
_PyImport_ReInitLock();
}
extern "C" {
......
......@@ -201,6 +201,10 @@ extern "C" int _PyImport_ReleaseLock() {
return 1;
}
extern "C" void _PyImport_ReInitLock() {
// TODO: currently no import lock!
}
extern "C" PyObject* PyImport_ImportModuleNoBlock(const char* name) {
Py_FatalError("unimplemented");
}
......
# skip-if: True
from thread import start_new_thread
import time
import os
counter = 0
def daemon_thread():
global counter
while True:
for i in xrange(100):
counter += 1
time.sleep(0.0)
start_new_thread(daemon_thread, ())
while counter < 100:
time.sleep(0.01)
def forceCollection():
for i in xrange(100):
[None] * 128000
pid = os.fork()
if pid:
print "parent"
r = os.waitpid(pid, 0)
print r[1]
print os.WIFSIGNALED(r[1]), os.WTERMSIG(r[1])
assert os.WIFEXITED(r[1])
assert os.WEXITSTATUS(r[1]) == 0
print "parent waking up"
forceCollection()
else:
print "child"
forceCollection()
print "child exiting successfully"
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment