プロセス グループ 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_sigaction
sa_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_pid
kill
getpgid()
PGID
getpgid(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 ) ですが、 (要求したとおり) に変更されます。^C
PGID
echo
PGID
15173
echo
15174
すべてが期待どおりに機能していると思います。
あなたが抱えている問題は、本質的にシグナルハンドラーにあると思います。最初に、あなたは記入されることを期待si_pid
しているようです。次に、あなたprintf
はpgid
and shell_pgid
(2を印刷していると言っていますがPGID
、実際にはPGID
kill を発行するプロセスの を印刷しています (または、ない場合、その結果はgetpgid(0)
呼び出しPGID
プロセスの)、次にプロセスの PID - つまり、間違った方法と aPID
と aの両方PGID
. また、ハンドラーの設定が間違っていると、とにかくジャンクの2番目のパラメーターが得られる可能性があると思われます。