signal_pidfile: support sig=0 on win32
authorMarko Kreen <markokr@gmail.com>
Fri, 25 May 2012 09:30:54 +0000 (12:30 +0300)
committerMarko Kreen <markokr@gmail.com>
Fri, 25 May 2012 09:30:54 +0000 (12:30 +0300)
To avoid pywin32 dependency for such basic functionality,
use kernel32.dll via ctypes directly.

python/skytools/scripting.py

index 0e0cdacf5a39b8712771aa886b66daeecf859829..6e6716e9cbb7f9905c0223a0a7c5bd57746b7b21 100644 (file)
@@ -43,6 +43,8 @@ def signal_pidfile(pidfile, sig):
         ln = f.readline().strip()
         f.close()
         pid = int(ln)
+        if sig == 0 and sys.platform == 'win32':
+            return win32_detect_pid(pid)
         os.kill(pid, sig)
         return True
     except IOError, ex:
@@ -59,6 +61,37 @@ def signal_pidfile(pidfile, sig):
         raise ValueError('Corrupt pidfile: %s' % pidfile)
     return False
 
+def win32_detect_pid(pid):
+    """Process detection for win32."""
+
+    # avoid pywin32 dependecy, use ctypes instead
+    import ctypes
+
+    # win32 constants
+    PROCESS_QUERY_INFORMATION = 1024
+    STILL_ACTIVE = 259
+    ERROR_INVALID_PARAMETER = 87
+    ERROR_ACCESS_DENIED = 5
+
+    # Load kernel32.dll
+    k = ctypes.windll.kernel32
+    OpenProcess = k.OpenProcess
+    OpenProcess.restype = ctypes.c_void_p
+
+    # query pid exit code
+    h = OpenProcess(PROCESS_QUERY_INFORMATION, 0, pid)
+    if h == None:
+        err = k.GetLastError()
+        if err == ERROR_INVALID_PARAMETER:
+            return False
+        if err == ERROR_ACCESS_DENIED:
+            return True
+        raise OSError(errno.EFAULT, "Unknown win32error: " + str(err))
+    code = ctypes.c_int()
+    k.GetExitCodeProcess(h, ctypes.byref(code))
+    k.CloseHandle(h)
+    return code.value == STILL_ACTIVE
+
 #
 # daemon mode
 #