Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4b6fdf3

Browse files
committed
#6394: Add os.getppid() support for Windows.
1 parent 8bc0903 commit 4b6fdf3

6 files changed

Lines changed: 80 additions & 4 deletions

File tree

Doc/library/os.rst

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,10 +281,14 @@ process and user.
281281

282282
.. index:: single: process; id of parent
283283

284-
Return the parent's process id.
284+
Return the parent's process id. When the parent process has exited, on Unix
285+
the id returned is the one of the init process (1), on Windows it is still
286+
the same id, which may be already reused by another process.
285287

286-
Availability: Unix.
288+
Availability: Unix, Windows
287289

290+
.. versionchanged:: 3.2
291+
Added support for Windows.
288292

289293
.. function:: getresuid()
290294

Doc/whatsnew/3.2.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,11 @@ New, Improved, and Deprecated Modules
312312

313313
(Patch by Adam Jackson; :issue:`7647`.)
314314

315+
* :func:`os.getppid` is now supported on Windows. Note that it will continue to
316+
return the same pid even after the parent process has exited.
317+
318+
(Patch by Jon Anglin; :issue:`6394`.)
319+
315320
* The :func:`shutil.copytree` function has two new options:
316321

317322
* *ignore_dangling_symlinks*: when ``symlinks=False`` so that the function

Lib/test/test_os.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,6 +1183,17 @@ def check(encoding, bytesfn, unicodefn):
11831183
check('iso-8859-15', b'\xef\xa4', '\xef\u20ac')
11841184

11851185

1186+
class PidTests(unittest.TestCase):
1187+
@unittest.skipUnless(hasattr(os, 'getppid'), "test needs os.getppid")
1188+
def test_getppid(self):
1189+
p = subprocess.Popen([sys.executable, '-c',
1190+
'import os; print(os.getppid())'],
1191+
stdout=subprocess.PIPE)
1192+
stdout, _ = p.communicate()
1193+
# We are the parent of our subprocess
1194+
self.assertEqual(int(stdout), os.getpid())
1195+
1196+
11861197
def test_main():
11871198
support.run_unittest(
11881199
FileTests,
@@ -1200,6 +1211,7 @@ def test_main():
12001211
Win32KillTests,
12011212
Win32SymlinkTests,
12021213
FSEncodingTests,
1214+
PidTests,
12031215
)
12041216

12051217
if __name__ == "__main__":

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ John Anderson
2828
Erik Andersén
2929
Oliver Andrich
3030
Ross Andrus
31+
Jon Anglin
3132
Éric Araujo
3233
Jason Asbahr
3334
David Ascher

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ Core and Builtins
1313
Library
1414
-------
1515

16+
- Issue #6394: os.getppid() is now supported on Windows. Note that it will
17+
still return the id of the parent process after it has exited. This process
18+
id may even have been reused by another unrelated process.
19+
1620
- Issue #9792: In case of connection failure, socket.create_connection()
1721
would swallow the exception and raise a new one, making it impossible
1822
to fetch the original errno, or to filter timeout errors. Now the

Modules/posixmodule.c

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ corresponding Unix manual entries for more information on calls.");
121121
#else
122122
#ifdef _MSC_VER /* Microsoft compiler */
123123
#define HAVE_GETCWD 1
124+
#define HAVE_GETPPID 1
124125
#define HAVE_SPAWNV 1
125126
#define HAVE_EXECV 1
126127
#define HAVE_PIPE 1
@@ -4363,16 +4364,65 @@ posix_setpgrp(PyObject *self, PyObject *noargs)
43634364
#endif /* HAVE_SETPGRP */
43644365

43654366
#ifdef HAVE_GETPPID
4367+
4368+
#ifdef MS_WINDOWS
4369+
#include <tlhelp32.h>
4370+
4371+
static PyObject*
4372+
win32_getppid()
4373+
{
4374+
HANDLE snapshot;
4375+
pid_t mypid;
4376+
PyObject* result = NULL;
4377+
BOOL have_record;
4378+
PROCESSENTRY32 pe;
4379+
4380+
mypid = getpid(); /* This function never fails */
4381+
4382+
snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
4383+
if (snapshot == INVALID_HANDLE_VALUE)
4384+
return PyErr_SetFromWindowsErr(GetLastError());
4385+
4386+
pe.dwSize = sizeof(pe);
4387+
have_record = Process32First(snapshot, &pe);
4388+
while (have_record) {
4389+
if (mypid == (pid_t)pe.th32ProcessID) {
4390+
/* We could cache the ulong value in a static variable. */
4391+
result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
4392+
break;
4393+
}
4394+
4395+
have_record = Process32Next(snapshot, &pe);
4396+
}
4397+
4398+
/* If our loop exits and our pid was not found (result will be NULL)
4399+
* then GetLastError will return ERROR_NO_MORE_FILES. This is an
4400+
* error anyway, so let's raise it. */
4401+
if (!result)
4402+
result = PyErr_SetFromWindowsErr(GetLastError());
4403+
4404+
CloseHandle(snapshot);
4405+
4406+
return result;
4407+
}
4408+
#endif /*MS_WINDOWS*/
4409+
43664410
PyDoc_STRVAR(posix_getppid__doc__,
43674411
"getppid() -> ppid\n\n\
4368-
Return the parent's process id.");
4412+
Return the parent's process id. If the parent process has already exited,\n\
4413+
Windows machines will still return its id; others systems will return the id\n\
4414+
of the 'init' process (1).");
43694415

43704416
static PyObject *
43714417
posix_getppid(PyObject *self, PyObject *noargs)
43724418
{
4419+
#ifdef MS_WINDOWS
4420+
return win32_getppid();
4421+
#else
43734422
return PyLong_FromPid(getppid());
4374-
}
43754423
#endif
4424+
}
4425+
#endif /* HAVE_GETPPID */
43764426

43774427

43784428
#ifdef HAVE_GETLOGIN

0 commit comments

Comments
 (0)