C
將 SIGUSR1 發送到程序是否安全,為什麼?
當您
SIGUSR1
在程序執行時向程序發送信號(例如信號處理程序已預先設置)時sleep(100)
,信號被正確擷取,但sleep(100)
在捕穫後立即終止。這可能意味著發送信號可以強制終止內部某些功能。例如,在一個科學計算程序中,我想擷取
SIGUSR1
並列印進度。但是,如果我碰巧在語句像has_error_occured = true
或should_break_this_roop = true
正在執行時發送信號怎麼辦?我認為這可能會導致意外行為。我怎樣才能安全地使用
SIGUSR1
(和SIGUSR2
)?眾所周知,shell 命令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(); }
您應該使用sigaction(2)而不是signal(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() 的包裝)。如果您的程序變得更複雜,您無論如何都必須這樣做——信號處理程序無法安全地做很多事情——請參閱Linux 上的 signal-safety(7) 手冊頁。