LoginSignup
3
5

More than 5 years have passed since last update.

pthread_killでセグる

Last updated at Posted at 2015-12-08
a.cpp

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 を使おうとした場合には、 例えば、 セグメンテーションフォールトになる可能性もある点に注意すること。

3
5
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5