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

Skip to content

gh-116195: Implement win32_getppid_fast #116207

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 91 additions & 2 deletions Modules/posixmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -9115,16 +9115,105 @@ os_setpgrp_impl(PyObject *module)
#ifdef HAVE_GETPPID

#ifdef MS_WINDOWS
#include <processsnapshot.h>
#include <winternl.h>
#include <ProcessSnapshot.h>

// The structure definition in winternl.h may be incomplete.
// This structure is the full version from the MSDN documentation.
typedef struct _PROCESS_BASIC_INFORMATION_FULL {
NTSTATUS ExitStatus;
PVOID PebBaseAddress;
ULONG_PTR AffinityMask;
LONG BasePriority;
ULONG_PTR UniqueProcessId;
ULONG_PTR InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION_FULL;

typedef NTSTATUS (NTAPI *PNT_QUERY_INFORMATION_PROCESS) (
IN HANDLE ProcessHandle,
IN PROCESSINFOCLASS ProcessInformationClass,
OUT PVOID ProcessInformation,
IN ULONG ProcessInformationLength,
OUT PULONG ReturnLength OPTIONAL);

// This function returns the process ID of the parent process.
// Returns 0 on failure.
static ULONG
win32_getppid_fast(void)
{
NTSTATUS Status;
HMODULE Ntdll;
PNT_QUERY_INFORMATION_PROCESS pNtQueryInformationProcess;
PROCESS_BASIC_INFORMATION_FULL BasicInformation;
static ULONG CachedParentProcessId = 0;

if (CachedParentProcessId) {
// No need to query the kernel again.
return CachedParentProcessId;
}

Ntdll = GetModuleHandleW(L"ntdll.dll");
if (!Ntdll) {
return 0;
}

pNtQueryInformationProcess = (PNT_QUERY_INFORMATION_PROCESS) GetProcAddress(Ntdll, "NtQueryInformationProcess");
if (!pNtQueryInformationProcess) {
return 0;
}

Status = pNtQueryInformationProcess(
GetCurrentProcess(),
ProcessBasicInformation,
&BasicInformation,
sizeof(BasicInformation),
NULL);

if (!NT_SUCCESS(Status)) {
return 0;
}

//
// Perform sanity check on the parent process ID we received from NtQueryInformationProcess.
// The check covers values which exceed the 32-bit range (if running on x64) as well as
// zero and (ULONG) -1.
//

if (BasicInformation.InheritedFromUniqueProcessId == 0 ||
BasicInformation.InheritedFromUniqueProcessId >= ULONG_MAX) {

return 0;
}

//
// Now that we have reached this point, the BasicInformation.InheritedFromUniqueProcessId
// structure member contains a ULONG_PTR which represents the process ID of our parent
// process. This process ID will be correctly returned even if the parent process has
// exited or been terminated.
//

CachedParentProcessId = (ULONG) BasicInformation.InheritedFromUniqueProcessId;
return CachedParentProcessId;
}

static PyObject*
win32_getppid(void)
{
DWORD error;
PyObject* result = NULL;
HANDLE process = GetCurrentProcess();

HPSS snapshot = NULL;
ULONG pid;

pid = win32_getppid_fast();
if (pid != 0) {
return PyLong_FromUnsignedLong(pid);
}

//
// If failure occurs in win32_getppid_fast(), fall back to using the PSS API.
//

error = PssCaptureSnapshot(process, PSS_CAPTURE_NONE, 0, &snapshot);
if (error != ERROR_SUCCESS) {
return PyErr_SetFromWindowsErr(error);
Expand Down