簡體   English   中英

不接收使用sudo執行的進程的SIGCHLD

[英]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之間是有用的。

傳統信號 - 信號()
即使不是不可能,也幾乎不可能保證在所有環境中使用原始信號處理器的氣密信號處理器。

  • 在某些UNIX系統上,進入信號處理程序可以將處理程序重置為默認條件。 除非處理程序明確重置信號,否則保證后續信號丟失。
  • signal()處理程序
    • 處理程序必須執行一段while( ( pid = waitpid( -1, &signal, WNOHANG ) ) > 0 )循環,直到找不到更多信號,因為傳統信號設置bool條件,指示至少一個信號未完成。 實際計數未知。
    • 如果先前的while()循環處理了信號,則處理程序必須允許沒有找到信號。
  • 允許來自未知進程的信號...如果您啟動的程序也啟動了孫子進程,如果您的孩子快速退出,您可以繼承該進程。

建議,抓住你的鼻子,逃離傳統信號。

傳統處理程序和多個SIGCHILD中缺少while()循環,一個來自你的sudo,一個或多個來自意外的孫子孫女被sudo解雇。 如果孫子信號首先進入時只處理一個SIGCHILD,則不會捕獲預期程序的信號。

POSIX信號 - sigaction()
POSIX信號可以清除傳統信號的所有故障。

  • 設置一個處理程序,沒有恢復(恢復不是POSIX信號的一部分,並且通常,至少在我看來,當你可能以相同的方式處理多個信號時,它是邪惡的)。
  • sigaction()信號是粘性的...它們一直存在直到明顯改變(太棒了!)。 沒有必要在處理程序中再次重置信號處理程序的麻煩。
  • 設置掩碼以在處理信號時屏蔽當前信號。 Paranoids也會屏蔽傳遞給同一個處理程序的任何其他信號。

如果在SIGCHILD處理程序中獲得SIGCHILD,缺少掩碼會導致丟失信號跟蹤等奇怪的事情。

GNU - sigset()
GNU提供了一個有用的中間版本,它具有與signal()相同的調用簽名,但刪除了大多數問題。 還提供一些額外的控制功能。 使用sigset()可以輕松解決許多信號問題。

提醒
將信號處理程序視為程序中的線程,即使您沒有在代碼中使用線程。

在舊的日子里,你需要在信號處理程序中進行絕對最少的處理......不要調用具有副作用的庫代碼,例如printf。 當我不得不使用傳統信號處理程序時,我仍然遵循這一點,並且總是在較新的處理程序中使用多線程注意事項。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM