地方エンジニアの学習日記

興味ある技術の雑なメモだったりを書いてくブログ。たまに日記とガジェット紹介。

【Linux】pidfd_send_signal(2)とは

今時はどうするんだろうと思ったりした。そもそもコンテナみたいにネームスペースが切られているみたいなケースだとpidが一周すること自体がそこまで起こらないとかだろうか?コンテナ内ではそうでもホストOSはむしろpidが一周しやすくなっているだろうしなんかしらあるだろうなと思って調べた。

pidfd_send_signal

manpages.ubuntu.com

ファイルディスクリプタで指定されたプロセスにシグナルを送る というシステムコールLinux 5.1あたりで入った模様。pidfd_open(2)で開いておいてシグナルを送りたい時にpidfd_send_signal(2)を実行することで一周してPIDが同じ意図しないプロセスが存在する場合でもシグナルが送られずにエラーを返すようになる。以下はサンプルコード。(実際の意味合い的には/procのファイルをopenするのと同じものになるはず)

#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>

// pidfd_open システムコールをラップする関数
int pidfd_open(pid_t pid, unsigned int flags) {
    return syscall(SYS_pidfd_open, pid, flags);
}

// pidfd_send_signal システムコールをラップする関数
int pidfd_send_signal(int pidfd, int sig, siginfo_t *info, unsigned int flags) {
    return syscall(SYS_pidfd_send_signal, pidfd, sig, info, flags);
}

int main() {
    pid_t pid;
    int status;

    // 子プロセスを生成
    pid = fork();
    if (pid == -1) {
        perror("fork");
        exit(EXIT_FAILURE);
    }

    if (pid == 0) {
        // 子プロセス: 無限ループで生き続ける
        printf("Child process PID: %d\n", getpid());
        while (1) {
            sleep(1);
        }
    } else {
        // 親プロセス: 少し待ってから子プロセスを終了させる
        sleep(2);

        // pidfd_open を使って子プロセスのファイルディスクリプタを取得
        int pidfd = pidfd_open(pid, 0);
        if (pidfd == -1) {
            perror("pidfd_open");
            exit(EXIT_FAILURE);
        }

        // pidfd_send_signal を使って子プロセスに SIGTERM を送信
        if (pidfd_send_signal(pidfd, SIGTERM, NULL, 0) == -1) {
            perror("pidfd_send_signal");
            close(pidfd);
            exit(EXIT_FAILURE);
        }

        // 子プロセスの終了を待機
        waitpid(pid, &status, 0);

        if (WIFEXITED(status)) {
            printf("Child process exited with status %d\n", WEXITSTATUS(status));
        } else if (WIFSIGNALED(status)) {
            printf("Child process killed by signal %d\n", WTERMSIG(status));
        }

        close(pidfd);
    }

    return 0;
}

実装

github.com

権限があるか、pidのfdかどうかや同一nsかどうかを見てシグナルを送っている。シンプル。スレッドやプロセスグループでのシグナル送信があったりとコンテナやスレッドベースのアプリケーションでのプロセス管理において役立つんだろうかという感想。