前言

停 thread 有幾種常見的方式,其中一種就是 pthread_cancel,而之前工作上就是使用 pthread_cancel 來停 thread, 但偶爾會發現 daemon core dump 在奇怪地方,深入研究之後發現 pthread_cancel 有坑,本篇簡單記錄下此坑,希望可以幫到之後的人。

pthread_cancel 實作

POSIX 並沒有定義 pthread_cancel 該如何實作,可以用 signal 也可以用其他方式,比方說 exception。 而此次遇到的情況就是 pthread_cancel 是透過 exception 實作的。

c++ 解構子

在 c++ 11 之後,所有解構子預設都是 noexcept(true)

pthread_cancel 加上 c++ 解構子

既然 pthread_cancel 是透過 exception 實作的,那如果碰上程式正在執行 noexcept(true) 部份 (比方說解構子)會發生什麼事情呢?

答案是會觸發 std::terminate(),從 cppreference 中指出 std::terminate() 將會被呼叫如果

a noexcept specification is violated

最終造成 core dump。

例子

#include <unistd.h>
#include <pthread.h>

#include <iostream>

class TestClass {
public:
	~TestClass() {
		sleep(3);
	}
};

void *ThreadFunc(void *)
{
	{
		TestClass c;
	}
	pthread_exit(nullptr);
}

int main()
{
	pthread_t t;
	pthread_create(&t, nullptr, ThreadFunc, nullptr);
	sleep(1);
	pthread_cancel(t);
	pthread_join(t, nullptr);
	return 0;
}

並且使用以下 command 編譯

g++ --std=c++17 -pthread -o pthread_test pthread_test.cp

之後執行 pthread_test 就會發生以上的 core dump。

Reference

  1. stackoverflow
  2. gcc mailing list