1. 程式人生 > >SIGCHLD waitpid, 在ndk開發簡直就在踩屎坑

SIGCHLD waitpid, 在ndk開發簡直就在踩屎坑

調試 結束 虛擬機 -1 ssm 般的 proc -i nag

原本項目中依賴子進程執行的地方,都使用jni調用java層的ProcessManager,換了c++ACE框架後,發現這些任務都很慢,調試才發現所有子進程執行的任務都必須等待到reactor超時才返回控制權。一時慌了居然懷疑是不是app進程沒有收到SIGCHLD信號,所以調試跟蹤了一下內核,信號正常。

技術分享

既然收到了信號,那麽去了哪裏呢?

這裏要說明一下ACE框架, ACE_Process_Manager會在handle_signal處理SIGCHLD信號,然後向reactor發一個notify,從而進入它的handle_input,在這裏ACE_Process_Manager再通過waitpid查詢出子進程號,從handler表中找出對應的handler,最後執行handler->handle_exit()。

SIGCHLD也就是子進程結束向父進程發的信號,並且在你進程某個隊列掛入一個事件,這個事件可以通過waitpid系統調用查詢WHOHANG,但這個事件在被waitpid就不存在了。一般的組合使用方式,在signal處理函數中調用waitpid取事件。而ACE框架的ACE_Process_Manager也是這樣搭配使用,只不過waitpid延後到一個notify事件中進行。

技術分享

好了回到本例,在這過程中,waitpid一直都返回0,表示沒有這個事件,ACE框架必須依賴這個事件。這就奇怪了,有SIGCHLD信號卻waitpid沒有事件,(可參看一下https://stackoverflow.com/questions/43949142/will-wait-and-waitpid-block-sigchld-and-unblock-it-when-they-return-in-linux)。開始以為是android linux有問題,一直苦悶調試。最後當斷點了waitpid後,一下子就明朗了,原來jni使用了java層的ProcessManager包,java虛擬機開了一個線程在wait4進而waitpid。

技術分享

技術分享

當子進程結束時,掛載到父進程也就是app進程的事件,先被art虛擬機用waitpid取出了。然後才到SIGCHLD信號處理,當ACE框架走到waitpid一步時,事件已經被art虛擬機偷走了,所以被耍了一轉。

SIGCHLD waitpid, 在ndk開發簡直就在踩屎坑