aboutsummaryrefslogtreecommitdiff
path: root/marsond.c
diff options
context:
space:
mode:
authorB. Watson <urchlay@slackware.uk>2025-05-07 01:56:01 -0400
committerB. Watson <urchlay@slackware.uk>2025-05-07 01:56:01 -0400
commit8359a7bc484c110552b347f6277d1218198bbec6 (patch)
treee8ccb3ff1155bbb1ba46cfa750cf1b57d05c4fdc /marsond.c
parent7b21ee0a67151824dca759874689e558b124ef27 (diff)
downloadmarsond-8359a7bc484c110552b347f6277d1218198bbec6.tar.gz
exit cleanly on both SIGTERM and die().
Diffstat (limited to 'marsond.c')
-rw-r--r--marsond.c58
1 files changed, 56 insertions, 2 deletions
diff --git a/marsond.c b/marsond.c
index 9419105..4a3b06a 100644
--- a/marsond.c
+++ b/marsond.c
@@ -10,6 +10,7 @@
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
+#include <signal.h>
#include <sys/resource.h>
#include <sys/mman.h>
@@ -35,6 +36,10 @@ int foreground = 0; /* -v */
const char *keyboard_dev = DEFAULT_KBD; /* -k */
int delay_ms = DEFAULT_DELAY_MS; /* -d */
+int infd = -1, outfd = -1;
+
+void cleanup(void);
+
/* variadic macros are apparently C99 and not just a GNU extension */
void logmsg(const char *prefix, const char *fmt, ...) {
va_list ap;
@@ -45,7 +50,7 @@ void logmsg(const char *prefix, const char *fmt, ...) {
fputc('\n', stderr);
}
-#define die(fmt, ...) { logmsg("fatal", fmt, ##__VA_ARGS__); exit(1); };
+#define die(fmt, ...) { logmsg("fatal", fmt, ##__VA_ARGS__); cleanup(); exit(1); };
#define warn(fmt, ...) { logmsg("warning", fmt, ##__VA_ARGS__); };
#define info(fmt, ...) { logmsg("info", fmt, ##__VA_ARGS__); };
#define debug(fmt, ...) { if(debugging) logmsg("debug", fmt, ##__VA_ARGS__); };
@@ -106,6 +111,53 @@ void parse_args(int argc, char **argv) {
if(delay_ms < 1) die("invalid -d argument");
}
+/* cleanup() gets called by die() and sighandler() */
+void cleanup(void) {
+ if(outfd != -1) {
+ ioctl(outfd, UI_DEV_DESTROY);
+ close(outfd);
+ outfd = -1;
+ }
+
+ if(infd != -1) {
+ ioctl(infd, EVIOCGRAB, 0);
+ close(infd);
+ infd = -1;
+ }
+}
+
+/* (try to) exit cleanly if we get a SIGTERM.
+ I say "try" because ioctl() (used by cleanup()) is not listed as
+ async-signal-safe in signal-safety(7). However, it does seem to
+ work OK.
+ If we didn't catch SIGTERM, the result would be that the keyboard
+ stops working entirely if marsond was started from udev and
+ manually killed. Cleanly exiting allows the physical keyboard to
+ keep working (with the Enter key timing issue of course).
+ */
+void sighandler(int sig, siginfo_t *si, void *) {
+ if(sig != SIGTERM) {
+ /* this should never happen! */
+ return;
+ }
+
+ cleanup();
+
+ exit(0);
+}
+
+void setup_sighandler(void) {
+ struct sigaction sa;
+
+ sa.sa_flags = SA_SIGINFO;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_sigaction = sighandler;
+
+ if(sigaction(SIGTERM, &sa, NULL) < 0) {
+ warn("can't catch SIGTERM (WTF?)");
+ }
+}
+
/* since every keystroke passes through this daemon, we *don't*
want it to be swapped out. it would suck if you couldn't type
because you were compiling something huge... note that we have to
@@ -215,7 +267,7 @@ void set_evbit(int outfd, int event) {
}
int main(int argc, char **argv) {
- int infd, outfd, i;
+ int i;
struct uinput_user_dev dev;
struct input_event ev;
@@ -280,6 +332,8 @@ int main(int argc, char **argv) {
die("UI_DEV_CREATE failed: %s", strerror(errno));
}
+ setup_sighandler();
+
/* this must be done while still running as root... */
if(foreground) {
lock_memory();