[英]Not receiving SIGCHLD for processes executed with sudo
我目前正在編寫shell。 我執行進程並利用SIGCHLD
信號處理程序在它們完成時清理(等待它們)。
一切都在工作 - 除非我執行使用sudo
升級權限的進程。 在這些情況下,我從未收到SIGCHLD
信號 - 因此我永遠不知道該過程已完成執行。
當我收到諸如sudo ls
類的sudo ls
,我執行程序sudo
然后提供ls
作為參數。 我用execvp
執行此執行。
如果我在shell執行sudo ls
之后看一下ps -aux
,我會看到以下內容:
root 4795 0.0 0.0 4496 1160 pts/29 S+ 16:51 0:00 sudo ls
root 4796 0.0 0.0 0 0 pts/29 Z+ 16:51 0:00 [ls] <defunct>
所以, sudo
跑了並被分配了pid = 4795
,孩子(ls)被分配了4796
。 孩子已經完成了任務,現在正處於一個僵屍狀態。 sudo
似乎不想收獲僵屍進程而只是坐在那里。
我想知道導致這種行為的原因 - 我已經嘗試了不同的技術來清理這些僵屍進程,例如在sudo
下運行我的shell並直接在sudo
上等待sudo
執行的PID
(在上面的例子中為4796)。 這些技術都沒有奏效。
一如既往,任何建議都表示贊賞。
我的第一個想法是錯誤的信號處理,但是你的帖子中沒有足夠的信息來編寫測試代碼來復制你的失敗。 但我可以給你一些看的地方。 如果我為未來的讀者介紹一些你已經知道的信號基礎,請原諒我。
首先,我不知道您是使用傳統信號()還是新的POSIX sigaction()信號例程來捕獲信號。 sigset()在GNU之間是有用的。
傳統信號 - 信號()
即使不是不可能,也幾乎不可能保證在所有環境中使用原始信號處理器的氣密信號處理器。
while( ( pid = waitpid( -1, &signal, WNOHANG ) ) > 0 )
循環,直到找不到更多信號,因為傳統信號設置bool條件,指示至少一個信號未完成。 實際計數未知。 建議,抓住你的鼻子,逃離傳統信號。
傳統處理程序和多個SIGCHILD中缺少while()循環,一個來自你的sudo,一個或多個來自意外的孫子孫女被sudo解雇。 如果孫子信號首先進入時只處理一個SIGCHILD,則不會捕獲預期程序的信號。
POSIX信號 - sigaction()
POSIX信號可以清除傳統信號的所有故障。
如果在SIGCHILD處理程序中獲得SIGCHILD,缺少掩碼會導致丟失信號跟蹤等奇怪的事情。
GNU - sigset()
GNU提供了一個有用的中間版本,它具有與signal()相同的調用簽名,但刪除了大多數問題。 還提供一些額外的控制功能。 使用sigset()可以輕松解決許多信號問題。
提醒
將信號處理程序視為程序中的線程,即使您沒有在代碼中使用線程。
在舊的日子里,你需要在信號處理程序中進行絕對最少的處理......不要調用具有副作用的庫代碼,例如printf。 當我不得不使用傳統信號處理程序時,我仍然遵循這一點,並且總是在較新的處理程序中使用多線程注意事項。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.