在主執行緒正在執行 libuv 事件回圈的多執行緒 C 程式中,是否保證該事件回圈執行緒正在執行使用注冊的信號處理程式uv_signal_start?
背景資料:
來自http://docs.libuv.org/en/v1.x/design.html
I/O(或事件)回圈 [...] 意味著系結到單個執行緒。
但是由于我們在一個多執行緒程式中,信號處理程式可以由其他執行緒執行
根據 POSIX.1,行程導向的信號(例如,使用 kill(2) 發送)應該由行程內的單個任意選擇的執行緒處理。
所以我的問題基本上是 libuv 信號處理是否像宣傳的那樣作業
信號句柄基于每個事件回圈實作 Unix 風格的信號處理。
即使在多執行緒程式中。
uj5u.com熱心網友回復:
TLDR:是的,應該像宣傳的那樣作業。
根據我對 libuv 源代碼unix/ signal.c 的理解,有一個通用信號處理程式
static void uv__signal_handler(int signum) {
uv__signal_msg_t msg;
uv_signal_t* handle;
int saved_errno;
saved_errno = errno;
memset(&msg, 0, sizeof msg);
if (uv__signal_lock()) {
errno = saved_errno;
return;
}
for (handle = uv__signal_first_handle(signum);
handle != NULL && handle->signum == signum;
handle = RB_NEXT(uv__signal_tree_s, &uv__signal_tree, handle)) {
int r;
msg.signum = signum;
msg.handle = handle;
/* write() should be atomic for small data chunks, so the entire message
* should be written at once. In theory the pipe could become full, in
* which case the user is out of luck.
*/
do {
r = write(handle->loop->signal_pipefd[1], &msg, sizeof msg);
} while (r == -1 && errno == EINTR);
assert(r == sizeof msg ||
(r == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)));
if (r != -1)
handle->caught_signals ;
}
uv__signal_unlock();
errno = saved_errno;
}
其中管道handle->loop->signal_pipefd[1]用于告訴句柄的關聯loop有關傳入信號的資訊。事實上,這個通用信號處理程式可以從任何執行緒呼叫,但是當 libuv 執行緒在下一次回圈迭代中讀取 時,它將呼叫uv_signal_start 在事件回圈執行緒(我的設定中的主執行緒)中注冊的用戶特定信號處理程式signal_pipefd[1]。
這是針對 unix 源代碼和 windows win/signal.c源代碼具有類似的機制。
所以答案應該是肯定的,它也應該像在多執行緒設定中宣傳的那樣作業,即注冊的處理程式將由回圈執行緒執行。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/355684.html
