Commit bb053bf4 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Allow forking with other threads alive

I wasn't sure what we would have to do in this case --
we don't really have any way of cleaning up the data referenced
by those other threads.

Fortunately(?), CPython doesn't do much cleanup of those threads
(cleans up their metadata but doesn't try to clean up any references
held by the thread), so we don't have to do much either.  Just set
a flag saying that this happened and that we should skip asserting
that we got down to 0 refs.
parent 6eea2b47
......@@ -488,6 +488,7 @@ static pthread_mutex_t gil = PTHREAD_MUTEX_INITIALIZER;
std::atomic<int> threads_waiting_on_gil(0);
static pthread_cond_t gil_acquired = PTHREAD_COND_INITIALIZER;
bool forgot_refs_via_fork = false;
extern "C" void PyEval_ReInitThreads() noexcept {
pthread_t current_thread = pthread_self();
......@@ -502,6 +503,11 @@ extern "C" void PyEval_ReInitThreads() noexcept {
tstate_delete_common(it->second->public_thread_state);
delete it->second;
it = current_threads.erase(it);
// Like CPython, we make no effort to try to clean anything referenced via other
// threads. Set this variable to know that that we won't be able to do much leak
// checking after this happens.
forgot_refs_via_fork = true;
}
}
......
......@@ -172,6 +172,7 @@ extern "C" inline void allowGLReadPreemption() {
}
#endif
extern bool forgot_refs_via_fork;
} // namespace threading
} // namespace pyston
......
......@@ -4930,13 +4930,26 @@ extern "C" void Py_Finalize() noexcept {
if (VERBOSITY())
PRINT_TOTAL_REFS();
bool assert_refs = true;
if (num_garbage_objects) {
if (VERBOSITY())
fprintf(stderr, "[%d garbage objects]\n", num_garbage_objects);
} else if (other_threads) {
assert_refs = false;
}
if (other_threads) {
if (VERBOSITY())
fprintf(stderr, "[Other threads alive, can't free their refs]\n");
} else {
assert_refs = false;
}
if (threading::forgot_refs_via_fork) {
if (VERBOSITY())
fprintf(stderr, "[Leaked refs via multithreaded fork]\n");
assert_refs = false;
}
if (assert_refs) {
#ifdef Py_TRACE_REFS
if (_Py_RefTotal != 0)
_Py_PrintReferenceAddressesCapped(stderr, 10);
......@@ -4944,6 +4957,6 @@ extern "C" void Py_Finalize() noexcept {
RELEASE_ASSERT(_Py_RefTotal == 0, "%ld refs remaining!", _Py_RefTotal);
}
#endif
#endif // Py_REF_DEBUG
}
}
# expected: reffail
# no-collect-stats
from thread import start_new_thread
......
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