diff --git a/src/core/python/thread.cpp b/src/core/python/thread.cpp index 3b3def2b4..795fc27c3 100644 --- a/src/core/python/thread.cpp +++ b/src/core/python/thread.cpp @@ -96,9 +96,9 @@ MI_PY_EXPORT(Thread) { .def_method(Thread, start) .def_method(Thread, is_running) .def_method(Thread, detach) - .def_method(Thread, join) - .def_static_method(Thread, sleep) - .def_static_method(Thread, wait_for_tasks); + .def_method(Thread, join, py::call_guard()) + .def_static_method(Thread, sleep, py::call_guard()) + .def_static_method(Thread, wait_for_tasks, py::call_guard()); py::class_(m, "ThreadEnvironment", D(ThreadEnvironment)) .def(py::init<>()); diff --git a/src/core/thread.cpp b/src/core/thread.cpp index c2e4cdafc..3708fd2dd 100644 --- a/src/core/thread.cpp +++ b/src/core/thread.cpp @@ -91,17 +91,20 @@ std::atomic WorkerThread::m_counter{0}; struct ThreadNotifier { ThreadNotifier() { // Do not register the main thread - if (m_counter > 0) - Thread::register_external_thread("wrk"); + if (m_counter > 0 && !self) + registered_external = Thread::register_external_thread("wrk"); + else + registered_external = false; m_counter++; } ~ThreadNotifier() { - if (self) + if (registered_external) Thread::unregister_external_thread(); m_counter--; } void ensure_initialized() {} static std::atomic m_counter; + bool registered_external; }; std::atomic ThreadNotifier::m_counter{0}; @@ -115,7 +118,7 @@ struct Thread::ThreadPrivate { bool external_thread = false; bool critical = false; int core_affinity = -1; - Thread::EPriority priority; + Thread::EPriority priority = Thread::ENormalPriority; ref logger; ref parent; ref fresolver; @@ -392,14 +395,27 @@ void Thread::start() { void Thread::dispatch() { d->native_handle = d->thread.native_handle(); - uint32_t id = thread_ctr++; - #if defined(__linux__) || defined(__APPLE__) - pthread_setspecific(this_thread_id, reinterpret_cast(id)); - #elif defined(_WIN32) - this_thread_id = id; - #endif - + struct WorkerSelf { + ref self_ = self; + ~WorkerSelf() { + // Avoid replaced Thread identity crashing with warning on destruction + if (self_) + self_->d->running = false; + } + } worker_identity; self = this; + if (worker_identity.self_) { + worker_identity.self_->dec_ref(); + notifier.registered_external = false; + } + else { + uint32_t id = thread_ctr++; + #if defined(__linux__) || defined(__APPLE__) + pthread_setspecific(this_thread_id, reinterpret_cast(id)); + #elif defined(_WIN32) + this_thread_id = id; + #endif + } if (d->priority != ENormalPriority) set_priority(d->priority); @@ -487,6 +503,7 @@ bool Thread::register_external_thread(const std::string &prefix) { set_thread_name_(thread_name.c_str()); #endif + self->inc_ref(); return true; } @@ -494,6 +511,9 @@ bool Thread::unregister_external_thread() { if (!self || !self->d->external_thread) return false; self->d->running = false; + Thread* worker = self; + self = nullptr; + worker->dec_ref(); return true; }