swaywm / swaylock

Screen locker for Wayland
MIT License
851 stars 202 forks source link

Fix handling of multiple SIGUSR1 signals #318

Closed mstoeckl closed 1 year ago

mstoeckl commented 1 year ago

The first commit fixes an issue in which, on receiving a second SIGUSR1, swaylock would exit without unlocking, printing User defined signal 1. The second fixes a deadlock which can occur if too many signals are sent in too short of a time; depending on how quickly signals are sent and on the pipe buffer size, the deadlock may prevent swaylock from exiting, possibly before it can send the unlock message.

To test this, I used a short program that sends signals in a tight loop:

signal_flood.c ``` // gcc signal_flood.c -o signal_flood #include #include #include #include int main(int argc, char **argv) { if (argc != 4) { printf("Usage: signal_flood PID SIGNUM NREPEAT\n"); printf("SIGINT = 2\n"); printf("SIGKILL = 9\n"); printf("SIGUSR1 = 10\n"); printf("SIGUSR2 = 12\n"); printf("SIGTERM = 15\n"); printf("SIGCONT = 18\n"); printf("SIGSTOP = 19\n"); return EXIT_FAILURE; } char *end; int sig = strtol(argv[2], &end, 10); if (*end) { printf("SIGNUM (%s) was not a number\n", argv[2]); return EXIT_FAILURE; } int nrepeat = strtol(argv[3], &end, 10);; if (*end) { printf("NREPEAT (%s) was not a number\n", argv[3]); return EXIT_FAILURE; } pid_t pid = strtol(argv[1], &end, 10);; if (*end) { printf("PID (%s) was not a number\n", argv[1]); return EXIT_FAILURE; } if (pid == 0) { printf("PID should be nonzero\n"); return EXIT_FAILURE; } for (int i = 0; i < nrepeat; i++) { if (kill(pid, sig) == -1) { printf("Iteration %d, sending signal %d to %d failed\n",i,sig,pid); break; } } return EXIT_SUCCESS; } ```