In rare cases, '/bin/kill -f PID' hangs because kill(2) is always tried first. With this patch, this could be prevented with '/bin/kill -f -s - PID'.

--
Regards,
Christian

From cb07ca02a856be378a2435f2095835c264b62bd9 Mon Sep 17 00:00:00 2001
From: Christian Franke <christian.fra...@t-online.de>
Date: Fri, 11 Apr 2025 16:34:48 +0200
Subject: [PATCH] Cygwin: kill(1): skip kill(2) call if '-f -s -' is used

If a process does not process signals including SIGKILL, a kill(2)
call may also hang.  If '-' is specified instead of a signal, the
win32 interface is used without trying kill(2) first.

Signed-off-by: Christian Franke <christian.fra...@t-online.de>
---
 winsup/utils/kill.cc | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/winsup/utils/kill.cc b/winsup/utils/kill.cc
index bcabcd47c..b2d3c6709 100644
--- a/winsup/utils/kill.cc
+++ b/winsup/utils/kill.cc
@@ -44,6 +44,7 @@ usage (FILE *where = stderr)
        "Send signals to processes\n"
        "\n"
        " -f, --force     force, using win32 interface if necessary\n"
+       "                 (add '-s -' to always use win32 interface)\n"
        " -l, --list      print a list of signal names\n"
        " -L, --table     print a formatted table of signal names\n"
        " -s, --signal    send signal (use %1$s --list for a list)\n"
@@ -312,6 +313,7 @@ main (int argc, char **argv)
 {
   int sig = SIGTERM;
   int force = 0;
+  int force_no_sig = 0;
   int winpids = 0;
   int ret = 0;
   char *gotasig = NULL;
@@ -335,7 +337,9 @@ main (int argc, char **argv)
        {
        case 's':
          gotasig = optarg;
-         sig = getsig (gotasig);
+         force_no_sig = !strcmp (gotasig, "-");
+         sig = (!force_no_sig ? getsig (gotasig) :
+               SIGKILL /* for exit status */);
          break;
        case 'l':
          if (!optarg)
@@ -387,6 +391,11 @@ main (int argc, char **argv)
     }
 
 out:
+  if (force_no_sig && !force)
+    {
+      fprintf (stderr, "%s: signal '-' requires '-f'\n", prog_name);
+      return 1;
+    }
   test_for_unknown_sig (sig, gotasig);
 
   argv += optind;
@@ -410,9 +419,10 @@ out:
       if (winpids)
        {
          dwpid = pid;
-         pid = (pid_t) cygwin_internal (CW_WINPID_TO_CYGWIN_PID, dwpid);
+         if (!force_no_sig)
+           pid = (pid_t) cygwin_internal (CW_WINPID_TO_CYGWIN_PID, dwpid);
        }
-      if (kill ((pid_t) pid, sig) == 0)
+      if (!force_no_sig && kill ((pid_t) pid, sig) == 0)
        {
          if (force)
            forcekill ((pid_t) pid, dwpid, sig, 1);
-- 
2.45.1

Reply via email to