![](/img/trans.png)
[英]Poco: Is it possible to do signal handling the same way it's done with libuv and Boost::Asio?
[英]libuv signal handling in multithreaded programs
在主線程正在執行 libuv 事件循環的多線程 C++ 程序中,是否保證該事件循環線程正在執行使用uv_signal_start
注冊的信號處理程序?
背景資料:
來自http://docs.libuv.org/en/v1.x/design.html
I/O(或事件)循環 [...] 意味着綁定到單個線程。
但是由於我們在一個多線程程序中,信號處理程序可以由其他線程執行
根據 POSIX.1,進程導向的信號(例如,使用 kill(2) 發送)應該由進程內的單個任意選擇的線程處理。
所以我的問題基本上是 libuv 信號處理是否像宣傳的那樣工作
信號句柄基於每個事件循環實現 Unix 風格的信號處理。
即使在多線程程序中。
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]
時,它會uv_signal_start
在事件循環線程(我的設置中的主線程)中注冊的用戶特定信號處理程序下一次循環迭代。
這是針對 unix 源代碼和 windows win/signal.c源代碼具有類似的機制。
所以答案應該是肯定的,它也應該像在多線程設置中宣傳的那樣工作,即注冊的處理程序將由循環線程執行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.