[newlib-cygwin] Cygwin: kill(1): introduce a -W option

Corinna Vinschen corinna@sourceware.org
Sat Feb 2 20:07:00 GMT 2019


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=658f9390032ad2f4a70fb2550480ec8ca58a530a

commit 658f9390032ad2f4a70fb2550480ec8ca58a530a
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Sat Feb 2 21:02:00 2019 +0100

    Cygwin: kill(1): introduce a -W option
    
    Allow to kill processes using Windows PIDs on the command line.
    
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 winsup/cygwin/external.cc          |  9 ++++++
 winsup/cygwin/include/sys/cygwin.h |  2 ++
 winsup/doc/utils.xml               | 10 ++++++-
 winsup/utils/kill.cc               | 58 +++++++++++++++++++++++++-------------
 4 files changed, 59 insertions(+), 20 deletions(-)

diff --git a/winsup/cygwin/external.cc b/winsup/cygwin/external.cc
index ae30695..fbb901f 100644
--- a/winsup/cygwin/external.cc
+++ b/winsup/cygwin/external.cc
@@ -322,6 +322,15 @@ cygwin_internal (cygwin_getinfo_types t, ...)
 	  res = p ? p->dwProcessId : 0;
 	}
 	break;
+
+      case CW_WINPID_TO_CYGWIN_PID:
+	{
+	  DWORD winpid = va_arg (arg, DWORD);
+	  pid_t pid = cygwin_pid (winpid);
+	  res = pid ?: winpid + MAX_PID;
+	}
+	break;
+
       case CW_EXTRACT_DOMAIN_AND_USER:
 	{
 	  WCHAR nt_domain[MAX_DOMAIN_NAME_LEN + 1];
diff --git a/winsup/cygwin/include/sys/cygwin.h b/winsup/cygwin/include/sys/cygwin.h
index 480d8ea..afc193f 100644
--- a/winsup/cygwin/include/sys/cygwin.h
+++ b/winsup/cygwin/include/sys/cygwin.h
@@ -158,6 +158,7 @@ typedef enum
     CW_GETNSS_GRP_SRC,
     CW_EXCEPTION_RECORD_FROM_SIGINFO_T,
     CW_CYGHEAP_PROFTHR_ALL,
+    CW_WINPID_TO_CYGWIN_PID,
   } cygwin_getinfo_types;
 
 #define CW_LOCK_PINFO CW_LOCK_PINFO
@@ -220,6 +221,7 @@ typedef enum
 #define CW_GETNSS_GRP_SRC CW_GETNSS_GRP_SRC
 #define CW_EXCEPTION_RECORD_FROM_SIGINFO_T CW_EXCEPTION_RECORD_FROM_SIGINFO_T
 #define CW_CYGHEAP_PROFTHR_ALL CW_CYGHEAP_PROFTHR_ALL
+#define CW_WINPID_TO_CYGWIN_PID CW_WINPID_TO_CYGWIN_PID
 
 /* Token type for CW_SET_EXTERNAL_TOKEN */
 enum
diff --git a/winsup/doc/utils.xml b/winsup/doc/utils.xml
index 17b564d..0909d11 100644
--- a/winsup/doc/utils.xml
+++ b/winsup/doc/utils.xml
@@ -692,6 +692,8 @@ kill -l [signal]
  -f, --force     force, using win32 interface if necessary
  -l, --list      print a list of signal names
  -s, --signal    send signal (use kill --list for a list)
+ -W, --winpid    specified pids are windows PIDs, not Cygwin PIDs
+                 (use with extrem caution!)
  -h, --help      output usage information and exit
  -V, --version   output version information and exit
 </screen>
@@ -717,7 +719,13 @@ $ /bin/kill --version
 </screen> which should give the Cygwin
       <command>kill</command> version number and copyright information. </para>
 
-    <para>Unless you specific the <literal>-f</literal> option, the "pid"
+    <para>The <literal>-f</literal> option uses Windows functions to
+      terminate processes forcefully. Use <literal>-f</literal> to
+      terminate native Windows processes not started by Cygwin processes.
+      <literal>-f</literal> can also be useful to terminate Cygwin processes
+      not answering to SIGKILL.</para>
+
+    <para>Unless you specific the <literal>-W</literal> option, the "pid"
       values used by <command>kill</command> are the Cygwin pids, not the
       Windows pids. To get a list of running programs and their Cygwin pids,
       use the Cygwin <command>ps</command> program. <command>ps -W</command>
diff --git a/winsup/utils/kill.cc b/winsup/utils/kill.cc
index e34923a..7905c4e 100644
--- a/winsup/utils/kill.cc
+++ b/winsup/utils/kill.cc
@@ -26,17 +26,18 @@ static struct option longopts[] =
   {"list", optional_argument, NULL, 'l'},
   {"force", no_argument, NULL, 'f'},
   {"signal", required_argument, NULL, 's'},
