static PyObject* pymonotonic(_Py_clock_info_t *info) { #if defined(MS_WINDOWS) static ULONGLONG (*GetTickCount64) (void) = NULL; static ULONGLONG (CALLBACK *Py_GetTickCount64)(void); static int has_getickcount64 = -1; double result; if (has_getickcount64 == -1) { /* GetTickCount64() was added to Windows Vista */ if (winver.dwMajorVersion >= 6) { HINSTANCE hKernel32; hKernel32 = GetModuleHandleW(L"KERNEL32"); *(FARPROC*)&Py_GetTickCount64 = GetProcAddress(hKernel32, "GetTickCount64"); has_getickcount64 = (Py_GetTickCount64 != NULL); } else has_getickcount64 = 0; } if (has_getickcount64) { ULONGLONG ticks; ticks = Py_GetTickCount64(); result = (double)ticks * 1e-3; } else { static DWORD last_ticks = 0; static DWORD n_overflow = 0; DWORD ticks; ticks = GetTickCount(); if (ticks < last_ticks) n_overflow++; last_ticks = ticks; result = ldexp(n_overflow, 32); result += ticks; result *= 1e-3; } if (info) { DWORD timeAdjustment, timeIncrement; BOOL isTimeAdjustmentDisabled, ok; if (has_getickcount64) info->implementation = "GetTickCount64()"; else info->implementation = "GetTickCount()"; info->monotonic = 1; ok = GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, &isTimeAdjustmentDisabled); if (!ok) { PyErr_SetFromWindowsErr(0); return NULL; } info->resolution = timeIncrement * 1e-7; info->adjustable = 0; } return PyFloat_FromDouble(result); #elif defined(__APPLE__) static mach_timebase_info_data_t timebase; uint64_t time; double secs; if (timebase.denom == 0) { /* According to the Technical Q&A QA1398, mach_timebase_info() cannot fail: https://developer.apple.com/library/mac/#qa/qa1398/ */ (void)mach_timebase_info(&timebase); } time = mach_absolute_time(); secs = (double)time * timebase.numer / timebase.denom * 1e-9; if (info) { info->implementation = "mach_absolute_time()"; info->resolution = (double)timebase.numer / timebase.denom * 1e-9; info->monotonic = 1; info->adjustable = 0; } return PyFloat_FromDouble(secs); #elif defined(HAVE_CLOCK_GETTIME) && (defined(CLOCK_HIGHRES) || defined(CLOCK_MONOTONIC)) struct timespec tp; #ifdef CLOCK_HIGHRES const clockid_t clk_id = CLOCK_HIGHRES; const char *function = "clock_gettime(CLOCK_HIGHRES)"; #else const clockid_t clk_id = CLOCK_MONOTONIC; const char *function = "clock_gettime(CLOCK_MONOTONIC)"; #endif if (clock_gettime(clk_id, &tp) != 0) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } if (info) { struct timespec res; info->monotonic = 1; info->implementation = function; info->adjustable = 0; if (clock_getres(clk_id, &res) == 0) info->resolution = res.tv_sec + res.tv_nsec * 1e-9; else info->resolution = 1e-9; } return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); #endif }
static PyObject * mmap_resize_method(mmap_object *self, PyObject *args) { Py_ssize_t new_size; CHECK_VALID(NULL); if (!PyArg_ParseTuple(args, "n:resize", &new_size) || !is_resizeable(self)) { return NULL; #ifdef MS_WINDOWS } else { DWORD dwErrCode = 0; DWORD newSizeLow, newSizeHigh; /* First, unmap the file view */ UnmapViewOfFile(self->data); /* Close the mapping object */ CloseHandle(self->map_handle); /* Move to the desired EOF position */ #if SIZEOF_SIZE_T > 4 newSizeHigh = (DWORD)(new_size >> 32); newSizeLow = (DWORD)(new_size & 0xFFFFFFFF); #else newSizeHigh = 0; newSizeLow = (DWORD)new_size; #endif SetFilePointer(self->file_handle, newSizeLow, &newSizeHigh, FILE_BEGIN); /* Change the size of the file */ SetEndOfFile(self->file_handle); /* Create another mapping object and remap the file view */ self->map_handle = CreateFileMapping( self->file_handle, NULL, PAGE_READWRITE, newSizeHigh, newSizeLow, self->tagname); if (self->map_handle != NULL) { self->data = (char *) MapViewOfFile(self->map_handle, FILE_MAP_WRITE, 0, 0, 0); if (self->data != NULL) { self->size = new_size; Py_INCREF(Py_None); return Py_None; } else { dwErrCode = GetLastError(); } } else { dwErrCode = GetLastError(); } PyErr_SetFromWindowsErr(dwErrCode); return NULL; #endif /* MS_WINDOWS */ #ifdef UNIX #ifndef HAVE_MREMAP } else {
static PyObject* py_process_time(_Py_clock_info_t *info) { #if defined(MS_WINDOWS) HANDLE process; FILETIME creation_time, exit_time, kernel_time, user_time; ULARGE_INTEGER large; double total; BOOL ok; process = GetCurrentProcess(); ok = GetProcessTimes(process, &creation_time, &exit_time, &kernel_time, &user_time); if (!ok) return PyErr_SetFromWindowsErr(0); large.u.LowPart = kernel_time.dwLowDateTime; large.u.HighPart = kernel_time.dwHighDateTime; total = (double)large.QuadPart; large.u.LowPart = user_time.dwLowDateTime; large.u.HighPart = user_time.dwHighDateTime; total += (double)large.QuadPart; if (info) { info->implementation = "GetProcessTimes()"; info->resolution = 1e-7; info->monotonic = 1; info->adjustable = 0; } return PyFloat_FromDouble(total * 1e-7); #else #if defined(HAVE_SYS_RESOURCE_H) struct rusage ru; #endif #ifdef HAVE_TIMES struct tms t; static long ticks_per_second = -1; #endif #if defined(HAVE_CLOCK_GETTIME) \ && (defined(CLOCK_PROCESS_CPUTIME_ID) || defined(CLOCK_PROF)) struct timespec tp; #ifdef CLOCK_PROF const clockid_t clk_id = CLOCK_PROF; const char *function = "clock_gettime(CLOCK_PROF)"; #else const clockid_t clk_id = CLOCK_PROCESS_CPUTIME_ID; const char *function = "clock_gettime(CLOCK_PROCESS_CPUTIME_ID)"; #endif if (clock_gettime(clk_id, &tp) == 0) { if (info) { struct timespec res; info->implementation = function; info->monotonic = 1; info->adjustable = 0; if (clock_getres(clk_id, &res) == 0) info->resolution = res.tv_sec + res.tv_nsec * 1e-9; else info->resolution = 1e-9; } return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9); } #endif #if defined(HAVE_SYS_RESOURCE_H) if (getrusage(RUSAGE_SELF, &ru) == 0) { double total; total = ru.ru_utime.tv_sec + ru.ru_utime.tv_usec * 1e-6; total += ru.ru_stime.tv_sec + ru.ru_stime.tv_usec * 1e-6; if (info) { info->implementation = "getrusage(RUSAGE_SELF)"; info->monotonic = 1; info->adjustable = 0; info->resolution = 1e-6; } return PyFloat_FromDouble(total); } #endif #ifdef HAVE_TIMES if (times(&t) != (clock_t)-1) { double total; if (ticks_per_second == -1) { #if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK) ticks_per_second = sysconf(_SC_CLK_TCK); if (ticks_per_second < 1) ticks_per_second = -1; #elif defined(HZ) ticks_per_second = HZ; #else ticks_per_second = 60; /* magic fallback value; may be bogus */ #endif } if (ticks_per_second != -1) { total = (double)t.tms_utime / ticks_per_second; total += (double)t.tms_stime / ticks_per_second; if (info) { info->implementation = "times()"; info->monotonic = 1; info->adjustable = 0; info->resolution = 1.0 / ticks_per_second; } return PyFloat_FromDouble(total); } } #endif return floatclock(info); #endif }
PyMODINIT_FUNC init_multiprocessing(void) { PyObject *module, *temp, *value; /* Initialize module */ module = Py_InitModule("_multiprocessing", module_methods); if (!module) return; /* Get copy of objects from pickle */ temp = PyImport_ImportModule(PICKLE_MODULE); if (!temp) return; pickle_dumps = PyObject_GetAttrString(temp, "dumps"); pickle_loads = PyObject_GetAttrString(temp, "loads"); pickle_protocol = PyObject_GetAttrString(temp, "HIGHEST_PROTOCOL"); Py_XDECREF(temp); /* Get copy of BufferTooShort */ temp = PyImport_ImportModule("multiprocessing"); if (!temp) return; BufferTooShort = PyObject_GetAttrString(temp, "BufferTooShort"); Py_XDECREF(temp); /* Add connection type to module */ if (PyType_Ready(&ConnectionType) < 0) return; Py_INCREF(&ConnectionType); PyModule_AddObject(module, "Connection", (PyObject*)&ConnectionType); #if defined(MS_WINDOWS) || \ (defined(HAVE_SEM_OPEN) && !defined(POSIX_SEMAPHORES_NOT_ENABLED)) /* Add SemLock type to module */ if (PyType_Ready(&SemLockType) < 0) return; Py_INCREF(&SemLockType); { PyObject *py_sem_value_max; /* Some systems define SEM_VALUE_MAX as an unsigned value that * causes it to be negative when used as an int (NetBSD). */ if ((int)(SEM_VALUE_MAX) < 0) py_sem_value_max = PyLong_FromLong(INT_MAX); else py_sem_value_max = PyLong_FromLong(SEM_VALUE_MAX); if (py_sem_value_max == NULL) return; PyDict_SetItemString(SemLockType.tp_dict, "SEM_VALUE_MAX", py_sem_value_max); } PyModule_AddObject(module, "SemLock", (PyObject*)&SemLockType); #endif #ifdef MS_WINDOWS /* Add PipeConnection to module */ if (PyType_Ready(&PipeConnectionType) < 0) return; Py_INCREF(&PipeConnectionType); PyModule_AddObject(module, "PipeConnection", (PyObject*)&PipeConnectionType); /* Initialize win32 class and add to multiprocessing */ temp = create_win32_namespace(); if (!temp) return; PyModule_AddObject(module, "win32", temp); /* Initialize the event handle used to signal Ctrl-C */ sigint_event = CreateEvent(NULL, TRUE, FALSE, NULL); if (!sigint_event) { PyErr_SetFromWindowsErr(0); return; } if (!SetConsoleCtrlHandler(ProcessingCtrlHandler, TRUE)) { PyErr_SetFromWindowsErr(0); return; } #endif /* Add configuration macros */ temp = PyDict_New(); if (!temp) return; #define ADD_FLAG(name) \ value = Py_BuildValue("i", name); \ if (value == NULL) { Py_DECREF(temp); return; } \ if (PyDict_SetItemString(temp, #name, value) < 0) { \ Py_DECREF(temp); Py_DECREF(value); return; } \ Py_DECREF(value) #if defined(HAVE_SEM_OPEN) && !defined(POSIX_SEMAPHORES_NOT_ENABLED) ADD_FLAG(HAVE_SEM_OPEN); #endif #ifdef HAVE_SEM_TIMEDWAIT ADD_FLAG(HAVE_SEM_TIMEDWAIT); #endif #ifdef HAVE_FD_TRANSFER ADD_FLAG(HAVE_FD_TRANSFER); #endif #ifdef HAVE_BROKEN_SEM_GETVALUE ADD_FLAG(HAVE_BROKEN_SEM_GETVALUE); #endif #ifdef HAVE_BROKEN_SEM_UNLINK ADD_FLAG(HAVE_BROKEN_SEM_UNLINK); #endif if (PyModule_AddObject(module, "flags", temp) < 0) return; }
/* * returns a Python list representing the arguments for the process * with given pid or NULL on error. */ PyObject * psutil_get_arg_list(long pid) { int nArgs, i; LPWSTR *szArglist = NULL; HANDLE hProcess = NULL; PVOID pebAddress; PVOID rtlUserProcParamsAddress; UNICODE_STRING commandLine; WCHAR *commandLineContents = NULL; PyObject *arg = NULL; PyObject *arg_from_wchar = NULL; PyObject *argList = NULL; hProcess = psutil_handle_from_pid(pid); if (hProcess == NULL) { return NULL; } pebAddress = psutil_get_peb_address(hProcess); // get the address of ProcessParameters #ifdef _WIN64 if (!ReadProcessMemory(hProcess, (PCHAR)pebAddress + 32, &rtlUserProcParamsAddress, sizeof(PVOID), NULL)) #else if (!ReadProcessMemory(hProcess, (PCHAR)pebAddress + 0x10, &rtlUserProcParamsAddress, sizeof(PVOID), NULL)) #endif { ////printf("Could not read the address of ProcessParameters!\n"); PyErr_SetFromWindowsErr(0); goto error; } // read the CommandLine UNICODE_STRING structure #ifdef _WIN64 if (!ReadProcessMemory(hProcess, (PCHAR)rtlUserProcParamsAddress + 112, &commandLine, sizeof(commandLine), NULL)) #else if (!ReadProcessMemory(hProcess, (PCHAR)rtlUserProcParamsAddress + 0x40, &commandLine, sizeof(commandLine), NULL)) #endif { PyErr_SetFromWindowsErr(0); goto error; } // allocate memory to hold the command line commandLineContents = (WCHAR *)malloc(commandLine.Length + 1); if (commandLineContents == NULL) { PyErr_NoMemory(); goto error; } // read the command line if (!ReadProcessMemory(hProcess, commandLine.Buffer, commandLineContents, commandLine.Length, NULL)) { PyErr_SetFromWindowsErr(0); goto error; } // Null-terminate the string to prevent wcslen from returning // incorrect length the length specifier is in characters, but // commandLine.Length is in bytes. commandLineContents[(commandLine.Length / sizeof(WCHAR))] = '\0'; // attempt tp parse the command line using Win32 API, fall back // on string cmdline version otherwise szArglist = CommandLineToArgvW(commandLineContents, &nArgs); if (NULL == szArglist) { // failed to parse arglist // encode as a UTF8 Python string object from WCHAR string arg_from_wchar = PyUnicode_FromWideChar(commandLineContents, commandLine.Length / 2); if (arg_from_wchar == NULL) goto error; #if PY_MAJOR_VERSION >= 3 argList = Py_BuildValue("N", PyUnicode_AsUTF8String(arg_from_wchar)); #else argList = Py_BuildValue("N", PyUnicode_FromObject(arg_from_wchar)); #endif if (!argList) goto error; } else { // arglist parsed as array of UNICODE_STRING, so convert each to // Python string object and add to arg list argList = Py_BuildValue("[]"); if (argList == NULL) goto error; for (i = 0; i < nArgs; i++) { arg_from_wchar = NULL; arg = NULL; arg_from_wchar = PyUnicode_FromWideChar(szArglist[i], wcslen(szArglist[i])); if (arg_from_wchar == NULL) goto error; #if PY_MAJOR_VERSION >= 3 arg = PyUnicode_FromObject(arg_from_wchar); #else arg = PyUnicode_AsUTF8String(arg_from_wchar); #endif if (arg == NULL) goto error; Py_XDECREF(arg_from_wchar); if (PyList_Append(argList, arg)) goto error; Py_XDECREF(arg); } } if (szArglist != NULL) LocalFree(szArglist); free(commandLineContents); CloseHandle(hProcess); return argList; error: Py_XDECREF(arg); Py_XDECREF(arg_from_wchar); Py_XDECREF(argList); if (hProcess != NULL) CloseHandle(hProcess); if (commandLineContents != NULL) free(commandLineContents); if (szArglist != NULL) LocalFree(szArglist); return NULL; }
static void SetException(DWORD code, EXCEPTION_RECORD *pr) { /* The 'code' is a normal win32 error code so it could be handled by PyErr_SetFromWindowsErr(). However, for some errors, we have additional information not included in the error code. We handle those here and delegate all others to the generic function. */ switch (code) { case EXCEPTION_ACCESS_VIOLATION: /* The thread attempted to read from or write to a virtual address for which it does not have the appropriate access. */ if (pr->ExceptionInformation[0] == 0) PyErr_Format(PyExc_WindowsError, "exception: access violation reading %p", pr->ExceptionInformation[1]); else PyErr_Format(PyExc_WindowsError, "exception: access violation writing %p", pr->ExceptionInformation[1]); break; case EXCEPTION_BREAKPOINT: /* A breakpoint was encountered. */ PyErr_SetString(PyExc_WindowsError, "exception: breakpoint encountered"); break; case EXCEPTION_DATATYPE_MISALIGNMENT: /* The thread attempted to read or write data that is misaligned on hardware that does not provide alignment. For example, 16-bit values must be aligned on 2-byte boundaries, 32-bit values on 4-byte boundaries, and so on. */ PyErr_SetString(PyExc_WindowsError, "exception: datatype misalignment"); break; case EXCEPTION_SINGLE_STEP: /* A trace trap or other single-instruction mechanism signaled that one instruction has been executed. */ PyErr_SetString(PyExc_WindowsError, "exception: single step"); break; case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: /* The thread attempted to access an array element that is out of bounds, and the underlying hardware supports bounds checking. */ PyErr_SetString(PyExc_WindowsError, "exception: array bounds exceeded"); break; case EXCEPTION_FLT_DENORMAL_OPERAND: /* One of the operands in a floating-point operation is denormal. A denormal value is one that is too small to represent as a standard floating-point value. */ PyErr_SetString(PyExc_WindowsError, "exception: floating-point operand denormal"); break; case EXCEPTION_FLT_DIVIDE_BY_ZERO: /* The thread attempted to divide a floating-point value by a floating-point divisor of zero. */ PyErr_SetString(PyExc_WindowsError, "exception: float divide by zero"); break; case EXCEPTION_FLT_INEXACT_RESULT: /* The result of a floating-point operation cannot be represented exactly as a decimal fraction. */ PyErr_SetString(PyExc_WindowsError, "exception: float inexact"); break; case EXCEPTION_FLT_INVALID_OPERATION: /* This exception represents any floating-point exception not included in this list. */ PyErr_SetString(PyExc_WindowsError, "exception: float invalid operation"); break; case EXCEPTION_FLT_OVERFLOW: /* The exponent of a floating-point operation is greater than the magnitude allowed by the corresponding type. */ PyErr_SetString(PyExc_WindowsError, "exception: float overflow"); break; case EXCEPTION_FLT_STACK_CHECK: /* The stack overflowed or underflowed as the result of a floating-point operation. */ PyErr_SetString(PyExc_WindowsError, "exception: stack over/underflow"); break; case EXCEPTION_STACK_OVERFLOW: /* The stack overflowed or underflowed as the result of a floating-point operation. */ PyErr_SetString(PyExc_WindowsError, "exception: stack overflow"); break; case EXCEPTION_FLT_UNDERFLOW: /* The exponent of a floating-point operation is less than the magnitude allowed by the corresponding type. */ PyErr_SetString(PyExc_WindowsError, "exception: float underflow"); break; case EXCEPTION_INT_DIVIDE_BY_ZERO: /* The thread attempted to divide an integer value by an integer divisor of zero. */ PyErr_SetString(PyExc_WindowsError, "exception: integer divide by zero"); break; case EXCEPTION_INT_OVERFLOW: /* The result of an integer operation caused a carry out of the most significant bit of the result. */ PyErr_SetString(PyExc_WindowsError, "exception: integer overflow"); break; case EXCEPTION_PRIV_INSTRUCTION: /* The thread attempted to execute an instruction whose operation is not allowed in the current machine mode. */ PyErr_SetString(PyExc_WindowsError, "exception: priviledged instruction"); break; case EXCEPTION_NONCONTINUABLE_EXCEPTION: /* The thread attempted to continue execution after a noncontinuable exception occurred. */ PyErr_SetString(PyExc_WindowsError, "exception: nocontinuable"); break; default: PyErr_SetFromWindowsErr(code); break; } }
static PyObject * mmap_resize_method(mmap_object *self, PyObject *args) { Py_ssize_t new_size; CHECK_VALID(NULL); if (!PyArg_ParseTuple(args, "n:resize", &new_size) || !is_resizeable(self)) { return NULL; } if (new_size < 0 || PY_SSIZE_T_MAX - new_size < self->offset) { PyErr_SetString(PyExc_ValueError, "new size out of range"); return NULL; } { #ifdef MS_WINDOWS DWORD dwErrCode = 0; DWORD off_hi, off_lo, newSizeLow, newSizeHigh; /* First, unmap the file view */ UnmapViewOfFile(self->data); self->data = NULL; /* Close the mapping object */ CloseHandle(self->map_handle); self->map_handle = NULL; /* Move to the desired EOF position */ newSizeHigh = (DWORD)((self->offset + new_size) >> 32); newSizeLow = (DWORD)((self->offset + new_size) & 0xFFFFFFFF); off_hi = (DWORD)(self->offset >> 32); off_lo = (DWORD)(self->offset & 0xFFFFFFFF); SetFilePointer(self->file_handle, newSizeLow, &newSizeHigh, FILE_BEGIN); /* Change the size of the file */ SetEndOfFile(self->file_handle); /* Create another mapping object and remap the file view */ self->map_handle = CreateFileMapping( self->file_handle, NULL, PAGE_READWRITE, 0, 0, self->tagname); if (self->map_handle != NULL) { self->data = (char *) MapViewOfFile(self->map_handle, FILE_MAP_WRITE, off_hi, off_lo, new_size); if (self->data != NULL) { self->size = new_size; Py_INCREF(Py_None); return Py_None; } else { dwErrCode = GetLastError(); CloseHandle(self->map_handle); self->map_handle = NULL; } } else { dwErrCode = GetLastError(); } PyErr_SetFromWindowsErr(dwErrCode); return NULL; #endif /* MS_WINDOWS */ #ifdef UNIX #ifndef HAVE_MREMAP PyErr_SetString(PyExc_SystemError, "mmap: resizing not available--no mremap()"); return NULL; #else void *newmap; if (self->fd != -1 && ftruncate(self->fd, self->offset + new_size) == -1) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } #ifdef MREMAP_MAYMOVE newmap = mremap(self->data, self->size, new_size, MREMAP_MAYMOVE); #else #if defined(__NetBSD__) newmap = mremap(self->data, self->size, self->data, new_size, 0); #else newmap = mremap(self->data, self->size, new_size, 0); #endif /* __NetBSD__ */ #endif if (newmap == (void *)-1) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } self->data = newmap; self->size = new_size; Py_INCREF(Py_None); return Py_None; #endif /* HAVE_MREMAP */ #endif /* UNIX */ } }
static int set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works) { #ifdef MS_WINDOWS HANDLE handle; DWORD flags; #else #if defined(HAVE_SYS_IOCTL_H) && defined(FIOCLEX) && defined(FIONCLEX) static int ioctl_works = -1; int request; int err; #endif int flags, new_flags; int res; #endif /* atomic_flag_works can only be used to make the file descriptor non-inheritable */ assert(!(atomic_flag_works != NULL && inheritable)); if (atomic_flag_works != NULL && !inheritable) { if (*atomic_flag_works == -1) { int isInheritable = get_inheritable(fd, raise); if (isInheritable == -1) return -1; *atomic_flag_works = !isInheritable; } if (*atomic_flag_works) return 0; } #ifdef MS_WINDOWS _Py_BEGIN_SUPPRESS_IPH handle = (HANDLE)_get_osfhandle(fd); _Py_END_SUPPRESS_IPH if (handle == INVALID_HANDLE_VALUE) { if (raise) PyErr_SetFromErrno(PyExc_OSError); return -1; } if (inheritable) flags = HANDLE_FLAG_INHERIT; else flags = 0; if (!SetHandleInformation(handle, HANDLE_FLAG_INHERIT, flags)) { if (raise) PyErr_SetFromWindowsErr(0); return -1; } return 0; #else #if defined(HAVE_SYS_IOCTL_H) && defined(FIOCLEX) && defined(FIONCLEX) if (ioctl_works != 0) { /* fast-path: ioctl() only requires one syscall */ if (inheritable) request = FIONCLEX; else request = FIOCLEX; err = ioctl(fd, request, NULL); if (!err) { ioctl_works = 1; return 0; } if (errno != ENOTTY && errno != EACCES) { if (raise) PyErr_SetFromErrno(PyExc_OSError); return -1; } else { /* Issue #22258: Here, ENOTTY means "Inappropriate ioctl for device". The ioctl is declared but not supported by the kernel. Remember that ioctl() doesn't work. It is the case on Illumos-based OS for example. Issue #27057: When SELinux policy disallows ioctl it will fail with EACCES. While FIOCLEX is safe operation it may be unavailable because ioctl was denied altogether. This can be the case on Android. */ ioctl_works = 0; } /* fallback to fcntl() if ioctl() does not work */ } #endif /* slow-path: fcntl() requires two syscalls */ flags = fcntl(fd, F_GETFD); if (flags < 0) { if (raise) PyErr_SetFromErrno(PyExc_OSError); return -1; } if (inheritable) { new_flags = flags & ~FD_CLOEXEC; } else { new_flags = flags | FD_CLOEXEC; } if (new_flags == flags) { /* FD_CLOEXEC flag already set/cleared: nothing to do */ return 0; } res = fcntl(fd, F_SETFD, new_flags); if (res < 0) { if (raise) PyErr_SetFromErrno(PyExc_OSError); return -1; } return 0; #endif }
static PyObject * semlock_acquire(SemLockObject *self, PyObject *args, PyObject *kwds) { int blocking = 1; double timeout; PyObject *timeout_obj = Py_None; DWORD res, full_msecs, msecs, start, ticks; static char *kwlist[] = {"block", "timeout", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iO", kwlist, &blocking, &timeout_obj)) return NULL; /* calculate timeout */ if (!blocking) { full_msecs = 0; } else if (timeout_obj == Py_None) { full_msecs = INFINITE; } else { timeout = PyFloat_AsDouble(timeout_obj); if (PyErr_Occurred()) return NULL; timeout *= 1000.0; /* convert to millisecs */ if (timeout < 0.0) { timeout = 0.0; } else if (timeout >= 0.5 * INFINITE) { /* 25 days */ PyErr_SetString(PyExc_OverflowError, "timeout is too large"); return NULL; } full_msecs = (DWORD)(timeout + 0.5); } /* check whether we already own the lock */ if (self->kind == RECURSIVE_MUTEX && ISMINE(self)) { ++self->count; Py_RETURN_TRUE; } /* check whether we can acquire without blocking */ if (WaitForSingleObject(self->handle, 0) == WAIT_OBJECT_0) { self->last_tid = GetCurrentThreadId(); ++self->count; Py_RETURN_TRUE; } msecs = full_msecs; start = GetTickCount(); for ( ; ; ) { HANDLE handles[2] = {self->handle, sigint_event}; /* do the wait */ Py_BEGIN_ALLOW_THREADS ResetEvent(sigint_event); res = WaitForMultipleObjects(2, handles, FALSE, msecs); Py_END_ALLOW_THREADS /* handle result */ if (res != WAIT_OBJECT_0 + 1) break; /* got SIGINT so give signal handler a chance to run */ Sleep(1); /* if this is main thread let KeyboardInterrupt be raised */ if (PyErr_CheckSignals()) return NULL; /* recalculate timeout */ if (msecs != INFINITE) { ticks = GetTickCount(); if ((DWORD)(ticks - start) >= full_msecs) Py_RETURN_FALSE; msecs = full_msecs - (ticks - start); } } /* handle result */ switch (res) { case WAIT_TIMEOUT: Py_RETURN_FALSE; case WAIT_OBJECT_0: self->last_tid = GetCurrentThreadId(); ++self->count; Py_RETURN_TRUE; case WAIT_FAILED: return PyErr_SetFromWindowsErr(0); default: PyErr_Format(PyExc_RuntimeError, "WaitForSingleObject() or " "WaitForMultipleObjects() gave unrecognized " "value %d", res); return NULL; } }
/* Returns: * 1: pid exists * 0: it doesn't * -1: error */ int psutil_pid_is_running(DWORD pid) { HANDLE hProcess; DWORD exitCode; DWORD err; // Special case for PID 0 System Idle Process if (pid == 0) return 1; if (pid < 0) return 0; hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); if (NULL == hProcess) { err = GetLastError(); // Yeah, this is the actual error code in case of "no such process". if (err == ERROR_INVALID_PARAMETER) { if (! psutil_assert_pid_not_exists( pid, "pir: OpenProcess() -> INVALID_PARAMETER")) { return -1; } return 0; } // Access denied obviously means there's a process to deny access to. else if (err == ERROR_ACCESS_DENIED) { if (! psutil_assert_pid_exists( pid, "pir: OpenProcess() ACCESS_DENIED")) { return -1; } return 1; } // Be strict and raise an exception; the caller is supposed // to take -1 into account. else { PyErr_SetFromWindowsErr(err); return -1; } } if (GetExitCodeProcess(hProcess, &exitCode)) { CloseHandle(hProcess); // XXX - maybe STILL_ACTIVE is not fully reliable as per: // http://stackoverflow.com/questions/1591342/#comment47830782_1591379 if (exitCode == STILL_ACTIVE) { if (! psutil_assert_pid_exists( pid, "pir: GetExitCodeProcess() -> STILL_ACTIVE")) { return -1; } return 1; } // We can't be sure so we look into pids. else { return psutil_pid_in_pids(pid); } } else { err = GetLastError(); CloseHandle(hProcess); // Same as for OpenProcess, assume access denied means there's // a process to deny access to. if (err == ERROR_ACCESS_DENIED) { if (! psutil_assert_pid_exists( pid, "pir: GetExitCodeProcess() -> ERROR_ACCESS_DENIED")) { return -1; } return 1; } else { PyErr_SetFromWindowsErr(0); return -1; } } }
/* Get data from the process with the given pid. The data is returned in the pdata output member as a nul terminated string which must be freed on success. On success 0 is returned. On error the output parameter is not touched, -1 is returned, and an appropriate Python exception is set. */ static int psutil_get_process_data(long pid, enum psutil_process_data_kind kind, WCHAR **pdata, SIZE_T *psize) { /* This function is quite complex because there are several cases to be considered: Two cases are really simple: we (i.e. the python interpreter) and the target process are both 32 bit or both 64 bit. In that case the memory layout of the structures matches up and all is well. When we are 64 bit and the target process is 32 bit we need to use custom 32 bit versions of the structures. When we are 32 bit and the target process is 64 bit we need to use custom 64 bit version of the structures. Also we need to use separate Wow64 functions to get the information. A few helper structs are defined above so that the compiler can handle calculating the correct offsets. Additional help also came from the following sources: https://github.com/kohsuke/winp and http://wj32.org/wp/2009/01/24/howto-get-the-command-line-of-processes/ http://stackoverflow.com/a/14012919 http://www.drdobbs.com/embracing-64-bit-windows/184401966 */ static _NtQueryInformationProcess NtQueryInformationProcess = NULL; #ifndef _WIN64 static _NtQueryInformationProcess NtWow64QueryInformationProcess64 = NULL; static _NtWow64ReadVirtualMemory64 NtWow64ReadVirtualMemory64 = NULL; #endif HANDLE hProcess = NULL; LPCVOID src; SIZE_T size; WCHAR *buffer = NULL; #ifdef _WIN64 LPVOID ppeb32 = NULL; #else PVOID64 src64; BOOL weAreWow64; BOOL theyAreWow64; #endif hProcess = psutil_handle_from_pid(pid); if (hProcess == NULL) return -1; if (NtQueryInformationProcess == NULL) { NtQueryInformationProcess = (_NtQueryInformationProcess)GetProcAddress( GetModuleHandleA("ntdll.dll"), "NtQueryInformationProcess"); } #ifdef _WIN64 /* 64 bit case. Check if the target is a 32 bit process running in WoW64 * mode. */ if (!NT_SUCCESS(NtQueryInformationProcess(hProcess, ProcessWow64Information, &ppeb32, sizeof(LPVOID), NULL))) { PyErr_SetFromWindowsErr(0); goto error; } if (ppeb32 != NULL) { /* We are 64 bit. Target process is 32 bit running in WoW64 mode. */ PEB32 peb32; RTL_USER_PROCESS_PARAMETERS32 procParameters32; // read PEB if (!ReadProcessMemory(hProcess, ppeb32, &peb32, sizeof(peb32), NULL)) { PyErr_SetFromWindowsErr(0); goto error; } // read process parameters if (!ReadProcessMemory(hProcess, UlongToPtr(peb32.ProcessParameters), &procParameters32, sizeof(procParameters32), NULL)) { PyErr_SetFromWindowsErr(0); goto error; } switch (kind) { case KIND_CMDLINE: src = UlongToPtr(procParameters32.CommandLine.Buffer), size = procParameters32.CommandLine.Length; break; case KIND_CWD: src = UlongToPtr(procParameters32.CurrentDirectoryPath.Buffer); size = procParameters32.CurrentDirectoryPath.Length; break; case KIND_ENVIRON: src = UlongToPtr(procParameters32.env); break; } } else #else /* 32 bit case. Check if the target is also 32 bit. */ if (!IsWow64Process(GetCurrentProcess(), &weAreWow64) || !IsWow64Process(hProcess, &theyAreWow64)) { PyErr_SetFromWindowsErr(0); goto error; } if (weAreWow64 && !theyAreWow64) { /* We are 32 bit running in WoW64 mode. Target process is 64 bit. */ PROCESS_BASIC_INFORMATION64 pbi64; PEB64 peb64; RTL_USER_PROCESS_PARAMETERS64 procParameters64; if (NtWow64QueryInformationProcess64 == NULL) { NtWow64QueryInformationProcess64 = (_NtQueryInformationProcess)GetProcAddress( GetModuleHandleA("ntdll.dll"), "NtWow64QueryInformationProcess64"); if (NtWow64QueryInformationProcess64 == NULL) { PyErr_SetString(PyExc_NotImplementedError, "NtWow64QueryInformationProcess64 missing"); goto error; } } if (!NT_SUCCESS(NtWow64QueryInformationProcess64( hProcess, ProcessBasicInformation, &pbi64, sizeof(pbi64), NULL))) { PyErr_SetFromWindowsErr(0); goto error; } // read peb if (NtWow64ReadVirtualMemory64 == NULL) { NtWow64ReadVirtualMemory64 = (_NtWow64ReadVirtualMemory64)GetProcAddress( GetModuleHandleA("ntdll.dll"), "NtWow64ReadVirtualMemory64"); if (NtWow64ReadVirtualMemory64 == NULL) { PyErr_SetString(PyExc_NotImplementedError, "NtWow64ReadVirtualMemory64 missing"); goto error; } } if (!NT_SUCCESS(NtWow64ReadVirtualMemory64(hProcess, pbi64.PebBaseAddress, &peb64, sizeof(peb64), NULL))) { PyErr_SetFromWindowsErr(0); goto error; } // read process parameters if (!NT_SUCCESS(NtWow64ReadVirtualMemory64(hProcess, peb64.ProcessParameters, &procParameters64, sizeof(procParameters64), NULL))) { PyErr_SetFromWindowsErr(0); goto error; } switch (kind) { case KIND_CMDLINE: src64 = procParameters64.CommandLine.Buffer; size = procParameters64.CommandLine.Length; break; case KIND_CWD: src64 = procParameters64.CurrentDirectoryPath.Buffer, size = procParameters64.CurrentDirectoryPath.Length; break; case KIND_ENVIRON: src64 = procParameters64.env; break; } } else #endif /* Target process is of the same bitness as us. */ { PROCESS_BASIC_INFORMATION pbi; PEB_ peb; RTL_USER_PROCESS_PARAMETERS_ procParameters; if (!NT_SUCCESS(NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), NULL))) { PyErr_SetFromWindowsErr(0); goto error; } // read peb if (!ReadProcessMemory(hProcess, pbi.PebBaseAddress, &peb, sizeof(peb), NULL)) { PyErr_SetFromWindowsErr(0); goto error; } // read process parameters if (!ReadProcessMemory(hProcess, peb.ProcessParameters, &procParameters, sizeof(procParameters), NULL)) { PyErr_SetFromWindowsErr(0); goto error; } switch (kind) { case KIND_CMDLINE: src = procParameters.CommandLine.Buffer; size = procParameters.CommandLine.Length; break; case KIND_CWD: src = procParameters.CurrentDirectoryPath.Buffer; size = procParameters.CurrentDirectoryPath.Length; break; case KIND_ENVIRON: src = procParameters.env; break; } } if (kind == KIND_ENVIRON) { #ifndef _WIN64 if (weAreWow64 && !theyAreWow64) { ULONG64 size64; if (psutil_get_process_region_size64(hProcess, src64, &size64) != 0) goto error; size = (SIZE_T)size64; } else #endif if (psutil_get_process_region_size(hProcess, src, &size) != 0) goto error; } buffer = calloc(size + 2, 1); if (buffer == NULL) { PyErr_NoMemory(); goto error; } #ifndef _WIN64 if (weAreWow64 && !theyAreWow64) { if (!NT_SUCCESS(NtWow64ReadVirtualMemory64(hProcess, src64, buffer, size, NULL))) { PyErr_SetFromWindowsErr(0); goto error; } } else #endif if (!ReadProcessMemory(hProcess, src, buffer, size, NULL)) { PyErr_SetFromWindowsErr(0); goto error; } CloseHandle(hProcess); *pdata = buffer; *psize = size; return 0; error: if (hProcess != NULL) CloseHandle(hProcess); if (buffer != NULL) free(buffer); return -1; }
static PyObject * semlock_acquire(SemLockObject *self, PyObject *args, PyObject *kwds) { int blocking = 1; double timeout; PyObject *timeout_obj = Py_None; DWORD res, full_msecs, nhandles; HANDLE handles[2], sigint_event; static char *kwlist[] = {"block", "timeout", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iO", kwlist, &blocking, &timeout_obj)) return NULL; /* calculate timeout */ if (!blocking) { full_msecs = 0; } else if (timeout_obj == Py_None) { full_msecs = INFINITE; } else { timeout = PyFloat_AsDouble(timeout_obj); if (PyErr_Occurred()) return NULL; timeout *= 1000.0; /* convert to millisecs */ if (timeout < 0.0) { timeout = 0.0; } else if (timeout >= 0.5 * INFINITE) { /* 25 days */ PyErr_SetString(PyExc_OverflowError, "timeout is too large"); return NULL; } full_msecs = (DWORD)(timeout + 0.5); } /* check whether we already own the lock */ if (self->kind == RECURSIVE_MUTEX && ISMINE(self)) { ++self->count; Py_RETURN_TRUE; } /* check whether we can acquire without releasing the GIL and blocking */ if (WaitForSingleObjectEx(self->handle, 0, FALSE) == WAIT_OBJECT_0) { self->last_tid = GetCurrentThreadId(); ++self->count; Py_RETURN_TRUE; } /* prepare list of handles */ nhandles = 0; handles[nhandles++] = self->handle; if (_PyOS_IsMainThread()) { sigint_event = _PyOS_SigintEvent(); assert(sigint_event != NULL); handles[nhandles++] = sigint_event; } /* do the wait */ Py_BEGIN_ALLOW_THREADS if (sigint_event != NULL) ResetEvent(sigint_event); res = WaitForMultipleObjectsEx(nhandles, handles, FALSE, full_msecs, FALSE); Py_END_ALLOW_THREADS /* handle result */ switch (res) { case WAIT_TIMEOUT: Py_RETURN_FALSE; case WAIT_OBJECT_0 + 0: self->last_tid = GetCurrentThreadId(); ++self->count; Py_RETURN_TRUE; case WAIT_OBJECT_0 + 1: errno = EINTR; return PyErr_SetFromErrno(PyExc_IOError); case WAIT_FAILED: return PyErr_SetFromWindowsErr(0); default: PyErr_Format(PyExc_RuntimeError, "WaitForSingleObject() or " "WaitForMultipleObjects() gave unrecognized " "value %d", res); return NULL; } }
/* * Enumerate all services. */ PyObject * psutil_winservice_enumerate(PyObject *self, PyObject *args) { ENUM_SERVICE_STATUS_PROCESS *lpService = NULL; BOOL ok; SC_HANDLE sc = NULL; DWORD bytesNeeded = 0; DWORD srvCount; DWORD resumeHandle = 0; DWORD dwBytes = 0; DWORD i; PyObject *py_retlist = PyList_New(0); PyObject *py_tuple = NULL; PyObject *py_unicode_display_name = NULL; if (py_retlist == NULL) return NULL; sc = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE); if (sc == NULL) { PyErr_SetFromWindowsErr(0); return NULL; } for (;;) { ok = EnumServicesStatusEx( sc, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, // XXX - extend this to include drivers etc.? SERVICE_STATE_ALL, (LPBYTE)lpService, dwBytes, &bytesNeeded, &srvCount, &resumeHandle, NULL); if (ok || (GetLastError() != ERROR_MORE_DATA)) break; if (lpService) free(lpService); dwBytes = bytesNeeded; lpService = (ENUM_SERVICE_STATUS_PROCESS*)malloc(dwBytes); } for (i = 0; i < srvCount; i++) { // Get unicode display name. py_unicode_display_name = NULL; py_unicode_display_name = PyUnicode_Decode( lpService[i].lpDisplayName, _tcslen(lpService[i].lpDisplayName), Py_FileSystemDefaultEncoding, "replace"); if (py_unicode_display_name == NULL) goto error; // Construct the result. py_tuple = Py_BuildValue( "(sO)", lpService[i].lpServiceName, // name py_unicode_display_name // display_name ); if (py_tuple == NULL) goto error; if (PyList_Append(py_retlist, py_tuple)) goto error; Py_DECREF(py_unicode_display_name); Py_DECREF(py_tuple); } // Free resources. CloseServiceHandle(sc); free(lpService); return py_retlist; error: Py_XDECREF(py_unicode_display_name); Py_XDECREF(py_tuple); Py_DECREF(py_retlist); if (sc != NULL) CloseServiceHandle(sc); if (lpService != NULL) free(lpService); return NULL; }
/* * Get service status information. Returns: * - status * - pid */ PyObject * psutil_winservice_query_status(PyObject *self, PyObject *args) { char *service_name; SC_HANDLE hService = NULL; BOOL ok; DWORD bytesNeeded = 0; DWORD resumeHandle = 0; DWORD dwBytes = 0; SERVICE_STATUS_PROCESS *ssp = NULL; PyObject *py_tuple = NULL; if (!PyArg_ParseTuple(args, "s", &service_name)) return NULL; hService = psutil_get_service_handler( service_name, SC_MANAGER_ENUMERATE_SERVICE, SERVICE_QUERY_STATUS); if (hService == NULL) goto error; // First call to QueryServiceStatusEx() is necessary to get the // right size. QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, NULL, 0, &bytesNeeded); if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { PyErr_SetFromWindowsErr(0); goto error; } ssp = (SERVICE_STATUS_PROCESS *)HeapAlloc( GetProcessHeap(), 0, bytesNeeded); if (ssp == NULL) { PyErr_NoMemory(); goto error; } // Actual call. ok = QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)ssp, bytesNeeded, &bytesNeeded); if (ok == 0) { PyErr_SetFromWindowsErr(0); goto error; } py_tuple = Py_BuildValue( "(sk)", get_state_string(ssp->dwCurrentState), ssp->dwProcessId ); if (py_tuple == NULL) goto error; CloseServiceHandle(hService); HeapFree(GetProcessHeap(), 0, ssp); return py_tuple; error: Py_XDECREF(py_tuple); if (hService != NULL) CloseServiceHandle(hService); if (ssp != NULL) HeapFree(GetProcessHeap(), 0, ssp); return NULL; }
/* * Get service config information. Returns: * - display_name * - binpath * - username * - startup_type */ PyObject * psutil_winservice_query_config(PyObject *self, PyObject *args) { char *service_name; SC_HANDLE hService = NULL; BOOL ok; DWORD bytesNeeded = 0; DWORD resumeHandle = 0; DWORD dwBytes = 0; QUERY_SERVICE_CONFIG *qsc = NULL; PyObject *py_tuple = NULL; PyObject *py_unicode_display_name = NULL; PyObject *py_unicode_binpath = NULL; PyObject *py_unicode_username = NULL; if (!PyArg_ParseTuple(args, "s", &service_name)) return NULL; hService = psutil_get_service_handler( service_name, SC_MANAGER_ENUMERATE_SERVICE, SERVICE_QUERY_CONFIG); if (hService == NULL) goto error; // First call to QueryServiceConfig() is necessary to get the // right size. bytesNeeded = 0; QueryServiceConfig(hService, NULL, 0, &bytesNeeded); if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { PyErr_SetFromWindowsErr(0); goto error; } qsc = (QUERY_SERVICE_CONFIG *)malloc(bytesNeeded); ok = QueryServiceConfig(hService, qsc, bytesNeeded, &bytesNeeded); if (ok == 0) { PyErr_SetFromWindowsErr(0); goto error; } // Get unicode display name. py_unicode_display_name = PyUnicode_Decode( qsc->lpDisplayName, _tcslen(qsc->lpDisplayName), Py_FileSystemDefaultEncoding, "replace"); if (py_unicode_display_name == NULL) goto error; // Get unicode bin path. py_unicode_binpath = PyUnicode_Decode( qsc->lpBinaryPathName, _tcslen(qsc->lpBinaryPathName), Py_FileSystemDefaultEncoding, "replace"); if (py_unicode_binpath == NULL) goto error; // Get unicode username. py_unicode_username = PyUnicode_Decode( qsc->lpServiceStartName, _tcslen(qsc->lpServiceStartName), Py_FileSystemDefaultEncoding, "replace"); if (py_unicode_username == NULL) goto error; // Construct result tuple. py_tuple = Py_BuildValue( "(OOOs)", py_unicode_display_name, py_unicode_binpath, py_unicode_username, get_startup_string(qsc->dwStartType) // startup ); if (py_tuple == NULL) goto error; // Free resources. Py_DECREF(py_unicode_display_name); Py_DECREF(py_unicode_binpath); Py_DECREF(py_unicode_username); free(qsc); CloseServiceHandle(hService); return py_tuple; error: Py_XDECREF(py_unicode_display_name); Py_XDECREF(py_unicode_binpath); Py_XDECREF(py_unicode_username); Py_XDECREF(py_tuple); if (hService != NULL) CloseServiceHandle(hService); if (qsc != NULL) free(qsc); return NULL; }
PyMODINIT_FUNC init_multiprocess(void) { PyObject *module, *temp, *value; /* Initialize module */ module = Py_InitModule("_multiprocess", module_methods); if (!module) return; /* Get copy of objects from pickle */ temp = PyImport_ImportModule("dill"); if (!temp) temp = PyImport_ImportModule(PICKLE_MODULE); if (!temp) return; pickle_dumps = PyObject_GetAttrString(temp, "dumps"); pickle_loads = PyObject_GetAttrString(temp, "loads"); pickle_protocol = PyObject_GetAttrString(temp, "DEFAULT_PROTOCOL"); if (!pickle_protocol) pickle_protocol = PyObject_GetAttrString(temp, "HIGHEST_PROTOCOL"); Py_XDECREF(temp); /* Get copy of BufferTooShort */ temp = PyImport_ImportModule("multiprocess"); if (!temp) return; BufferTooShort = PyObject_GetAttrString(temp, "BufferTooShort"); Py_XDECREF(temp); /* Add connection type to module */ if (PyType_Ready(&ConnectionType) < 0) return; Py_INCREF(&ConnectionType); PyModule_AddObject(module, "Connection", (PyObject*)&ConnectionType); #if defined(MS_WINDOWS) || HAVE_SEM_OPEN /* Add SemLock type to module */ if (PyType_Ready(&SemLockType) < 0) return; Py_INCREF(&SemLockType); PyDict_SetItemString(SemLockType.tp_dict, "SEM_VALUE_MAX", Py_BuildValue("i", SEM_VALUE_MAX)); PyModule_AddObject(module, "SemLock", (PyObject*)&SemLockType); #endif #ifdef MS_WINDOWS /* Add PipeConnection to module */ if (PyType_Ready(&PipeConnectionType) < 0) return; Py_INCREF(&PipeConnectionType); PyModule_AddObject(module, "PipeConnection", (PyObject*)&PipeConnectionType); /* Initialize win32 class and add to multiprocessing */ temp = create_win32_namespace(); if (!temp) return; PyModule_AddObject(module, "win32", temp); /* Initialize the event handle used to signal Ctrl-C */ sigint_event = CreateEvent(NULL, TRUE, FALSE, NULL); if (!sigint_event) { PyErr_SetFromWindowsErr(0); return; } if (!SetConsoleCtrlHandler(ProcessingCtrlHandler, TRUE)) { PyErr_SetFromWindowsErr(0); return; } #endif /* Add configuration macros */ temp = PyDict_New(); if (!temp) return; #define ADD_FLAG(name) \ value = Py_BuildValue("i", name); \ if (value == NULL) { Py_DECREF(temp); return; } \ if (PyDict_SetItemString(temp, #name, value) < 0) { \ Py_DECREF(temp); Py_DECREF(value); return; } \ Py_DECREF(value) #ifdef HAVE_SEM_OPEN ADD_FLAG(HAVE_SEM_OPEN); #endif #ifdef HAVE_SEM_TIMEDWAIT ADD_FLAG(HAVE_SEM_TIMEDWAIT); #endif #ifdef HAVE_FD_TRANSFER ADD_FLAG(HAVE_FD_TRANSFER); #endif #ifdef HAVE_BROKEN_SEM_GETVALUE ADD_FLAG(HAVE_BROKEN_SEM_GETVALUE); #endif #ifdef HAVE_BROKEN_SEM_UNLINK ADD_FLAG(HAVE_BROKEN_SEM_UNLINK); #endif if (PyModule_AddObject(module, "flags", temp) < 0) return; }