多线程程序中的 libuv 信号处理

libuv signal handling in multithreaded programs

在主线程正在执行 libuv 事件循环的多线程 C++ 程序中,是否保证此事件循环线程正在执行使用 uv_signal_start 注册的信号处理程序?

背景资料:

来自http://docs.libuv.org/en/v1.x/design.html

The I/O (or event) loop is [...] meant to be tied to a single thread.

但是由于我们在多线程程序中,signal handlers can be executed by other threads

According to POSIX.1, a process-directed signal (sent using kill(2), for example) should be handled by a single, arbitrarily selected thread within the process.

所以我的问题基本上是 libuv 信号处理是否有效 as advertised

Signal handles implement Unix style signal handling on a per-event loop bases.

即使在多线程程序中。

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 源代码具有类似的机制。

所以答案应该是肯定的,它也应该像在多线程设置中宣传的那样工作,即注册的处理程序将由循环线程执行。