c++ - gtest DEATH_TEST complains about fork() and threads, but only threads found had been joined -
i'm using gtest unit testing and, in particular, have death_tests assertions in debug builds. setup()
test, have create object creates thread, goes off , work, returns data, , joins on object's thread. test fixture's setup()
returns, allowing test body run.
i've noticed death_test complain death tests use fork(), unsafe particularly in threaded context. test, google test detected 2 threads.
is, of course, valid problem if there's multiple threads running. sometimes, however, no such warning exists. seems race condition.
so looking it, discovered gtest using /proc/self/task
pseudo filesystem discover threads. since of threads named, decided use /proc/self/task/[tid]/comm
discover thread might lingering. indeed, it's exact same thread join()
ed. came example source code reproduce issue 1) reproduces gtest's thread detection gtest, , 2) if target thread lingering, emits message stdout.
// g++ test.cpp --std=c++11 -pthread #include <iostream> #include <fstream> #include <string> #include <thread> #include <dirent.h> // dir*, dirent*, opendir(), closedir(); enumerate pseudo-fs /proc/self/task #include <string.h> // strcmp(); #include <sys/prctl.h> // prctl(), pr_set_name; sets name of current thread std::string get_thread_name(std::string tid_str) { std::fstream f(std::string("/proc/self/task/") + tid_str + std::string("/comm")); tid_str.clear(); std::getline(f, tid_str); return tid_str; } int main(int argc, char **argv) { // until sigterm (ctrl-c) while (true) { std::thread a([](){ prctl(pr_set_name,"target",0,0,0); }); a.join(); if (dir *dir = opendir("/proc/self/task")) { bool found = false; while (dirent *entry = readdir(dir)) { if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) { std::string name = get_thread_name(entry->d_name); if ( found = (name == "target") ) { std::cout << "thread " << entry->d_name << " -- " << name << std::endl; } } } closedir(dir); if ( not found ) { std::cout << "not found" << std::endl; } } else { std::cout << "cannot enumerate" << std::endl; } } return 0; }
using ubuntu 14.04 , gcc 4.8.2-19ubuntu1 , command commented on first line of example source, end output stdout indicating race condition seem exist. of output states "not found", while output interspersed tid of target-named thread. disable output of "not found" , observe emitted tid changes.
in working on this, discovered system's thread id ([tid]
in /proc/self/task/[tid]
) different pthread's pthread_t
expected in pthread_getname_np()
. discovered there prctl
pr_get_name
appears retrieve name of current (calling) thread. 1 of questions is: is there documented api retrieve thread's name if given system tid (eg, don't have read /proc/self/task/[tid]/comm
)? that's side question.
more importantly, is there way guarantee false positive far fork()
problems concerned?, , related question: is there better way ensure std::thread
has finished join()
?
i think w/o tracking system tid <-> pthread id mappings you're out of luck; pthread id opaque value decouple platform-specific process abstractions , don't believe there public apis extract it.
i think procfs &
std::thread::join
/pthread_join
race unavoidable, @ least in present linux implementations.pthread_join
waits kernel clear registered memory location & signal futex during thread exit. happens inmm_release
(linux/kernel/fork.c) invoked right in middle ofdo_exit
, before of task accounting structures updated. suspect traversing procfs afterpthread_join
completes can race rest of process teardown.
a dissatisfying answer in terms of problem you're trying solve, hope helps.
Comments
Post a Comment