From: Gurusamy Sarathy Date: Thu, 17 Aug 2000 00:19:20 +0000 (+0000) Subject: waitpid() now handles externally spawned pids correctly; X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=922b18888a177879df1569d1969abfcaa0090a6f;p=p5sagit%2Fp5-mst-13.2.git waitpid() now handles externally spawned pids correctly; fixes for backtick/wait/waitpid failures on Windows 9x these changes make the pid returned by process functions on Windows 9x always positive by clearing the high bit (which is always set on Win9x); pseudo-process PIDs are likewise always negative now on Win9x (just as on NT/2000) p4raw-id: //depot/perl@6661 --- diff --git a/pp_sys.c b/pp_sys.c index ba9e3bf..8a77c09 100644 --- a/pp_sys.c +++ b/pp_sys.c @@ -3868,6 +3868,8 @@ PP(pp_system) } PerlProc__exit(-1); #else /* ! FORK or VMS or OS/2 */ + PL_statusvalue = 0; + result = 0; if (PL_op->op_flags & OPf_STACKED) { SV *really = *++MARK; value = (I32)do_aspawn(really, (void **)MARK, (void **)SP); @@ -3877,10 +3879,12 @@ PP(pp_system) else { value = (I32)do_spawn(SvPVx(sv_mortalcopy(*SP), n_a)); } + if (PL_statusvalue == -1) /* hint that value must be returned as is */ + result = 1; STATUS_NATIVE_SET(value); do_execfree(); SP = ORIGMARK; - PUSHi(STATUS_CURRENT); + PUSHi(result ? value : STATUS_CURRENT); #endif /* !FORK or VMS */ RETURN; } diff --git a/win32/perlhost.h b/win32/perlhost.h index 3b1d8ca..4509a2c 100644 --- a/win32/perlhost.h +++ b/win32/perlhost.h @@ -1666,6 +1666,11 @@ win32_start_child(LPVOID arg) w32_pseudo_id = id; #else w32_pseudo_id = GetCurrentThreadId(); + if (IsWin95()) { + int pid = (int)w32_pseudo_id; + if (pid < 0) + w32_pseudo_id = -pid; + } #endif if (tmpgv = gv_fetchpv("$", TRUE, SVt_PV)) sv_setiv(GvSV(tmpgv), -(IV)w32_pseudo_id); @@ -1781,6 +1786,11 @@ PerlProcFork(struct IPerlProc* piPerl) errno = EAGAIN; return -1; } + if (IsWin95()) { + int pid = (int)id; + if (pid < 0) + id = -pid; + } w32_pseudo_child_handles[w32_num_pseudo_children] = handle; w32_pseudo_child_pids[w32_num_pseudo_children] = id; ++w32_num_pseudo_children; diff --git a/win32/win32.c b/win32/win32.c index 56ebdaf..5af22ff 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -436,12 +436,19 @@ win32_os_id(void) DllExport int win32_getpid(void) { + int pid; #ifdef USE_ITHREADS dTHXo; if (w32_pseudo_id) return -((int)w32_pseudo_id); #endif - return _getpid(); + pid = _getpid(); + /* Windows 9x appears to always reports a pid for threads and processes + * that has the high bit set. So we treat the lower 31 bits as the + * "real" PID for Perl's purposes. */ + if (IsWin95() && pid < 0) + pid = -pid; + return pid; } /* Tokenize a string. Words are null-separated, and the list @@ -568,7 +575,11 @@ do_aspawn(void *vreally, void **vmark, void **vsp) (const char* const*)argv); } - if (flag != P_NOWAIT) { + if (flag == P_NOWAIT) { + if (IsWin95()) + PL_statusvalue = -1; /* >16bits hint for pp_system() */ + } + else { if (status < 0) { dTHR; if (ckWARN(WARN_EXEC)) @@ -657,7 +668,11 @@ do_spawn2(char *cmd, int exectype) cmd = argv[0]; Safefree(argv); } - if (exectype != EXECF_SPAWN_NOWAIT) { + if (exectype == EXECF_SPAWN_NOWAIT) { + if (IsWin95()) + PL_statusvalue = -1; /* >16bits hint for pp_system() */ + } + else { if (status < 0) { dTHR; if (ckWARN(WARN_EXEC)) @@ -1034,6 +1049,10 @@ win32_kill(int pid, int sig) return 0; } } + else if (IsWin95()) { + pid = -pid; + goto alien_process; + } } else #endif @@ -1049,7 +1068,9 @@ win32_kill(int pid, int sig) } } else { - hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid); +alien_process: + hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, + (IsWin95() ? -pid : pid)); if (hProcess) { if (!sig) return 0; @@ -1636,6 +1657,7 @@ DllExport int win32_waitpid(int pid, int *status, int flags) { dTHXo; + DWORD timeout = (flags & WNOHANG) ? 0 : INFINITE; int retval = -1; if (pid == -1) /* XXX threadid == 1 ? */ return win32_wait(status); @@ -1644,7 +1666,6 @@ win32_waitpid(int pid, int *status, int flags) long child = find_pseudo_pid(-pid); if (child >= 0) { HANDLE hThread = w32_pseudo_child_handles[child]; - DWORD timeout = (flags & WNOHANG) ? 0 : INFINITE; DWORD waitcode = WaitForSingleObject(hThread, timeout); if (waitcode == WAIT_TIMEOUT) { return 0; @@ -1660,35 +1681,53 @@ win32_waitpid(int pid, int *status, int flags) else errno = ECHILD; } + else if (IsWin95()) { + pid = -pid; + goto alien_process; + } } #endif else { + HANDLE hProcess; + DWORD waitcode; long child = find_pid(pid); if (child >= 0) { - HANDLE hProcess = w32_child_handles[child]; - DWORD timeout = (flags & WNOHANG) ? 0 : INFINITE; - DWORD waitcode = WaitForSingleObject(hProcess, timeout); + hProcess = w32_child_handles[child]; + waitcode = WaitForSingleObject(hProcess, timeout); if (waitcode == WAIT_TIMEOUT) { return 0; } else if (waitcode != WAIT_FAILED) { - if (GetExitCodeProcess(hProcess, &waitcode)) { - *status = (int)((waitcode & 0xff) << 8); - retval = (int)w32_child_pids[child]; - remove_dead_process(child); - return retval; - } + if (GetExitCodeProcess(hProcess, &waitcode)) { + *status = (int)((waitcode & 0xff) << 8); + retval = (int)w32_child_pids[child]; + remove_dead_process(child); + return retval; + } } else errno = ECHILD; } else { - retval = cwait(status, pid, WAIT_CHILD); - /* cwait() returns "correctly" on Borland */ -#ifndef __BORLANDC__ - if (status) - *status *= 256; -#endif +alien_process: + hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, + (IsWin95() ? -pid : pid)); + if (hProcess) { + waitcode = WaitForSingleObject(hProcess, timeout); + if (waitcode == WAIT_TIMEOUT) { + return 0; + } + else if (waitcode != WAIT_FAILED) { + if (GetExitCodeProcess(hProcess, &waitcode)) { + *status = (int)((waitcode & 0xff) << 8); + CloseHandle(hProcess); + return pid; + } + } + CloseHandle(hProcess); + } + else + errno = ECHILD; } } return retval >= 0 ? pid : retval; @@ -3273,9 +3312,12 @@ RETRY: if (mode == P_NOWAIT) { /* asynchronous spawn -- store handle, return PID */ - w32_child_handles[w32_num_children] = ProcessInformation.hProcess; - w32_child_pids[w32_num_children] = ProcessInformation.dwProcessId; ret = (int)ProcessInformation.dwProcessId; + if (IsWin95() && ret < 0) + ret = -ret; + + w32_child_handles[w32_num_children] = ProcessInformation.hProcess; + w32_child_pids[w32_num_children] = (DWORD)ret; ++w32_num_children; } else { @@ -3835,8 +3877,11 @@ XS(w32_Spawn) &stStartInfo, /* -> Startup info */ &stProcInfo)) /* <- Process info (if OK) */ { + int pid = (int)stProcInfo.dwProcessId; + if (IsWin95() && pid < 0) + pid = -pid; + sv_setiv(ST(2), pid); CloseHandle(stProcInfo.hThread);/* library source code does this. */ - sv_setiv(ST(2), stProcInfo.dwProcessId); bSuccess = TRUE; } XSRETURN_IV(bSuccess);