プログラムの実行中にプログラムに信号を送信するとSIGUSR1
(信号ハンドラが事前設定されていると仮定)、sleep(100)
信号は正しくキャプチャされますが、キャプチャされsleep(100)
た直後に終了します。これは、シグナルを送信すると、一部の内部機能が強制終了される可能性があることを意味します。
たとえば、科学コンピューティングプログラムで進行状況をキャプチャして印刷したいとしますSIGUSR1
。しかし、has_error_occured = true
orのようなステートメントの実行should_break_this_roop = true
中にシグナルを送信するとどうなりますか?これは予期しない動作を引き起こす可能性があると思います。
SIGUSR1
(および)を安全に使用するにはSIGUSR2
?私たち全員が知っているように、シェルコマンドdd
はSIGUSR1
。なぜそんなに安全ですか?
サンプルプログラム(私が実行したkill -SIGUSR1 xxxxx
):
#include <iostream>
#include <csignal>
#include <unistd.h>
void my_handler(int signal) {
; //some instructions
}
void just_sleep() {
std::cout << "sleep() starts.\n";
sleep(100); //not wait for 100s if a signal caught
std::cout << "sleep() ends.\n"; //executed even if a signal caught
}
int main() {
signal(SIGUSR1, my_handler);
just_sleep();
}
ベストアンサー1
以下を使用して信号ハンドラを設定する必要があります。信号動作(2)変える信号(2)、ブロックシステムコールを中断しないように設定しますSA_RESTART
。sa_flags
struct sigaction sa;
sa.sa_handler = your_handler;
sa.sa_flags = SA_RESTART;
sigemptyset(&sa.sa_mask);
sigaction(SIGUSR1, &sa, 0);
あるいは、より良い方法は邪魔を直接処理することです。
nanosleep() などが -1 を返すことを確認し、進捗errno == EINTR
状況を印刷してから呼び出しを再実行します (sleep() は Linux の nanosleep() のラッパーにすぎません)。プログラムがより複雑になったら、とにかくこれを行う必要があります。シグナルハンドラを介して安全に実行できる作業はあまりありません。signal-safety(7) のマニュアルページLinuxで。