プロセス グループ ID の仕組みについて少し混乱していると思います。
まず、ソースを整理しました。
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
pid_t pid;
void
handler (int signum, siginfo_t * siginfo, void *context)
{
printf ("in signal handler pid is %d, getpgid(pid) is %d \n",
pid, getpgid (pid));
printf
("in signal handler siginfo->si_pid is %d, getpgid(siginfo->si_pid) is %d \n",
siginfo->si_pid, getpgid (siginfo->si_pid));
exit (0);
}
int
main (int argc, char **argv)
{
struct sigaction sa;
memset (&sa, 0, sizeof (sa));
sa.sa_sigaction = handler;
sigemptyset (&sa.sa_mask);
sa.sa_flags = SA_RESTART | SA_SIGINFO;
sigaction (SIGINT, &sa, NULL);
pid = getpid ();
printf ("before call pgid is %d pid=%d\n", getpgid (pid), pid);
setpgid (pid, pid);
printf ("after setpgid call pgid is %d pid=%d\n", getpgid (pid), pid);
tcsetpgrp (STDIN_FILENO, pid);
printf ("after tcsetprgrp call pgid is %d pid=%d\n", getpgid (pid), pid);
while (1)
{
}
}
主な変更点は、ハンドラーが 3 つのパラメーターを受け取る場合、 notSA_SIGINFOでハンドラーを使用および指定する必要があることです。そうしないと、ハンドラーが無効な 2 番目と 3 番目の引数を取得する可能性があります。sa_sigactionsa_handler
次に、ハンドラーを修正してsi_pid、pid.
また、追加のデバッグも行いました。
シェルから直接実行すると、次のようになります。
$ ./x
before call pgid is 15136 pid=15136
after setpgid call pgid is 15136 pid=15136
after tcsetprgrp call pgid is 15136 pid=15136
^Cin signal handler pid is 15136, getpgid(pid) is 15136
in signal handler siginfo->si_pid is 0, getpgid(siginfo->si_pid) is 15136
は を介して送信された信号によってのみ埋められるsiginfo->si_pidため、 は 0 としてレポートされることに注意してください。これは 0 が渡されることを意味し、これは当然のことながら、前の行で返されたものと同じです。si_pidkillgetpgid()PGIDgetpgid(pid)
kill -SIGINTを押すのではなく、別のプロセスからで強制終了するとどうなりますか^C。
$ ./x
before call pgid is 15165 pid=15165
after setpgid call pgid is 15165 pid=15165
after tcsetprgrp call pgid is 15165 pid=15165
in signal handler pid is 15165, getpgid(pid) is 15165
in signal handler siginfo->si_pid is 14858, getpgid(siginfo->si_pid) is 14858
ご覧のとおり、最後の行は、kill.
上記の両方の例で、プロセスが開始さPGIDれた時点で、 はすでに に等しくなっています。PID何故ですか?さて、コマンド ラインから 1 つのコマンドを起動したため、1 つのプロセス グループ (のみ) が存在するため、PGIDは常に になりますPID。
では、最初のプロセスではないプロセス グループを起動するとどうなるでしょうか。これを試して:
$ echo | ./x
before call pgid is 15173 pid=15174
after setpgid call pgid is 15174 pid=15174
after tcsetprgrp call pgid is 15174 pid=15174
in signal handler pid is 15174, getpgid(pid) is 15174
in signal handler siginfo->si_pid is 14858, getpgid(siginfo->si_pid) is 14858
a は (が変更された後) のみであるプロセスグループに移動するkill -SIGINTため、これで強制終了する必要があったことに注意してください。したがって、オン エントリは(の PID ) ですが、 (要求したとおり) に変更されます。^CPGIDechoPGID15173echo15174
すべてが期待どおりに機能していると思います。
あなたが抱えている問題は、本質的にシグナルハンドラーにあると思います。最初に、あなたは記入されることを期待si_pidしているようです。次に、あなたprintfはpgidand shell_pgid(2を印刷していると言っていますがPGID、実際にはPGIDkill を発行するプロセスの を印刷しています (または、ない場合、その結果はgetpgid(0)呼び出しPGIDプロセスの)、次にプロセスの PID - つまり、間違った方法と aPIDと aの両方PGID. また、ハンドラーの設定が間違っていると、とにかくジャンクの2番目のパラメーターが得られる可能性があると思われます。