TLDR: Yes, should work as advertised.
From my understanding of libuv's source code unix/signal.c there is a generic signal handler
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. 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.
This was for the unix source code and the windows win/signal.c source has a similar mechanism.
So the answer should be yes, it should also work as advertised in a multithreaded setting, i.e. the registered handler will be executed by the loop thread.