From ab034fab03bf1a0ee1d03651799f1c42f4f48050 Mon Sep 17 00:00:00 2001 From: Tim Peters Date: Fri, 1 Feb 2002 11:27:43 +0000 Subject: [PATCH] Implement os.waitpid() for Windows, in a way that's compatible with Linux where their capabilities intersect. Would be nice if people using non- MSVC compilers (Borland etc) took a whack at doing something similar for them (this code relies on the MS _cwait function). --- Doc/lib/libos.tex | 27 +++++++++++++++++++++------ Misc/NEWS | 7 +++++++ Modules/posixmodule.c | 30 ++++++++++++++++++++++++++++-- 3 files changed, 56 insertions(+), 8 deletions(-) diff --git a/Doc/lib/libos.tex b/Doc/lib/libos.tex index 51f00273eff..57394855afe 100644 --- a/Doc/lib/libos.tex +++ b/Doc/lib/libos.tex @@ -96,7 +96,7 @@ environment. \function{putenv()} will be called automatically when the mapping is modified. If \function{putenv()} is not provided, this mapping may be passed to -the appropriate process-creation functions to cause child processes to +the appropriate process-creation functions to cause child processes to use a modified environment. \end{datadesc} @@ -184,7 +184,7 @@ When \function{putenv()} is supported, assignments to items in \code{os.environ} are automatically translated into corresponding calls to \function{putenv()}; however, calls to \function{putenv()} don't update \code{os.environ}, so it is -actually preferable to assign to items of \code{os.environ}. +actually preferable to assign to items of \code{os.environ}. \end{funcdesc} \begin{funcdesc}{setegid}{egid} @@ -413,7 +413,7 @@ Availability: \UNIX. \end{funcdesc} \begin{funcdesc}{ftruncate}{fd, length} -Truncate the file corresponding to file descriptor \var{fd}, +Truncate the file corresponding to file descriptor \var{fd}, so that it is at most \var{length} bytes in size. Availability: \UNIX. \end{funcdesc} @@ -909,7 +909,7 @@ will seem to be ignored. \begin{funcdesc}{abort}{} Generate a \constant{SIGABRT} signal to the current process. On -\UNIX, the default behavior is to produce a core dump; on Windows, the +\UNIX, the default behavior is to produce a core dump; on Windows, the process immediately returns an exit code of \code{3}. Be aware that programs which use \function{signal.signal()} to register a handler for \constant{SIGABRT} will behave differently. @@ -1166,12 +1166,14 @@ Availability: \UNIX. \end{funcdesc} \begin{funcdesc}{waitpid}{pid, options} +The details of this function differ on \UNIX and Windows. + +On \UNIX: Wait for completion of a child process given by process id \var{pid}, and return a tuple containing its process id and exit status indication (encoded as for \function{wait()}). The semantics of the call are affected by the value of the integer \var{options}, which should be \code{0} for normal operation. -Availability: \UNIX. If \var{pid} is greater than \code{0}, \function{waitpid()} requests status information for that specific process. If \var{pid} is @@ -1180,6 +1182,19 @@ group of the current process. If \var{pid} is \code{-1}, the request pertains to any child of the current process. If \var{pid} is less than \code{-1}, status is requested for any process in the process group \code{-\var{pid}} (the absolute value of \var{pid}). + +On Windows: +Wait for completion of a process given by process id \var{pid}, +and return a tuple containing \var{pid}, +and its exit status shifted left by 8 bits (shifting makes cross-platform +use of the function easier). +A \var{pid} less than or equal to \code{0} has no special meaning on +Windows, and raises an exception. +The value of integer \var{options} has no effect. +\var{pid} can refer to any process whose id is known, not necessarily a +child process. +The \function{spawn()} functions called with \constant{P_NOWAIT} +return suitable process ids. \end{funcdesc} \begin{datadesc}{WNOHANG} @@ -1211,7 +1226,7 @@ Availability: \UNIX. \begin{funcdesc}{WEXITSTATUS}{status} If \code{WIFEXITED(\var{status})} is true, return the integer -parameter to the \manpage{exit}{2} system call. Otherwise, the return +parameter to the \manpage{exit}{2} system call. Otherwise, the return value is meaningless. Availability: \UNIX. \end{funcdesc} diff --git a/Misc/NEWS b/Misc/NEWS index ee9df99f312..c1510679704 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -59,6 +59,13 @@ Tests Windows +- os.waitpid() is now implemented for Windows, and can be used to block + until a specified process exits. This is similar to, but not exactly + the same as, os.waitpid() on POSIX systems. If you're waiting for + a specific process whose pid was obtained from one of the spawn() + functions, the same Python os.waitpid() code works across platforms. + See the docs for details. + - New tempfile.TemporaryFile implementation for Windows: this doesn't need a TemproraryFileWrapper wrapper anymore, and should be immune to a nasty problem: before 2.3, if you got a temp file on Windows, it diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 77b0d66c09b..40cf5a70e0b 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -78,6 +78,7 @@ corresponding Unix manual entries for more information on calls."; #define HAVE_PIPE 1 #define HAVE_POPEN 1 #define HAVE_SYSTEM 1 +#define HAVE_CWAIT 1 #else /* 16-bit Windows */ #endif /* !MS_WIN32 */ #else /* all other compilers */ @@ -3333,8 +3334,33 @@ posix_waitpid(PyObject *self, PyObject *args) else return Py_BuildValue("ii", pid, status_i); } -#endif /* HAVE_WAITPID */ +#elif defined(HAVE_CWAIT) + +/* MS C has a variant of waitpid() that's usable for most purposes. */ +static char posix_waitpid__doc__[] = +"waitpid(pid, options) -> (pid, status << 8)\n" +"Wait for completion of a given process. options is ignored on Windows."; + +static PyObject * +posix_waitpid(PyObject *self, PyObject *args) +{ + int pid, options; + int status; + + if (!PyArg_ParseTuple(args, "ii:waitpid", &pid, &options)) + return NULL; + Py_BEGIN_ALLOW_THREADS + pid = _cwait(&status, pid, options); + Py_END_ALLOW_THREADS + if (pid == -1) + return posix_error(); + else + /* shift the status left a byte so this is more like the + POSIX waitpid */ + return Py_BuildValue("ii", pid, status << 8); +} +#endif /* HAVE_WAITPID || HAVE_CWAIT */ #ifdef HAVE_WAIT static char posix_wait__doc__[] = @@ -5678,7 +5704,7 @@ static PyMethodDef posix_methods[] = { #ifdef HAVE_WAIT {"wait", posix_wait, METH_VARARGS, posix_wait__doc__}, #endif /* HAVE_WAIT */ -#ifdef HAVE_WAITPID +#if defined(HAVE_WAITPID) || defined(HAVE_CWAIT) {"waitpid", posix_waitpid, METH_VARARGS, posix_waitpid__doc__}, #endif /* HAVE_WAITPID */ #ifdef HAVE_SETSID