aboutsummaryrefslogtreecommitdiffstats
path: root/misc-utils
diff options
context:
space:
mode:
Diffstat (limited to 'misc-utils')
-rw-r--r--misc-utils/kill.1.adoc2
-rw-r--r--misc-utils/kill.c36
2 files changed, 38 insertions, 0 deletions
diff --git a/misc-utils/kill.1.adoc b/misc-utils/kill.1.adoc
index 4a6996a380..40ab0248d1 100644
--- a/misc-utils/kill.1.adoc
+++ b/misc-utils/kill.1.adoc
@@ -62,6 +62,8 @@ Similar to *-l*, but it will print signal names and their corresponding numbers.
Do not restrict the command-name-to-PID conversion to processes with the same UID as the present process.
*-p*, *--pid*::
Only print the process ID (PID) of the named processes, do not send any signals.
+*-r*, *--require-handler*::
+Do not send the signal if it is not caught in userspace by the signalled process.
*--verbose*::
Print PID(s) that will be signaled with *kill* along with the signal.
*-q*, *--queue* _value_::
diff --git a/misc-utils/kill.c b/misc-utils/kill.c
index f557aacaab..c469074b95 100644
--- a/misc-utils/kill.c
+++ b/misc-utils/kill.c
@@ -95,6 +95,7 @@ struct kill_control {
check_all:1,
do_kill:1,
do_pid:1,
+ require_handler:1,
use_sigval:1,
#ifdef UL_HAVE_PIDFD
timeout:1,
@@ -212,6 +213,7 @@ static void __attribute__((__noreturn__)) usage(void)
fputs(_(" -p, --pid print pids without signaling them\n"), out);
fputs(_(" -l, --list[=<signal>] list signal names, or convert a signal number to a name\n"), out);
fputs(_(" -L, --table list signal names and numbers\n"), out);
+ fputs(_(" -r, --require-handler do not send signal if signal handler is not present\n"), out);
fputs(_(" --verbose print pids that will be signaled\n"), out);
fputs(USAGE_SEPARATOR, out);
@@ -302,6 +304,10 @@ static char **parse_arguments(int argc, char **argv, struct kill_control *ctl)
print_all_signals(stdout, 1);
exit(EXIT_SUCCESS);
}
+ if (!strcmp(arg, "-r") || !strcmp(arg, "--require-handler")) {
+ ctl->require_handler = 1;
+ continue;
+ }
if (!strcmp(arg, "-p") || !strcmp(arg, "--pid")) {
ctl->do_pid = 1;
if (ctl->do_kill)
@@ -448,6 +454,32 @@ static int kill_verbose(const struct kill_control *ctl)
return rc;
}
+static int check_signal_handler(const struct kill_control *ctl)
+{
+ uintmax_t sigcgt = 0;
+ int rc = 0, has_hnd = 0;
+ struct path_cxt *pc;
+
+ if (!ctl->require_handler)
+ return 1;
+
+ pc = ul_new_procfs_path(ctl->pid, NULL);
+ if (!pc)
+ return -ENOMEM;
+
+ rc = procfs_process_get_stat_nth(pc, 34, &sigcgt);
+ if (rc)
+ return -EINVAL;
+
+ ul_unref_path(pc);
+
+ has_hnd = ((1UL << (ctl->numsig - 1)) & sigcgt) != 0;
+ if (ctl->verbose && !has_hnd)
+ printf(_("not signalling pid %d, it has no userspace handler for signal %d\n"), ctl->pid, ctl->numsig);
+
+ return has_hnd;
+}
+
int main(int argc, char **argv)
{
struct kill_control ctl = { .numsig = SIGTERM };
@@ -470,6 +502,8 @@ int main(int argc, char **argv)
errno = 0;
ctl.pid = strtol(ctl.arg, &ep, 10);
if (errno == 0 && ep && *ep == '\0' && ctl.arg < ep) {
+ if (check_signal_handler(&ctl) <= 0)
+ continue;
if (kill_verbose(&ctl) != 0)
nerrs++;
ct++;
@@ -491,6 +525,8 @@ int main(int argc, char **argv)
continue;
if (procfs_dirent_get_pid(d, &ctl.pid) != 0)
continue;
+ if (check_signal_handler(&ctl) <= 0)
+ continue;
if (kill_verbose(&ctl) != 0)
nerrs++;