]> granicus.if.org Git - python/commitdiff
#6394: Add os.getppid() support for Windows.
authorAmaury Forgeot d'Arc <amauryfa@gmail.com>
Tue, 7 Sep 2010 21:31:17 +0000 (21:31 +0000)
committerAmaury Forgeot d'Arc <amauryfa@gmail.com>
Tue, 7 Sep 2010 21:31:17 +0000 (21:31 +0000)
Doc/library/os.rst
Doc/whatsnew/3.2.rst
Lib/test/test_os.py
Misc/ACKS
Misc/NEWS
Modules/posixmodule.c

index 2e29e4a4672f7b4e63857cbbd0c3e19a70f50e31..9373bda655ef11ba914f483d862bcaad3ac7d636 100644 (file)
@@ -281,10 +281,14 @@ process and user.
 
    .. index:: single: process; id of parent
 
-   Return the parent's process id.
+   Return the parent's process id.  When the parent process has exited, on Unix
+   the id returned is the one of the init process (1), on Windows it is still
+   the same id, which may be already reused by another process.
 
-   Availability: Unix.
+   Availability: Unix, Windows
 
+   .. versionchanged:: 3.2
+      Added support for Windows.
 
 .. function:: getresuid()
 
index 1dd1449d9a40f300322935d85a9511c2a6c0c9f4..ff54bdda9a7c0459f8dd008cd114d7c590d42eff 100644 (file)
@@ -312,6 +312,11 @@ New, Improved, and Deprecated Modules
 
   (Patch by Adam Jackson; :issue:`7647`.)
 
+* :func:`os.getppid` is now supported on Windows.  Note that it will continue to
+  return the same pid even after the parent process has exited.
+
+  (Patch by Jon Anglin; :issue:`6394`.)
+
 * The :func:`shutil.copytree` function has two new options:
 
   * *ignore_dangling_symlinks*: when ``symlinks=False`` so that the function
index 6ce0d5f42c738ffcb58c1267cdc259e3f7b4d864..f42290f4dfdb7805b5b3e9cd6770dff9695294b1 100644 (file)
@@ -1183,6 +1183,17 @@ class FSEncodingTests(unittest.TestCase):
         check('iso-8859-15', b'\xef\xa4', '\xef\u20ac')
 
 
+class PidTests(unittest.TestCase):
+    @unittest.skipUnless(hasattr(os, 'getppid'), "test needs os.getppid")
+    def test_getppid(self):
+        p = subprocess.Popen([sys.executable, '-c',
+                              'import os; print(os.getppid())'],
+                             stdout=subprocess.PIPE)
+        stdout, _ = p.communicate()
+        # We are the parent of our subprocess
+        self.assertEqual(int(stdout), os.getpid())
+
+
 def test_main():
     support.run_unittest(
         FileTests,
@@ -1200,6 +1211,7 @@ def test_main():
         Win32KillTests,
         Win32SymlinkTests,
         FSEncodingTests,
+        PidTests,
     )
 
 if __name__ == "__main__":
index 2c24d2f060c76af635f951c89f83eae41302d0d1..ef67d58d1959b53aab3784da04ceeb39481f3556 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -28,6 +28,7 @@ John Anderson
 Erik Andersén
 Oliver Andrich
 Ross Andrus
+Jon Anglin
 Éric Araujo
 Jason Asbahr
 David Ascher
index c0f2d6edee9da7a1c9b13c09141f8c75311c57f3..f3c5592196abb9c37730107a07513f66662802a8 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -13,6 +13,10 @@ Core and Builtins
 Library
 -------
 
+- Issue #6394: os.getppid() is now supported on Windows.  Note that it will
+  still return the id of the parent process after it has exited.  This process
+  id may even have been reused by another unrelated process.
+
 - Issue #9792: In case of connection failure, socket.create_connection()
   would swallow the exception and raise a new one, making it impossible
   to fetch the original errno, or to filter timeout errors.  Now the
index a83a06bb31f9603ddaa23742e160a079e337b4f8..981132975d6571720f9b26d987e1c7bd4039221a 100644 (file)
@@ -121,6 +121,7 @@ corresponding Unix manual entries for more information on calls.");
 #else
 #ifdef _MSC_VER         /* Microsoft compiler */
 #define HAVE_GETCWD     1
+#define HAVE_GETPPID    1
 #define HAVE_SPAWNV     1
 #define HAVE_EXECV      1
 #define HAVE_PIPE       1
@@ -4363,16 +4364,65 @@ posix_setpgrp(PyObject *self, PyObject *noargs)
 #endif /* HAVE_SETPGRP */
 
 #ifdef HAVE_GETPPID
+
+#ifdef MS_WINDOWS
+#include <tlhelp32.h>
+
+static PyObject*
+win32_getppid()
+{
+    HANDLE snapshot;
+    pid_t mypid;
+    PyObject* result = NULL;
+    BOOL have_record;
+    PROCESSENTRY32 pe;
+
+    mypid = getpid(); /* This function never fails */
+
+    snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+    if (snapshot == INVALID_HANDLE_VALUE)
+        return PyErr_SetFromWindowsErr(GetLastError());
+
+    pe.dwSize = sizeof(pe);
+    have_record = Process32First(snapshot, &pe);
+    while (have_record) {
+        if (mypid == (pid_t)pe.th32ProcessID) {
+            /* We could cache the ulong value in a static variable. */
+            result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
+            break;
+        }
+
+        have_record = Process32Next(snapshot, &pe);
+    }
+
+    /* If our loop exits and our pid was not found (result will be NULL)
+     * then GetLastError will return ERROR_NO_MORE_FILES. This is an
+     * error anyway, so let's raise it. */
+    if (!result)
+        result = PyErr_SetFromWindowsErr(GetLastError());
+
+    CloseHandle(snapshot);
+
+    return result;
+}
+#endif /*MS_WINDOWS*/
+
 PyDoc_STRVAR(posix_getppid__doc__,
 "getppid() -> ppid\n\n\
-Return the parent's process id.");
+Return the parent's process id.  If the parent process has already exited,\n\
+Windows machines will still return its id; others systems will return the id\n\
+of the 'init' process (1).");
 
 static PyObject *
 posix_getppid(PyObject *self, PyObject *noargs)
 {
+#ifdef MS_WINDOWS
+    return win32_getppid();
+#else
     return PyLong_FromPid(getppid());
-}
 #endif
+}
+#endif /* HAVE_GETPPID */
 
 
 #ifdef HAVE_GETLOGIN