调用pthread_timedjoin_np后std::thread的join()抛出"No such process"异常
问题:使用pthread_timedjoin_np配合std::thread的native_handle后调用join()抛出异常
尝试通过调用std::thread的native_handle()执行pthread_timedjoin_np,模拟已废弃的boost::thread::timed_join功能。但遇到异常:尽管joinable()返回true,调用join()时仍抛出异常。仅当子线程运行时调用pthread_timedjoin_np超时的情况一切正常。
代码示例:
#include <thread> #include <chrono> #include <iostream> int main() { auto t = std::thread([]{ std::this_thread::sleep_for(std::chrono::milliseconds{100}); std::cout << "hello from thread\n"; }); struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); ts.tv_sec += 1; if (int s = pthread_timedjoin_np(t.native_handle(), nullptr, &ts); s != 0) { std::cout << "timed out: " << s << std::endl; } if(t.joinable()) { std::cout << "thread is joinable\n"; t.join(); } return 0; }
原因分析
核心问题在于**std::thread的内部状态与pthread原生API的操作不同步**:
- 当
pthread_timedjoin_np成功join线程(子线程结束,未超时)时,pthread层面已经完成了线程资源的回收,但std::thread对象的内部状态并未更新,依然标记线程为可join状态(joinable()返回true)。此时调用std::thread::join(),会尝试join一个已被pthread回收的线程,属于未定义行为,因此抛出异常。 - 若
pthread_timedjoin_np超时,说明线程仍在运行,pthread层面未改变线程状态,std::thread的内部状态也未被破坏,后续调用join()自然正常。
关于native_handle的使用规则
标准C++允许获取std::thread的native_handle(),但禁止通过原生API执行会改变std::thread对象状态的操作(比如pthread_join、pthread_detach这类修改线程可join性的操作)。因为std::thread无法感知这些外部操作,会导致对象内部状态与实际线程状态不一致,进而引发未定义行为。
解决方案
方案1:手动同步状态(不推荐)
如果坚持使用pthread_timedjoin_np,在成功join线程后,需手动将std::thread对象置为不可join状态,比如调用t.detach()(需确保线程已结束),避免后续错误调用join():
if (int s = pthread_timedjoin_np(t.native_handle(), nullptr, &ts); s != 0) { std::cout << "timed out: " << s << std::endl; } else { // 线程已被原生API回收,手动置为不可join状态 t.detach(); }
方案2:使用C++标准库实现超时等待(推荐)
用std::future和std::packaged_task实现标准的超时等待,完全符合C++规范,不存在状态不一致问题:
#include <thread> #include <chrono> #include <iostream> #include <future> int main() { auto task = []{ std::this_thread::sleep_for(std::chrono::milliseconds{100}); std::cout << "hello from thread\n"; }; std::packaged_task<void()> pt(task); std::future<void> fut = pt.get_future(); std::thread t(std::move(pt)); // 超时等待1秒 auto status = fut.wait_for(std::chrono::seconds(1)); if (status == std::future_status::timeout) { std::cout << "timed out\n"; t.join(); // 线程仍在运行,join安全 } else { std::cout << "thread completed\n"; t.join(); // 线程已结束,状态同步,join安全 } return 0; }
内容的提问来源于stack exchange,提问作者Balint Bertalan
相关产品推荐
相关产品推荐

