Document detached-thread lifetime safety in autoscale self-exit

After _try_remove_self_if_above detaches and erases the thread, the
destructor's snapshot will not include it — so pthread_join is never
called on it, and the ThreadPool object can be destroyed while this
thread is still returning.

This is safe because the thread only accesses local variables after
detach (name is a std::string copy made at function entry), but the
reasoning is subtle. Add an explicit safety comment explaining why
there is no use-after-free.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Antonio S. Musumeci
2026-04-09 23:42:02 -04:00
co-authored by Claude Opus 4.6
parent 96824eab31
commit db784e00a2
+9 -1
View File
@@ -416,8 +416,16 @@ ThreadPool::start_routine_autoscale(void *arg_)
// Copy state needed for the log message BEFORE detaching,
// because _try_remove_self_if_above detaches the thread and
// the destructor won't wait for us - btp may be destroyed
// the destructor won't wait for us — btp may be destroyed
// by the time we reach the syslog call.
//
// Safety: after _try_remove_self_if_above returns true the
// thread is detached and removed from _threads. The
// destructor's snapshot won't include it, so pthread_join
// is never called. From this point we touch only locals
// (name is a std::string copy made at function entry), so
// there is no use-after-free even if ~ThreadPool runs
// concurrently on another thread.
if(btp->_try_remove_self_if_above(pthread_self(),
btp->_scaling_config.min_threads))
{