pid_t gettid() {
return static_cast<pid_t>(syscall(SYS_gettid));
}
voud _pthread_kill(std::thread::native_handle_type ptid, int sig, pid_t pid, pid_t tid) {
// pidとtidを使って、
// /proc/pid/task/tid
// というパスをチェックしてから、pthread_killを実行する。
// pthread_killで存在しないptidを操作しようとすると、
// CentOS 6だと、もれなくセグる。
char path[1024];
sprintf(path, "/proc/%d/task/%d", pid, tid);
struct stat st;
int ret = stat(path, &st);
// statが成功したら、とりあえずOKとし、pthread_killを実行する。
// statが失敗する場合は、pthread_killをせずに戻る。
if (ret) {
return;
}
pthread_kill(ptid, sig);
}
環境はCentOS release 6.7 (Final)
コンパイラは、gcc 4.8.2
スレッドは、std::threadを使いつつ、
スレッドからスレッドにシグナルを送信する場合は、pthread_killを使う。
この環境だと、pthread_killに渡すpthread_tの内容が、すでに存在しない
スレッドだった場合、、もれなくセグる。
たとえば、pthread_kill(ptid, 0); で生存確認したい、という場合も、
スレッドが存在しないのであれば、問答無用でセグる。(生存確認できない)
なので、そのスレッドの生存確認をするのに、
上記コードのように、/proc/pid/task/tidを確認する方法にした。
この件について、man pageにも書いてある。
以下引用
シグナルの配送はプロセス全体で行われる。 シグナルハンドラーが設定されている場合、 そのハンドラーがスレッド thread で起動される>が、 シグナルの配送が "stop", "continue", "terminate" のいずれかの場合、 シグナルに対するアクションはプロセス全体に影響がある。
POSIX.1-2008 では、 スレッドが終了した後にそのスレッド ID が使用されたことを検出した場合に、 pthread_kill() はエラー ESRCH を返すことを推奨されている。 glibc の実装では、無効なスレッド ID を検出できる場合にはこのエラーを返す。 しかし、 POSIX では、 終了したスレッド ID を使おうとした場合の動作は不定であり、 pthread_kill() で無効なスレッド ID を使おうとした場合には、 例えば、 セグメンテーションフォールトになる可能性もある点に注意すること。