Skip to content

Conversation

dmantipov
Copy link

@dmantipov dmantipov commented Sep 20, 2022

Linux-specific signal handling backend based on signalfd(2) system call, and public function event_base_get_signal_method() to obtain an underlying kernel signal handling mechanism.

@dmantipov dmantipov force-pushed the signal-use-signalfd-if-available branch 3 times, most recently from 3834d93 to 45f0232 Compare September 20, 2022 13:02
@dmantipov
Copy link
Author

Could I run CI jobs myself?

@dmantipov dmantipov force-pushed the signal-use-signalfd-if-available branch from 45f0232 to d7f8284 Compare September 20, 2022 14:07
@azat
Copy link
Member

azat commented Sep 20, 2022

Could I run CI jobs myself?

Sadly, but first-time contributors requires an approve for CI.

@dmantipov dmantipov force-pushed the signal-use-signalfd-if-available branch from d7f8284 to b38c6b2 Compare September 20, 2022 14:52
@azat azat marked this pull request as draft September 21, 2022 06:41
@azat
Copy link
Member

azat commented Sep 21, 2022

Work-in-progress Linux-specific signal handling backend based on signalfd(2) system call.

I will mark it as draft, please press Ready for review once you will finish.

Copy link
Member

@azat azat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general this is a good thing, thank you!
Will take a look once you will finish it.

@azat
Copy link
Member

azat commented Sep 21, 2022

Sadly, but first-time contributors requires an approve for CI.

I will merge you #1339, and then CI will started automatically for you.

@dmantipov dmantipov force-pushed the signal-use-signalfd-if-available branch from b38c6b2 to 7b5cca7 Compare September 21, 2022 10:54
@dmantipov dmantipov marked this pull request as ready for review September 21, 2022 10:55
@dmantipov dmantipov force-pushed the signal-use-signalfd-if-available branch from 7b5cca7 to 2db8115 Compare September 30, 2022 07:52
@dmantipov dmantipov force-pushed the signal-use-signalfd-if-available branch from 2db8115 to 7913a0c Compare October 13, 2022 07:52
@dmantipov
Copy link
Author

Any chance to consider this for upstream?

@azat azat self-assigned this Oct 23, 2022
@azat
Copy link
Member

azat commented Oct 23, 2022

Any chance to consider this for upstream?

Yes, this is a great patch! Just let me take a closer look.

Copy link
Member

@azat azat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, please look at the comments.

