kill: use sigqueue to pass value with the signal.

New -q/--queue option for kill so it will send an integer to the
signalled process. See sigqueue(3) for details.

References:
 https://pubs.opengroup.org/onlinepubs/009695399/functions/sigqueue.html
 procps-ng/procps!32

Signed-off-by: Craig Small <csmall@dropbear.xyz>
This commit is contained in:
Arun Chandrasekaran 2020-04-24 19:22:47 +10:00 committed by Craig Small
parent 1f5e037d4f
commit 2b804a532a
3 changed files with 30 additions and 5 deletions

14
kill.1
View File

@ -6,7 +6,7 @@ it under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
.. ..
.TH KILL 1 "2018-05-31" "procps-ng" "User Commands" .TH KILL 1 "2020-04-24" "procps-ng" "User Commands"
.SH NAME .SH NAME
kill \- send a signal to a process kill \- send a signal to a process
.SH SYNOPSIS .SH SYNOPSIS
@ -45,6 +45,18 @@ The behavior of signals is explained in
.BR signal (7) .BR signal (7)
manual page. manual page.
.TP .TP
\fB\-q\fR, \fB\-\-queue \fIvalue\fP
Use
.BR sigqueue(2)
rather than
.BR kill(2)
and the value argument is used to specify
an integer to be sent with the signal. If the receiving process has
installed a handler for this signal using the SA_SIGINFO flag to
.BR sigaction(2)
, then it can obtain this data via the si_value field of the
siginfo_t structure.
.TP
\fB\-l\fR, \fB\-\-list\fR [\fIsignal\fR] \fB\-l\fR, \fB\-\-list\fR [\fIsignal\fR]
List signal names. This option has optional argument, which List signal names. This option has optional argument, which
will convert signal number to signal name, or other way round. will convert signal number to signal name, or other way round.

17
skill.c
View File

@ -26,6 +26,7 @@
#include <pwd.h> #include <pwd.h>
#include <signal.h> #include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/resource.h> #include <sys/resource.h>
@ -341,6 +342,7 @@ static void __attribute__ ((__noreturn__)) kill_usage(FILE * out)
fputs(_(" <pid> [...] send signal to every <pid> listed\n"), out); fputs(_(" <pid> [...] send signal to every <pid> listed\n"), out);
fputs(_(" -<signal>, -s, --signal <signal>\n" fputs(_(" -<signal>, -s, --signal <signal>\n"
" specify the <signal> to be sent\n"), out); " specify the <signal> to be sent\n"), out);
fputs(_(" -q, --queue <value> integer value to be sent with the signal\n"), out);
fputs(_(" -l, --list=[<signal>] list all signal names, or convert one to a name\n"), out); fputs(_(" -l, --list=[<signal>] list all signal names, or convert one to a name\n"), out);
fputs(_(" -L, --table list all signal names in a nice table\n"), out); fputs(_(" -L, --table list all signal names in a nice table\n"), out);
fputs(USAGE_SEPARATOR, out); fputs(USAGE_SEPARATOR, out);
@ -434,6 +436,8 @@ static void __attribute__ ((__noreturn__))
int signo, i; int signo, i;
long pid; long pid;
int exitvalue = EXIT_SUCCESS; int exitvalue = EXIT_SUCCESS;
union sigval sigval;
bool use_sigqueue = false;
char *sig_option; char *sig_option;
static const struct option longopts[] = { static const struct option longopts[] = {
@ -442,6 +446,7 @@ static void __attribute__ ((__noreturn__))
{"signal", required_argument, NULL, 's'}, {"signal", required_argument, NULL, 's'},
{"help", no_argument, NULL, 'h'}, {"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'V'}, {"version", no_argument, NULL, 'V'},
{"queue", required_argument, NULL, 'q'},
{NULL, 0, NULL, 0} {NULL, 0, NULL, 0}
}; };
@ -458,7 +463,7 @@ static void __attribute__ ((__noreturn__))
signo = SIGTERM; signo = SIGTERM;
opterr=0; /* suppress errors on -123 */ opterr=0; /* suppress errors on -123 */
while ((i = getopt_long(argc, argv, "l::Ls:hV", longopts, NULL)) != -1) while ((i = getopt_long(argc, argv, "l::Ls:hVq:", longopts, NULL)) != -1)
switch (i) { switch (i) {
case 'l': case 'l':
sig_option = NULL; sig_option = NULL;
@ -491,6 +496,10 @@ static void __attribute__ ((__noreturn__))
case 'V': case 'V':
display_kill_version(); display_kill_version();
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
case 'q':
sigval.sival_int = strtol_or_err(optarg, _("must be an integer value to be passed with the signal."));
use_sigqueue = true;
break;
case '?': case '?':
if (!isdigit(optopt)) { if (!isdigit(optopt)) {
xwarnx(_("invalid argument %c"), optopt); xwarnx(_("invalid argument %c"), optopt);
@ -516,7 +525,11 @@ static void __attribute__ ((__noreturn__))
for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++) {
pid = strtol_or_err(argv[i], _("failed to parse argument")); pid = strtol_or_err(argv[i], _("failed to parse argument"));
if (!kill((pid_t) pid, signo)) if (use_sigqueue) {
if (!sigqueue((pid_t) pid, signo, sigval))
continue;
}
else if (!kill((pid_t) pid, signo))
continue; continue;
error(0, errno, "(%ld)", pid); error(0, errno, "(%ld)", pid);
exitvalue = EXIT_FAILURE; exitvalue = EXIT_FAILURE;

View File

@ -10,7 +10,7 @@ if { ![ file exists $kill ] } {
set test "kill with no arguments" set test "kill with no arguments"
spawn $kill spawn $kill
expect_pass "$test" "Usage:\\s+\(lt-\)?kill \\\[options\\\] <pid> \\\[...\\\]\\s+Options:\\s+<pid> \\\[...\\\]\\s+send signal to every <pid> listed\\s+-<signal>, -s, --signal <signal>\\s+specify the <signal> to be sent\\s+-l, --list=\\\[<signal>\\\]\\s+list all signal names, or convert one to a name\\\s+-L, --table\\s+list all signal names in a nice table$usage_help$usage_version$usage_man" expect_pass "$test" "Usage:\\s+\(lt-\)?kill \\\[options\\\] <pid>"
set test "kill list signal names" set test "kill list signal names"
spawn $kill -l spawn $kill -l