C

將 SIGUSR1 發送到程序是否安全,為什麼?

  • November 12, 2018

當您SIGUSR1在程序執行時向程序發送信號(例如信號處理程序已預先設置)時sleep(100),信號被正確擷取,但sleep(100)在捕穫後立即終止。這可能意味著發送信號可以強制終止內部某些功能。

例如,在一個科學計算程序中,我想擷取SIGUSR1並列印進度。但是,如果我碰巧在語句像has_error_occured = trueshould_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_RESTARTsa_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) 手冊頁。

引用自:https://unix.stackexchange.com/questions/481271