fix killpg on Win32, to meet posix expectations for killpg
authorDaniel Dragan <bulk88@hotmail.com>
Thu, 27 Mar 2014 07:37:03 +0000 (03:37 -0400)
committerSteve Hay <steve.m.hay@googlemail.com>
Thu, 27 Mar 2014 11:01:56 +0000 (11:01 +0000)
On Win32 Perls built without PERL_IMPLICIT_SYS, killpg from win32.c was
directly called by Perl_apply, yet killpg's return value had Win32
behavior, not POSIX behavior. Modify killpg token to have same meaning as
PerlProcKillpg/PerlProc_killpg has on PERL_IMPLICIT_SYS builds. Use a
macro rather than create a win32_killpg C function since win32_killpg would
be nothing but a call to win32_kill anyways. win32_kill contains the Win32
to POSIX semantics conversion code. Rename old killpg to my_killpg since
it has no use outside of win32.c. The psuedo-PID code in win32_kill also
played a factor in not writing a separate win32_killpg that calls
my_killpg. This fix is tested by kill0.t passing on
no-PERL_IMPLICIT_SYS builds.

[perl #121230]

pod/perldelta.pod
win32/win32.c
win32/win32.h
win32/win32iop.h

index 358aea3..aa7e1ce 100644 (file)
@@ -316,6 +316,14 @@ a bug in which the timeout monitor used for tests could not be cancelled once
 the test completes, and the full timeout period elapsed before running the next
 test file.
 
+On a Perl built without psuedo-fork (psuedo-fork builds were not affected by
+this bug), probably since prcess tree kill feature was implemented on Win32,
+killing a process tree with L<perlfunc/kill> and a negative signal, resulted
+in kill inverting the returned value.  This ment successfully killing
+1 process tree PID returned 0, and also passing 2 invalid PID, returned 2.
+This has been corrected so the documented behavior for return values for kill
+executes.  [perl #121230]
+
 =back
 
 =head1 Internal Changes
index 0064a50..bff5b88 100644 (file)
@@ -139,6 +139,7 @@ static int  do_spawnvp_handles(int mode, const char *cmdname,
 static long    find_pid(pTHX_ int pid);
 static void    remove_dead_process(long child);
 static int     terminate_process(DWORD pid, HANDLE process_handle, int sig);
+static int     my_killpg(int pid, int sig);
 static int     my_kill(int pid, int sig);
 static void    out_of_memory(void);
 static char*   wstr_to_str(const wchar_t* wstr);
@@ -1250,8 +1251,9 @@ terminate_process(DWORD pid, HANDLE process_handle, int sig)
     return 0;
 }
 
-int
-killpg(int pid, int sig)
+/* returns number of processes killed */
+static int
+my_killpg(int pid, int sig)
 {
     HANDLE process_handle;
     HANDLE snapshot_handle;
@@ -1271,7 +1273,7 @@ killpg(int pid, int sig)
         if (Process32First(snapshot_handle, &entry)) {
             do {
                 if (entry.th32ParentProcessID == (DWORD)pid)
-                    killed += killpg(entry.th32ProcessID, sig);
+                    killed += my_killpg(entry.th32ProcessID, sig);
                 entry.dwSize = sizeof(entry);
             }
             while (Process32Next(snapshot_handle, &entry));
@@ -1282,6 +1284,7 @@ killpg(int pid, int sig)
     return killed;
 }
 
+/* returns number of processes killed */
 static int
 my_kill(int pid, int sig)
 {
@@ -1289,7 +1292,7 @@ my_kill(int pid, int sig)
     HANDLE process_handle;
 
     if (sig < 0)
-        return killpg(pid, -sig);
+        return my_killpg(pid, -sig);
 
     process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
     /* OpenProcess() returns NULL on error, *not* INVALID_HANDLE_VALUE */
index 3d1655a..e109939 100644 (file)
@@ -322,7 +322,6 @@ extern  gid_t       getegid(void);
 extern  int    setuid(uid_t uid);
 extern  int    setgid(gid_t gid);
 extern  int    kill(int pid, int sig);
-extern  int    killpg(int pid, int sig);
 #ifndef USE_PERL_SBRK
 extern  void   *sbrk(ptrdiff_t need);
 #  define HAS_SBRK_PROTO
index 11d4219..246375f 100644 (file)
@@ -448,6 +448,11 @@ END_EXTERN_C
 #  undef kill
 #endif
 #define kill                   win32_kill
+#ifdef UNDER_CE
+#  undef killpg
+#endif
+#define killpg(pid, sig)       win32_kill(pid, -(sig))
+
 
 #ifdef UNDER_CE
 #  undef opendir