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 557fda8f98
commit cd7ea2abf3
3 changed files with 24 additions and 7 deletions

2
kill.1
View File

@ -5,7 +5,7 @@
.\" Licensed under version 2 of the GNU General Public License. .\" Licensed under version 2 of the GNU General Public License.
.\" Written by Albert Cahalan; converted to a man page by .\" Written by Albert Cahalan; converted to a man page by
.\" Michael K. Johnson .\" Michael K. Johnson
.TH KILL 1 "October 2011" "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

27
kill.c
View File

@ -21,6 +21,7 @@
#include <getopt.h> #include <getopt.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdbool.h>
#include <signal.h> #include <signal.h>
#include <ctype.h> #include <ctype.h>
@ -39,6 +40,7 @@ static void __attribute__ ((__noreturn__)) print_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);
@ -48,12 +50,22 @@ static void __attribute__ ((__noreturn__)) print_usage(FILE * out)
exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
} }
inline static int execute_kill(pid_t pid, int sig_num, const bool use_sigqueue, union sigval sigval)
{
if (use_sigqueue)
return sigqueue(pid, sig_num, sigval);
else
return kill(pid, sig_num);
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int signo, i; int signo, i;
long pid; long pid;
int exitvalue = EXIT_SUCCESS; int exitvalue = EXIT_SUCCESS;
int optindex; int optindex;
union sigval sigval;
bool use_sigqueue = false;
char *sig_option; char *sig_option;
static const struct option longopts[] = { static const struct option longopts[] = {
@ -62,6 +74,7 @@ int main(int argc, char **argv)
{"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}
}; };
@ -79,7 +92,7 @@ int main(int argc, char **argv)
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, &optindex)) != -1) while ((i = getopt_long(argc, argv, "l::Ls:hVq:", longopts, &optindex)) != -1)
switch (i) { switch (i) {
case 'l': case 'l':
sig_option = NULL; sig_option = NULL;
@ -112,6 +125,10 @@ int main(int argc, char **argv)
case 'V': case 'V':
fprintf(stdout, PROCPS_NG_VERSION); fprintf(stdout, PROCPS_NG_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);
@ -119,9 +136,9 @@ int main(int argc, char **argv)
} else { } else {
/* Special case for signal digit negative /* Special case for signal digit negative
* PIDs */ * PIDs */
pid = (long)('0' - optopt); pid = (long)('0' - optopt);
if (kill((pid_t)pid, signo) != 0) if (!execute_kill((pid_t) pid, signo, use_sigqueue, sigval))
exitvalue = EXIT_FAILURE; exitvalue = EXIT_FAILURE;
exit(exitvalue); exit(exitvalue);
} }
xerrx(EXIT_FAILURE, _("internal error")); xerrx(EXIT_FAILURE, _("internal error"));
@ -137,7 +154,7 @@ int main(int argc, char **argv)
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 (!execute_kill((pid_t) pid, signo, use_sigqueue, sigval))
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