use signalfd instead of signal

Switch to using signalfds because using the signal syscall was causing
problems without the frame callbacks (the change in the next commit), I
think this is because it would end up with multiple tasks polling the
same wayland file descriptor.

Previously this would exit after the second SIGPIPE signal. I checked
with earboxer on irc, and confirmed that handling all occurrences is the
correct behavior.

Signed-off-by: Maarten van Gompel <proycon@anaproy.nl>
This commit is contained in:
ArenM 2022-07-05 12:54:32 -04:00 committed by Maarten van Gompel
parent dbe1e01fe9
commit a2cacb7e25

73
main.c
View File

@ -5,6 +5,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/signalfd.h>
#include <poll.h>
#include <unistd.h> #include <unistd.h>
#include <wayland-client.h> #include <wayland-client.h>
#include <wchar.h> #include <wchar.h>
@ -366,8 +368,7 @@ usage(char *argv0) {
} }
void void
hide(int sigint) { hide() {
signal(SIGUSR1, hide);
if (!layer_surface) { if (!layer_surface) {
return; return;
} }
@ -384,8 +385,7 @@ hide(int sigint) {
} }
void void
show(int sigint) { show() {
signal(SIGUSR2, show);
if (layer_surface) { if (layer_surface) {
return; return;
} }
@ -393,7 +393,6 @@ show(int sigint) {
wl_display_sync(display); wl_display_sync(display);
draw_surf.surf = wl_compositor_create_surface(compositor); draw_surf.surf = wl_compositor_create_surface(compositor);
;
layer_surface = zwlr_layer_shell_v1_get_layer_surface( layer_surface = zwlr_layer_shell_v1_get_layer_surface(
layer_shell, draw_surf.surf, wl_output, layer, namespace); layer_shell, draw_surf.surf, wl_output, layer, namespace);
@ -413,18 +412,13 @@ show(int sigint) {
} }
void void
toggle_visibility(int sigint) { toggle_visibility() {
signal(SIGRTMIN, toggle_visibility); if (hidden) show();
else hide();
if (hidden) {
show(sigint);
} else {
hide(sigint);
}
} }
void void
pipewarn(int sigint) { pipewarn() {
fprintf(stderr, "wvkbd: cannot pipe data out.\n"); fprintf(stderr, "wvkbd: cannot pipe data out.\n");
} }
@ -538,19 +532,50 @@ main(int argc, char **argv) {
draw_ctx.font_description = draw_ctx.font_description =
pango_font_description_from_string(fc_font_pattern); pango_font_description_from_string(fc_font_pattern);
if (!hidden) show(SIGUSR2); if (!hidden) show();
signal(SIGUSR1, hide); struct pollfd fds[2];
signal(SIGUSR2, show); int WAYLAND_FD = 0;
signal(SIGPIPE, pipewarn); int SIGNAL_FD = 1;
signal(SIGRTMIN, toggle_visibility); fds[WAYLAND_FD].events = POLLIN;
fds[SIGNAL_FD].events = POLLIN;
fds[WAYLAND_FD].fd = wl_display_get_fd(display);
if (fds[WAYLAND_FD].fd == -1) {
die("Failed to get wayland_fd: %d\n", errno);
}
sigset_t signal_mask;
sigemptyset(&signal_mask);
sigaddset(&signal_mask, SIGUSR1);
sigaddset(&signal_mask, SIGUSR2);
sigaddset(&signal_mask, SIGRTMIN);
sigaddset(&signal_mask, SIGPIPE);
if (sigprocmask(SIG_BLOCK, &signal_mask, NULL) == -1) {
die("Failed to disable handled signals: %d\n", errno);
}
fds[SIGNAL_FD].fd = signalfd(-1, &signal_mask, 0);
if (fds[SIGNAL_FD].fd == -1) {
die("Failed to get signalfd: %d\n", errno);
}
while (run_display) { while (run_display) {
while (wl_display_dispatch(display) != -1 && layer_surface) { wl_display_flush(display);
} poll(fds, 2, -1);
wl_display_roundtrip(display);
while (run_display && !layer_surface) { if (fds[WAYLAND_FD].revents & POLLIN)
sleep(1); wl_display_dispatch(display);
if (fds[SIGNAL_FD].revents & POLLIN) {
struct signalfd_siginfo si;
if (read(fds[SIGNAL_FD].fd, &si, sizeof(si)) != sizeof(si))
fprintf(stderr, "Signal read error: %d", errno);
else if (si.ssi_signo == SIGUSR1) hide();
else if (si.ssi_signo == SIGUSR2) show();
else if (si.ssi_signo == SIGRTMIN) toggle_visibility();
else if (si.ssi_signo == SIGPIPE) pipewarn();
} }
} }