Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: add -q option to kill for sigqueue



The following adds support for a -q option to kill which takes a numeric
argument. It then uses sigqueue(2) to send the signal with the provided
number which a signal handler can pick up as si_value.sival_int in the
siginfo_t parameter. The util-linux kill also supports a similar option.
sigqueue and a range of "realtime" signals are specified in POSIX and
well supported. As far as I can tell, the RT signals are intended for
user-defined purposes like SIGUSR1 and USR2. The value can be an int or
a pointer but in practice, sending a pointer is fairly useless given
that signals are usually sent to a different process.

We could potentially make the signal value and other details such as
si_pid available to trap handlers. Perhaps using namespaced variables -
e.g. .signal.pid and .signal.value? However, I don't really understand
enough about how trap is implemented to know how (or whether) that can
be done safely.

It also ought to be possible to make SIGRTMIN through to SIGRTMAX
available. util-linux's kill allows those to be specified as RT<n>,
RTMIN+<n> or RTMAX-<n>. Would that need us to muck around with
signames2.awk or is leaving them out of $signals / kill -l and using
#ifdef RTMIN sufficient?

Oliver

diff --git a/Src/jobs.c b/Src/jobs.c
index a3b9f667a..4e9767ee4 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -2677,9 +2677,35 @@ bin_kill(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func))
 {
     int sig = SIGTERM;
     int returnval = 0;
+#ifdef HAVE_SIGQUEUE
+    union sigval sigqueue_info;
+#endif
+    int use_sigqueue = 0, got_sig = 0;
+
+    while (*argv && **argv == '-') {
+	if (!use_sigqueue && (*argv)[1] == 'q' && (*argv)[2] == '\0') {
+	    char *endp;
+
+	    if (!*++argv) {
+		zwarnnam(nam, "-q: argument expected");
+		return 1;
+	    }
+#ifdef HAVE_SIGQUEUE
+	    sigqueue_info.sival_int =
+#endif
+		    zstrtol(*argv, &endp, 10);
+	    if (*endp) {
+		zwarnnam(nam, "invalid number: %s", *argv);
+		return 1;
+	    }
+	    use_sigqueue = 1;
+	    argv++;
+	    continue;
+	}
+	if (got_sig)
+	    break;
 
     /* check for, and interpret, a signal specifier */
-    if (*argv && **argv == '-') {
 	if (idigit((*argv)[1])) {
 	    char *endp;
 	    /* signal specified by number */
@@ -2796,6 +2822,7 @@ bin_kill(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func))
 	    }
 	}
 	argv++;
+	got_sig = 1;
     }
 
     /* Discard the standard "-" and "--" option breaks */
@@ -2844,7 +2871,12 @@ bin_kill(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func))
 	    returnval++;
 	} else {
 	    int pid = atoi(*argv);
-	    if (kill(pid, sig) == -1) {
+	    if (
+#ifdef HAVE_SIGQUEUE
+		use_sigqueue ? sigqueue(pid, sig, sigqueue_info) :
+#endif
+		kill(pid, sig) == -1)
+	    {
 		zwarnnam("kill", "kill %s failed: %e", *argv, errno);
 		returnval++;
 	    } 
diff --git a/configure.ac b/configure.ac
index c5263035e..9cb6e032b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1299,6 +1299,7 @@ AC_CHECK_FUNCS(strftime strptime mktime timelocal \
 	       mkfifo _mktemp mkstemp \
 	       waitpid wait3 \
 	       sigaction sigblock sighold sigrelse sigsetmask sigprocmask \
+	       sigqueue \
 	       killpg setpgid setpgrp tcsetpgrp tcgetattr nice \
 	       gethostname gethostbyname2 getipnodebyname \
 	       inet_aton inet_pton inet_ntop \




Messages sorted by: Reverse Date, Date, Thread, Author