summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Dubois <jand@activestate.com>2011-03-15 16:53:00 -0700
committerJan Dubois <jand@activestate.com>2011-03-15 17:14:16 -0700
commit8a3cb9c669c3017b0610c1d6dfaec59426203252 (patch)
tree6da7f63ae2c98872bc23e8aafc57e886cc7e1422
parent3aa0ac5aa5f5cff1b95ae5ff8641818c450e4b16 (diff)
downloadperl-8a3cb9c669c3017b0610c1d6dfaec59426203252.tar.gz
Hang on to child handle after signalling SIGTERM
This is a refinement of commit 3aa0ac5aa. We still want to hang on to the mapping between pseudo-process and thread handle, so that we can still waitpid() after signalling SIGTERM. We just don't want to wait implicitly on the signalled process anymore.
-rw-r--r--t/op/fork.t20
-rw-r--r--win32/perlhost.h1
-rw-r--r--win32/win32.c26
-rw-r--r--win32/win32.h15
4 files changed, 50 insertions, 12 deletions
diff --git a/t/op/fork.t b/t/op/fork.t
index b74da8b0a2..fbff8fb2d9 100644
--- a/t/op/fork.t
+++ b/t/op/fork.t
@@ -463,3 +463,23 @@ system $^X, "-e", "if (\$pid=fork){kill(9, \$pid)} else {sleep 5}";
print $?>>8, "\n";
EXPECT
0
+########
+# Windows fork() emulation: can we still waitpid() after signalling SIGTERM?
+$|=1;
+if (my $pid = fork) {
+ sleep 1;
+ print "1\n";
+ kill 'TERM', $pid;
+ waitpid($pid, 0);
+ print "4\n";
+}
+else {
+ $SIG{TERM} = sub { print "2\n" };
+ sleep 3;
+ print "3\n";
+}
+EXPECT
+1
+2
+3
+4
diff --git a/win32/perlhost.h b/win32/perlhost.h
index 70a2f65639..0240044c11 100644
--- a/win32/perlhost.h
+++ b/win32/perlhost.h
@@ -1877,6 +1877,7 @@ PerlProcFork(struct IPerlProc* piPerl)
}
w32_pseudo_child_handles[w32_num_pseudo_children] = handle;
w32_pseudo_child_pids[w32_num_pseudo_children] = id;
+ w32_pseudo_child_sigterm[w32_num_pseudo_children] = 0;
++w32_num_pseudo_children;
# endif
return -(int)id;
diff --git a/win32/win32.c b/win32/win32.c
index b8bb5bb5fe..cffd2b5bca 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -1177,9 +1177,33 @@ remove_dead_pseudo_process(long child)
(w32_num_pseudo_children-child-1), DWORD);
Move(&w32_pseudo_child_message_hwnds[child+1], &w32_pseudo_child_message_hwnds[child],
(w32_num_pseudo_children-child-1), HWND);
+ Move(&w32_pseudo_child_sigterm[child+1], &w32_pseudo_child_sigterm[child],
+ (w32_num_pseudo_children-child-1), char);
w32_num_pseudo_children--;
}
}
+
+void
+win32_wait_for_children(pTHX)
+{
+ if (w32_pseudo_children && w32_num_pseudo_children) {
+ long child = 0;
+ long count = 0;
+ HANDLE handles[MAXIMUM_WAIT_OBJECTS];
+
+ for (child = 0; child < w32_num_pseudo_children; ++child) {
+ if (!w32_pseudo_child_sigterm[child])
+ handles[count++] = w32_pseudo_child_handles[child];
+ }
+ /* XXX should use MsgWaitForMultipleObjects() to continue
+ * XXX processing messages while we wait.
+ */
+ WaitForMultipleObjects(count, handles, TRUE, INFINITE);
+
+ while (w32_num_pseudo_children)
+ CloseHandle(w32_pseudo_child_handles[--w32_num_pseudo_children]);
+ }
+}
#endif
static int
@@ -1316,7 +1340,7 @@ win32_kill(int pid, int sig)
*/
if (sig == SIGTERM) {
Sleep(0);
- remove_dead_pseudo_process(child);
+ w32_pseudo_child_sigterm[child] = 1;
}
/* It might be us ... */
PERL_ASYNC_CHECK();
diff --git a/win32/win32.h b/win32/win32.h
index 65d6d319d0..204a380099 100644
--- a/win32/win32.h
+++ b/win32/win32.h
@@ -443,6 +443,7 @@ typedef struct {
DWORD pids[MAXIMUM_WAIT_OBJECTS];
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
HWND message_hwnds[MAXIMUM_WAIT_OBJECTS];
+ char sigterm[MAXIMUM_WAIT_OBJECTS];
} pseudo_child_tab;
#endif
@@ -488,6 +489,7 @@ DllExport int win32_async_check(pTHX);
#define w32_pseudo_child_pids (w32_pseudo_children->pids)
#define w32_pseudo_child_handles (w32_pseudo_children->handles)
#define w32_pseudo_child_message_hwnds (w32_pseudo_children->message_hwnds)
+#define w32_pseudo_child_sigterm (w32_pseudo_children->sigterm)
#define w32_internal_host (PL_sys_intern.internal_host)
#define w32_timerid (PL_sys_intern.timerid)
#define w32_message_hwnd (PL_sys_intern.message_hwnd)
@@ -503,17 +505,8 @@ DllExport int win32_async_check(pTHX);
#define w32_showwindow (PL_sys_intern.thr_intern.Wshowwindow)
#ifdef USE_ITHREADS
-# define PERL_WAIT_FOR_CHILDREN \
- STMT_START { \
- if (w32_pseudo_children && w32_num_pseudo_children) { \
- long children = w32_num_pseudo_children; \
- WaitForMultipleObjects(children, \
- w32_pseudo_child_handles, \
- TRUE, INFINITE); \
- while (children) \
- CloseHandle(w32_pseudo_child_handles[--children]); \
- } \
- } STMT_END
+void win32_wait_for_children(pTHX);
+# define PERL_WAIT_FOR_CHILDREN win32_wait_for_children(aTHX)
#endif
/* IO.xs and POSIX.xs define PERLIO_NOT_STDIO to 1 */