From 9432574fecc1af8a9d7b24ea98bd2a52c8600cfc Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Mon, 26 Nov 2012 19:47:33 +0100 Subject: [PATCH] [FIX] restart of server on windows when running as nt service bzr revid: chs@openerp.com-20121126184733-i4blfoh0d57s5s4l --- openerp/service/__init__.py | 3 +- openerp/tools/osutil.py | 60 +++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/openerp/service/__init__.py b/openerp/service/__init__.py index f34ef0c9461..3d641abf9b4 100644 --- a/openerp/service/__init__.py +++ b/openerp/service/__init__.py @@ -129,7 +129,8 @@ def start_services_workers(): def _reexec(): """reexecute openerp-server process with (nearly) the same arguments""" - # TODO check if parent is a NT service + if openerp.tools.osutil.is_running_as_nt_service(): + os._exit(1) strip_args = ['-d', '-u'] a = sys.argv[:] args = [x for i, x in enumerate(a) if x not in strip_args and a[max(i - 1, 0)] not in strip_args] diff --git a/openerp/tools/osutil.py b/openerp/tools/osutil.py index 3da9fa624a3..949ba2a8422 100644 --- a/openerp/tools/osutil.py +++ b/openerp/tools/osutil.py @@ -26,6 +26,11 @@ Some functions related to the os and os.path module import os from os.path import join as opj +if os.name == 'nt': + import ctypes + import win32service as ws + + def listdir(dir, recursive=False): """Allow to recursively get the file listing""" dir = os.path.normpath(dir) @@ -56,6 +61,61 @@ def walksymlinks(top, topdown=True, onerror=None): yield dirpath, dirnames, filenames +if os.name != 'nt': + getppid = os.getppid + is_running_as_nt_service = lambda: False +else: + # based on http://mail.python.org/pipermail/python-win32/2007-June/006174.html + _TH32CS_SNAPPROCESS = 0x00000002 + class _PROCESSENTRY32(ctypes.Structure): + _fields_ = [("dwSize", ctypes.c_ulong), + ("cntUsage", ctypes.c_ulong), + ("th32ProcessID", ctypes.c_ulong), + ("th32DefaultHeapID", ctypes.c_ulong), + ("th32ModuleID", ctypes.c_ulong), + ("cntThreads", ctypes.c_ulong), + ("th32ParentProcessID", ctypes.c_ulong), + ("pcPriClassBase", ctypes.c_ulong), + ("dwFlags", ctypes.c_ulong), + ("szExeFile", ctypes.c_char * 260)] + + def getppid(): + CreateToolhelp32Snapshot = ctypes.windll.kernel32.CreateToolhelp32Snapshot + Process32First = ctypes.windll.kernel32.Process32First + Process32Next = ctypes.windll.kernel32.Process32Next + CloseHandle = ctypes.windll.kernel32.CloseHandle + hProcessSnap = CreateToolhelp32Snapshot(_TH32CS_SNAPPROCESS, 0) + current_pid = os.getpid() + try: + pe32 = _PROCESSENTRY32() + pe32.dwSize = ctypes.sizeof(_PROCESSENTRY32) + if not Process32First(hProcessSnap, ctypes.byref(pe32)): + raise OSError('Failed getting first process.') + while True: + if pe32.th32ProcessID == current_pid: + return pe32.th32ParentProcessID + if not Process32Next(hProcessSnap, ctypes.byref(pe32)): + return None + finally: + CloseHandle(hProcessSnap) + + from contextlib import contextmanager + from openerp.release import serie + + def is_running_as_nt_service(): + @contextmanager + def close_srv(srv): + try: + yield srv + finally: + ws.CloseServiceHandle(srv) + + service_name = 'openerp-server-' + serie + + with close_srv(ws.OpenSCManager(None, None, ws.SC_MANAGER_ALL_ACCESS)) as hscm: + with close_srv(ws.SmartOpenService(hscm, service_name, ws.SERVICE_ALL_ACCESS)) as hs: + info = ws.QueryServiceStatusEx(hs) + return info.ProcessId == getppid() if __name__ == '__main__': from pprint import pprint as pp