Also what bothers me most is that it is not possible to use old signal API, and with signalfd yo cannot catch SIGSEGV/SIGFPU (though it is not an issue for almost 99% code, but I'm worrying that there can be the code that relies on this).

So that said, I think we need a way to get back to old signal-based API (and I'm fine to use signalfd by default, since it is cleaner code), and let's also add a test run with this old signal-based API.

@@ -1260,6 +1260,9 @@ test_signal_pipeloss(void)
* make two bases to catch signals, use both of them. this only works
* for event mechanisms that use our signal pipe trick. kqueue handles
* signals internally, and all interested kqueues get all the signals.
* This is not expected to work with signalfd - having more than one
* descriptor in attempt to accept the same signal (or intersecting sets
* of signals) is not the thing signalfd() was designed for.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is not signalfd, but SIG_UNBLOCK

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why SIG_UNBLOCK? The limitation is clearly stated in signalfd() manual page as:

If a signal appears in the mask of more than one of the file descriptors, then occurrences of that signal can be read (once) from any one of the file descriptors.

IOW if you poll() more than one descriptor in attempt to accept the same signal, all of them will be marked active (with POLLIN in revents after poll() return) on signal arrival, but you can read struct signalfd_siginfo from the only one of them, and attempt to read another active descriptor(s) always returns -1.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I'm talking about the test, look:

$ strace -e/signal,/proc regress --no-fork signal/signal_switchbase
signal/signal_switchbase: rt_sigprocmask(SIG_BLOCK, [USR1], NULL, 8) = 0
signalfd4(-1, [USR1], 8, SFD_CLOEXEC|SFD_NONBLOCK) = 11
rt_sigprocmask(SIG_BLOCK, [USR1], NULL, 8) = 0
signalfd4(-1, [USR1], 8, SFD_CLOEXEC|SFD_NONBLOCK) = 12
rt_sigprocmask(SIG_UNBLOCK, [USR1], NULL, 8) = 0
--- SIGUSR1 {si_signo=SIGUSR1, si_code=SI_USER, si_pid=32667, si_uid=1000} ---
+++ killed by SIGUSR1 +++
User defined signal 1

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So because there is no way to tell that this signal had been used in another base, this does not work.
But this is OK.

@dmantipov dmantipov force-pushed the signal-use-signalfd-if-available branch from 7913a0c to bdb2df2 Compare October 25, 2022 12:40
@dmantipov dmantipov force-pushed the signal-use-signalfd-if-available branch from bdb2df2 to 5057027 Compare November 7, 2022 08:35
@azat azat mentioned this pull request Nov 12, 2022
21 tasks
Linux-specific signal handling backend based on signalfd(2)
system call, and public function event_base_get_signal_method()
to obtain an underlying kernel signal handling mechanism.

Signed-off-by: Dmitry Antipov <dantipov@cloudlinux.com>
@azat azat force-pushed the signal-use-signalfd-if-available branch from 5057027 to 1af745d Compare November 12, 2022 20:15
@azat azat merged commit 1af745d into libevent:master Nov 12, 2022
@azat
Copy link
Member

azat commented Nov 12, 2022

Applied, thank you!
Can you also add a test with non signalfd approach?

For this the following places should be modified:

azat added a commit to azat/libevent that referenced this pull request Jul 10, 2023
signalfd may behave differently to sigaction/signal, so to avoid
breaking libevent users (like [1], [2]) disable it by default.

  [1]: tmux/tmux#3621
  [1]: tmux/tmux#3626

Also signalfd is not that perfect:
- you need to SIG_BLOCK the signal before
  - blocked signals are not reset on exec
  - blocked signals are allowed to coalesce - so in case of multiple
    signals sent you may get the signal only once (ok for most of the
    signals, but may be a problem for SIGCHLD, though you may call
    waitpid() in a loop or use pidfd)
- and also one implementation problem -
  sigprocmask is unspecified in a multithreaded process

Refs:
- https://lwn.net/Articles/415684/
- https://ldpreload.com/blog/signalfd-is-useless

Refs: libevent#1460
Refs: libevent#1342 (cc @dmantipov)
azat added a commit to azat/libevent that referenced this pull request Jul 10, 2023
signalfd may behave differently to sigaction/signal, so to avoid
breaking libevent users (like [1], [2]) disable it by default.

  [1]: tmux/tmux#3621
  [2]: tmux/tmux#3626

Also signalfd is not that perfect:
- you need to SIG_BLOCK the signal before
  - blocked signals are not reset on exec
  - blocked signals are allowed to coalesce - so in case of multiple
    signals sent you may get the signal only once (ok for most of the
    signals, but may be a problem for SIGCHLD, though you may call
    waitpid() in a loop or use pidfd)
- and also one implementation problem -
  sigprocmask is unspecified in a multithreaded process

Refs:
- https://lwn.net/Articles/415684/
- https://ldpreload.com/blog/signalfd-is-useless

Refs: libevent#1460
Refs: libevent#1342 (cc @dmantipov)
azat added a commit to azat/libevent that referenced this pull request Jul 13, 2023
signalfd may behave differently to sigaction/signal, so to avoid
breaking libevent users (like [1], [2]) disable it by default.

  [1]: tmux/tmux#3621
  [2]: tmux/tmux#3626

Also signalfd is not that perfect:
- you need to SIG_BLOCK the signal before
  - blocked signals are not reset on exec
  - blocked signals are allowed to coalesce - so in case of multiple
    signals sent you may get the signal only once (ok for most of the
    signals, but may be a problem for SIGCHLD, though you may call
    waitpid() in a loop or use pidfd)
- and also one implementation problem -
  sigprocmask is unspecified in a multithreaded process

Refs:
- https://lwn.net/Articles/415684/
- https://ldpreload.com/blog/signalfd-is-useless

Refs: libevent#1460
Refs: libevent#1342 (cc @dmantipov)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants