diff --git a/winsup/cygwin/external.cc b/winsup/cygwin/external.cc index ae30695a1..fbb901f3a 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 480d8ea06..afc193fb7 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 17b564da4..0909d1173 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 @@ -717,7 +719,13 @@ $ /bin/kill --version which should give the Cygwin kill version number and copyright information. - Unless you specific the -f option, the "pid" + The -f option uses Windows functions to + terminate processes forcefully. Use -f to + terminate native Windows processes not started by Cygwin processes. + -f can also be useful to terminate Cygwin processes + not answering to SIGKILL. + + Unless you specific the -W option, the "pid" values used by kill are the Cygwin pids, not the Windows pids. To get a list of running programs and their Cygwin pids, use the Cygwin ps program. ps -W diff --git a/winsup/utils/kill.cc b/winsup/utils/kill.cc index e34923ac0..7905c4ea7 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; } - else if (kill ((pid_t) pid, sig) == 0) + if (winpids) + { + dwpid = pid; + pid = (pid_t) cygwin_internal (CW_WINPID_TO_CYGWIN_PID, dwpid); + } + 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; }