+  {"winpid", no_argument, NULL, 'W'},
   {"version", no_argument, NULL, 'V'},
   {NULL, 0, NULL, 0}
 };
 
-static char opts[] = "hl::fs:V";
+static char opts[] = "hl::fs:WV";
 
 static void
 usage (FILE *where = stderr)
 {
   fprintf (where , ""
-	"Usage: %1$s [-f] [-signal] [-s signal] pid1 [pid2 ...]\n"
+	"Usage: %1$s [-fW] [-signal] [-s signal] pid1 [pid2 ...]\n"
 	"       %1$s -l [signal]\n"
 	"\n"
 	"Send signals to processes\n"
@@ -44,6 +45,8 @@ usage (FILE *where = stderr)
 	" -f, --force     force, using win32 interface if necessary\n"
 	" -l, --list      print a list of signal names\n"
 	" -s, --signal    send signal (use %1$s --list for a list)\n"
+	" -W, --winpid    specified pids are windows PIDs, not Cygwin PIDs\n"
+	"                 (use with extrem caution!)\n"
 	" -h, --help      output usage information and exit\n"
 	" -V, --version   output version information and exit\n"
 	"\n", prog_name);
@@ -152,19 +155,28 @@ get_debug_priv (void)
 }
 
 static void __stdcall
-forcekill (pid_t pid, int sig, int wait)
+forcekill (pid_t pid, DWORD winpid, int sig, int wait)
 {
+  DWORD dwpid;
+
   /* try to acquire SeDebugPrivilege */
   get_debug_priv();
 
-  external_pinfo *p = NULL;
-  p = (external_pinfo *) cygwin_internal (CW_GETPINFO_FULL, pid);
-  if (!p)
+  if (!winpid)
     {
-      fprintf (stderr, "%s: %d: No such process\n", prog_name, pid);
-      return;
+      external_pinfo *p = (external_pinfo *)
+			  cygwin_internal (CW_GETPINFO_FULL, pid);
+      if (!p)
+	{
+	  fprintf (stderr, "%s: %d: No such process\n", prog_name, pid);
+	  return;
+	}
+      dwpid = p->dwProcessId;
     }
-  DWORD dwpid = p->dwProcessId;
+  else
+    /* pid is used for printing only after this point */
+    pid = dwpid = winpid;
+
   HANDLE h = OpenProcess (PROCESS_TERMINATE, FALSE, dwpid);
   if (!h)
     {
@@ -186,6 +198,7 @@ main (int argc, char **argv)
 {
   int sig = SIGTERM;
   int force = 0;
+  int winpids = 0;
   int ret = 0;
   char *gotasig = NULL;
 
@@ -197,7 +210,6 @@ main (int argc, char **argv)
   opterr = 0;
 
   char *p;
-  long long int pid = 0;
 
   for (;;)
     {
@@ -228,6 +240,9 @@ main (int argc, char **argv)
 	case 'f':
 	  force = 1;
 	  break;
+	case 'W':
+	  winpids = 1;
+	  break;
 	case 'h':
 	  usage (stdout);
 	  break;
@@ -257,32 +272,37 @@ out:
       fprintf (stderr, "%s: not enough arguments\n", prog_name);
       return 1;
     }
-  while (*argv != NULL)
+  for (long long int pid = 0; *argv != NULL; argv++)
     {
-      if (!pid)
-	pid = strtoll (*argv, &p, 10);
+      DWORD dwpid = 0;
+
+      pid = strtoll (*argv, &p, 10);
       /* INT_MIN <= pid <= INT_MAX.  -f only takes positive pids. */
       if (*p != '\0' || pid < (force ? 1 : INT_MIN) || pid > INT_MAX)
 	{
 	  fprintf (stderr, "%s: illegal pid: %s\n", prog_name, *argv);
 	  ret = 1;
+	  continue;
+	}
+      if (winpids)
+	{
+	  dwpid = pid;
+	  pid = (pid_t) cygwin_internal (CW_WINPID_TO_CYGWIN_PID, dwpid);
 	}
-      else if (kill ((pid_t) pid, sig) == 0)
+      if (kill ((pid_t) pid, sig) == 0)
 	{
 	  if (force)
-	    forcekill ((pid_t) pid, sig, 1);
+	    forcekill ((pid_t) pid, dwpid, sig, 1);
 	}
       else if (force)
-	forcekill ((pid_t) pid, sig, 0);
+	forcekill ((pid_t) pid, dwpid, sig, 0);
       else
 	{
 	  char buf[1000];
-	  sprintf (buf, "%s: %lld", prog_name, pid);
+	  sprintf (buf, "%s: %lld", prog_name, dwpid ?: pid);
 	  perror (buf);
 	  ret = 1;
 	}
-      argv++;
-      pid = 0;
     }
   return ret;
 }



More information about the Cygwin-cvs mailing list