mirror of
https://github.com/trapexit/mergerfs.git
synced 2026-10-26 02:48:59 -04:00
Fix destructor race with _remove_self during shutdown
The destructor and autoscale idle-exit path could race: a worker calling _remove_self would erase itself from _threads and detach while the destructor was iterating _threads to enqueue poison pills and join. This could cause too few poison pills (deadlocking remaining workers) or pthread_join on a detached thread (UB). Two changes: - _remove_self now checks _stop and returns immediately during shutdown, ensuring no thread detaches after destruction begins. - Destructor snapshots _threads under the mutex before enqueueing poison pills and joining, so it operates on a stable copy. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9ae145b7e9
commit
c0b4ea3fae
1 changed files with 16 additions and 3 deletions
|
|
@ -291,16 +291,25 @@ ThreadPool::~ThreadPool()
|
|||
pthread_join(_monitor_thread,NULL);
|
||||
}
|
||||
|
||||
// Snapshot threads under lock to close the race with _remove_self.
|
||||
// After _stop is set, _remove_self becomes a no-op, so no thread
|
||||
// will detach or erase itself from this point forward.
|
||||
std::vector<pthread_t> snapshot;
|
||||
{
|
||||
mutex_lockguard(_threads_mutex);
|
||||
snapshot = _threads;
|
||||
}
|
||||
|
||||
syslog(LOG_DEBUG,
|
||||
"threadpool (%s): destroying %zu threads",
|
||||
_name.c_str(),
|
||||
_threads.size());
|
||||
snapshot.size());
|
||||
|
||||
// Enqueue one poison pill per thread
|
||||
for(std::size_t i = 0; i < _threads.size(); ++i)
|
||||
for(std::size_t i = 0; i < snapshot.size(); ++i)
|
||||
_queue.enqueue_unbounded(Func{});
|
||||
|
||||
for(auto t : _threads)
|
||||
for(auto t : snapshot)
|
||||
pthread_join(t,NULL);
|
||||
}
|
||||
|
||||
|
|
@ -546,6 +555,10 @@ inline
|
|||
void
|
||||
ThreadPool::_remove_self(pthread_t t_)
|
||||
{
|
||||
// During shutdown the destructor owns all joins; don't detach.
|
||||
if(_stop.load(std::memory_order_acquire))
|
||||
return;
|
||||
|
||||
mutex_lockguard(_threads_mutex);
|
||||
|
||||
auto it = std::find(_threads.begin(),_threads.end(),t_);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue