From 8a3cb9c669c3017b0610c1d6dfaec59426203252 Mon Sep 17 00:00:00 2001 From: Jan Dubois Date: Tue, 15 Mar 2011 16:53:00 -0700 Subject: [PATCH] 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. --- t/op/fork.t | 20 ++++++++++++++++++++ win32/perlhost.h | 1 + win32/win32.c | 26 +++++++++++++++++++++++++- win32/win32.h | 15 ++++----------- 4 files changed, 50 insertions(+), 12 deletions(-) diff --git a/t/op/fork.t b/t/op/fork.t index b74da8b..fbff8fb 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 70a2f65..0240044 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 b8bb5bb..cffd2b5 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 65d6d31..204a380 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 */ -- 2.7.4