2

SIGINT 用に独自のシグナル ハンドラを定義しました。しかし、シグナル ハンドラーが呼び出されない シグナル ハンドラーはプログラムを終了させるだけです。しかし、ctrl+c を押してもプログラムは終了しません。助けてください...

これは、コードがどのように見えるかです..

sa.sa_handler = handle_termsig;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sigaction(SIGINT, &sa, 0);
sigaction(SIGTERM, &sa, 0);
sigemptyset(&g_termsigs);
sigaddset(&g_termsigs, SIGINT);
sigaddset(&g_termsigs, SIGTERM);

sigprocmask(SIG_BLOCK, &g_termsigs, 0);
if (select (fdmax+1, &rd, &wr, NULL, &time) < 0)
{
  exit();
}
sigprocmask(SIG_UNBLOCK, &g_termsigs, &savemask);
4

2 に答える 2

0

select を呼び出している間は SIGINT がブロックされるため、配信select()も中断もされません。ハンドラーが呼び出すだけでexit()、コード呼び出しが選択されている間でもこれが必要な場合、最良の解決策はシグナル マスクをそのままにしておくことです。何らかの理由で、 の呼び出し中に通常のハンドラーを呼び出したくない場合select()は、関数を使用できますpselect()

編集:

信号はいつ配信されますか

シグナルが有効 (つまり、ブロックされていない) で、プロセスが実行中の場合は、すぐに。

シグナルが有効で、プロセスが中断可能なスリープ (つまり、top/ps 出力で state==S を意味する) でスリープしている場合、syscall は中断され (たとえば、呼び出し元に EINTR を返すことによって)、シグナル ハンドラが実行されます。

シグナルがブロックされている場合は、ブロックが解除されるとすぐに配信されるのを待ちます。システムコールは、ブロックされたシグナルによって中断されません。

あなたの例では、これはselect()が入力を待っていることを意味します。入力が利用可能になると戻り、シグナルハンドラが有効になり (sigprocmask への 2 回目の呼び出しで)、ハンドラが呼び出されます。

これは strace でどのように見えるかです:

Process 22393 attached - interrupt to quit
19:31:05.844940 select(1, [0], NULL, NULL, NULL) = 1 (in [0])
19:31:12.131431 rt_sigprocmask(SIG_UNBLOCK, [INT TERM], [INT TERM], 8) = 0
19:31:12.131560 --- SIGINT (Interrupt) @ 0 (0) ---
19:31:12.131730 fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
19:31:12.131871 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7ffb000
19:31:12.132027 write(1, "signal..."..., 9) = 9
19:31:12.132148 exit_group(1)           = ?
Process 22393 detached

信号を有効にする方法

シグナル ハンドラーを常に有効にするにはsigprocmask()、コードから への呼び出しを削除するだけです。

于 2009-02-26T10:46:49.453 に答える