aboutsummaryrefslogtreecommitdiff
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
parent7b21ee0a67151824dca759874689e558b124ef27 (diff)
downloadmarsond-8359a7bc484c110552b347f6277d1218198bbec6.tar.gz
exit cleanly on both SIGTERM and die().
-rw-r--r--TODO12
-rw-r--r--marsond.82
-rw-r--r--marsond.c58
-rw-r--r--marsond.rst19
4 files changed, 79 insertions, 12 deletions
diff --git a/TODO b/TODO
index bb32e1d..22f46c4 100644
--- a/TODO
+++ b/TODO
@@ -1,9 +1,11 @@
-- actual realtime scheduling (maybe). sched(7).
+Definitely:
+
+Maybe:
+
+- actual realtime scheduling (maybe). sched(7). not sure it's
+ needed (nice -20 seems OK even while compiling mame with -j5), and it
+ might interfere with stuff like JACK.
- use a log file instead of stderr, so we can have error/warning messages
after detaching from the tty.
- print our /dev/input/event* node name, if possible.
- options to set the virtual device name and vendor/product IDs.
-- possibly use a UNIX socket. if we can connect to it on startup,
- that means another instance is already running... so either exit
- or pass a command to it (like "marsond -K" would kill an existing
- instance).
diff --git a/marsond.8 b/marsond.8
index 0bc4835..2a73f93 100644
--- a/marsond.8
+++ b/marsond.8
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
..
-.TH "MARSOND" 8 "2025-05-06" "0.1.4" "SlackBuilds.org"
+.TH "MARSOND" 8 "2025-05-07" "0.1.4" "SlackBuilds.org"
.SH NAME
marsond \- Fix Enter key timing on Marson/USBLink/MT606-1 PS/2-USB adaptors
.SH SYNOPSIS
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();
diff --git a/marsond.rst b/marsond.rst
index ee36b42..8f79bf3 100644
--- a/marsond.rst
+++ b/marsond.rst
@@ -57,10 +57,21 @@ does, with SDL 1 and 2 running under X (and SDL 1 on the console,
too). I don't use Wayland, so I haven't tested it there. If you do,
please contact me and let me know if it works for you.
-**marsond** must be run as root. After grabbing the keyboard
-and creating the virtual keyboard device, it will drop
-privileges and run as the *nobody* user by default (but
-see **ENVIRONMENT** if you need a different user).
+**marsond** must be run as root. At startup, it does these
+things as root:
+
+- Grab the physical keyboard.
+
+- Create the virtual keyboard device.
+
+- Lock its pages into physical memory, to avoid being swapped out.
+
+- Set its priority (nice value) to -20 (highest priority), to
+ avoid slow response on a loaded system.
+
+After doing the above, root access is no longer needed, so it will
+drop privileges and run as the *nobody* user by default (but see
+**ENVIRONMENT** if you need a different user).
While **marsond** is running, "xinput --list" will show an input
device called "marson virtual keyboard".