簡體   English   中英

多線程程序中的 libuv 信號處理

[英]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.

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