我得到了這個問題:
我用 c 撰寫了一個程式,其中主行程創建了一些子行程,這些子行程過了一會兒,能夠向主行程發送信號:
使用以下代碼發送信號:
kill(getppid(), SIGUSR1);
而主行程,在while回圈中正在等待SIGUSR1訊息......
一切都很好,但是如果我增加子數量并自動同時有更多信號的可能性,程式會崩潰列印訊息:
用戶定義信號 1
主要代碼是這樣的:
void signalHandler(int sig, siginfo_t* info, void* vp) {
if (sig == SIGUSR1) {
printf("SIGUSR1 has arrived\n");
} else if (sig == SIGUSR2) {
printf("SIGUSR2 has arrived\n");
}
}
int main(int argc, char const *argv[]) {
struct sigaction action, old_action;
memset(&action, 0, sizeof(struct sigaction));
action.sa_sigaction = signalHandler;
sigemptyset(&action.sa_mask);
action.sa_flags = SA_RESTART | SA_NODEFER;
while (1) {
sigaction(SIGUSR1, &action, &old_action);
sigaction(SIGUSR2, &action, &old_action);
}
}
我認為問題是當主機仍在處理前一個信號時發送信號......但是我該怎么做才能解決這個問題
非常感謝你
uj5u.com熱心網友回復:
這意味著子行程在父行程能夠呼叫sigaction()以配置信號處理程式之前發送信號。發生這種情況時,對 SIGUSR1 的默認信號反應將終止程式:
SIGUSR1 P1990 Term User-defined signal 1
https://man7.org/linux/man-pages/man7/signal.7.html
但是,您的代碼存在很多問題。printf()在信號處理程式中呼叫是不安全的(它是 POSIX 定義的 AS-Unsafe):
https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/functions/V2_chap02.html#tag_15_04_03
此外,使用SA_NODEFER可能會創建嵌套信號(在某些信號處理程式運行時呼叫另一個信號處理程式),但您的程式不能防止洪水泛濫。如果有足夠多的孩子,這將產生堆疊溢位。最后,主程式繼續運行一個不間斷的無限回圈來重新配置信號,而它應該只在回圈外配置一次并在回圈內阻塞(例如sigwait()or pselect()):
https://man7.org/linux/man-pages/man2/select.2.html
最后,如果您希望運行大量子級,而這些子級可能會用信號淹沒父級,那么最好使用實時信號生成函式 ( sigqueue()) 而不是kill()。不同之處在于,使用sigqueue(),所有信號都排入佇列,并且SA_NODEFER不必避免在其他信號處理程式運行時丟棄信號:
https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/functions/V2_chap02.html#tag_15_04_02
最終結論:代碼應該完全重寫。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/403463.html
標籤:
