简体   繁体   English

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

[英]libuv signal handling in multithreaded programs

In a multithreaded C++ program where the main thread is executing a libuv event loop, is it guaranteed that this event loop thread is executing signal handlers registered using uv_signal_start ?在主线程正在执行 libuv 事件循环的多线程 C++ 程序中,是否保证该事件循环线程正在执行使用uv_signal_start注册的信号处理程序?

Background information:背景资料:

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

The I/O (or event) loop is [...] meant to be tied to a single thread. I/O(或事件)循环 [...] 意味着绑定到单个线程。

But as we are in a multithreaded program, 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.根据 POSIX.1,进程导向的信号(例如,使用 kill(2) 发送)应该由进程内的单个任意选择的线程处理。

So my question is basically whether libuv signal handling works as advertised所以我的问题基本上是 libuv 信号处理是否像宣传的那样工作

Signal handles implement Unix style signal handling on a per-event loop bases.信号句柄基于每个事件循环实现 Unix 风格的信号处理。

even in multithreaded programs.即使在多线程程序中。

TLDR: Yes, should work as advertised. TLDR:是的,应该像宣传的那样工作。

From my understanding of libuv's source code unix/signal.c there is a generic signal handler根据我对 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;
}

in which a pipe handle->loop->signal_pipefd[1] is used to tell the handle's associated loop abount the incoming signal.其中管道handle->loop->signal_pipefd[1]用于告诉句柄的关联loop关于传入信号。 Indeed, this generic signal handler can be called from any thread, however the libuv thread will then call the user's specific signal handler registered with uv_signal_start in the event loop thread (main thread in my setting) when it reads the signal_pipefd[1] in the next loop iteration.实际上,这个通用信号处理程序可以从任何线程调用,但是当 libuv 线程读取信号中的uv_signal_start signal_pipefd[1]时,它会uv_signal_start在事件循环线程(我的设置中的主线程)中注册的用户特定信号处理程序下一次循环迭代。

This was for the unix source code and the windows win/signal.c source has a similar mechanism.这是针对 unix 源代码和 windows win/signal.c源代码具有类似的机制。

So the answer should be yes, it should also work as advertised in a multithreaded setting, ie the registered handler will be executed by the loop thread.所以答案应该是肯定的,它也应该像在多线程设置中宣传的那样工作,即注册的处理程序将由循环线程执行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM