From df26f71e5963778af90f620bd62d3ced7f2799fd Mon Sep 17 00:00:00 2001 From: Robert Rettig Date: Tue, 30 May 2017 09:06:07 +0200 Subject: [PATCH] [#1896] fix play daemon stacktrace on [re]start-stop duplicates [#1910] and fixes [#1860] --- framework/pym/play/commands/daemon.py | 80 ++++++++++++++++----------- 1 file changed, 48 insertions(+), 32 deletions(-) diff --git a/framework/pym/play/commands/daemon.py b/framework/pym/play/commands/daemon.py index 370364144e..f1cbb1f8ee 100644 --- a/framework/pym/play/commands/daemon.py +++ b/framework/pym/play/commands/daemon.py @@ -1,9 +1,12 @@ -import os, os.path +import os +import os.path import subprocess -from play.utils import * import time + +from play.utils import * + if os.name == 'nt': - import win32pdh, string, win32api + import win32pdh, win32pdhutil COMMANDS = ['start', 'stop', 'restart', 'pid', 'out'] @@ -15,6 +18,7 @@ 'out': 'Follow logs/system.out file' } + def execute(**kargs): command = kargs.get("command") app = kargs.get("app") @@ -32,12 +36,14 @@ def execute(**kargs): if command == 'out': out(app) + def start(app, args): app.check() if os.path.exists(app.pid_path()): pid = open(app.pid_path()).readline().strip() if process_running(pid): - print "~ Oops. %s is already started (pid:%s)! (or delete %s)" % (os.path.normpath(app.path), pid, os.path.normpath(app.pid_path())) + print "~ Oops. %s is already started (pid:%s)! (or delete %s)" % ( + os.path.normpath(app.path), pid, os.path.normpath(app.pid_path())) print "~" sys.exit(1) else: @@ -45,7 +51,7 @@ def start(app, args): os.remove(app.pid_path()) sysout = app.readConf('application.log.system.out') - sysout = sysout!='false' and sysout!='off' + sysout = sysout != 'false' and sysout != 'off' if not sysout: sout = None else: @@ -57,12 +63,13 @@ def start(app, args): sys.exit(-1) print "~ OK, %s is started" % os.path.normpath(app.path) if sysout: - print "~ output is redirected to %s" % os.path.normpath(os.path.join(app.log_path(), 'system.out')) + print "~ output is redirected to %s" % os.path.normpath(os.path.join(app.log_path(), 'system.out')) pid_file = open(app.pid_path(), 'w') pid_file.write(str(pid)) print "~ pid is %s" % pid print "~" + def stop(app): app.check() if not os.path.exists(app.pid_path()): @@ -87,12 +94,12 @@ def restart(app, args): kill(pid) sysout = app.readConf('application.log.system.out') - sysout = sysout!='false' and sysout!='off' + sysout = sysout != 'false' and sysout != 'off' java_cmd = app.java_cmd(args) if not sysout: - sout = None + sout = None else: - sout = open(os.path.join(app.log_path(), 'system.out'), 'w') + sout = open(os.path.join(app.log_path(), 'system.out'), 'w') try: pid = subprocess.Popen(java_cmd, stdout=sout, env=os.environ).pid except OSError: @@ -100,7 +107,7 @@ def restart(app, args): sys.exit(-1) print "~ OK, %s is restarted" % os.path.normpath(app.path) if sysout: - print "~ output is redirected to %s" % os.path.normpath(os.path.join(app.log_path(), 'system.out')) + print "~ output is redirected to %s" % os.path.normpath(os.path.join(app.log_path(), 'system.out')) pid_file = open(app.pid_path(), 'w') pid_file.write(str(pid)) print "~ New pid is %s" % pid @@ -118,6 +125,7 @@ def pid(app): print "~ PID of the running applications is %s" % pid print "~ " + def out(app): app.check() if not os.path.exists(os.path.join(app.log_path(), 'system.out')): @@ -138,14 +146,18 @@ def out(app): else: print line + def kill(pid): if os.name == 'nt': import ctypes handle = ctypes.windll.kernel32.OpenProcess(1, False, int(pid)) - if not ctypes.windll.kernel32.TerminateProcess(handle, 0): + process = ctypes.windll.kernel32.TerminateProcess(handle, 0) + ctypes.windll.kernel32.CloseHandle(handle) + if not process: print "~ Cannot kill the process with pid %s (ERROR %s)" % (pid, ctypes.windll.kernel32.GetLastError()) print "~ " sys.exit(-1) + print "~ Process with PID %s terminated" % pid else: try: os.kill(int(pid), 15) @@ -154,42 +166,46 @@ def kill(pid): print "~" sys.exit(-1) + def process_running(pid): - if os.name == 'nt': - return process_running_nt(pid) - else: - try: - os.kill(int(pid), 0) - return True - except OSError: - return False + if os.name == 'nt': + return process_running_nt(pid) + else: + try: + os.kill(int(pid), 0) + return True + except OSError: + return False + # loosely based on http://code.activestate.com/recipes/303339/ def process_list_nt(): - #each instance is a process, you can have multiple processes w/same name - junk, instances = win32pdh.EnumObjectItems(None,None,'process', win32pdh.PERF_DETAIL_WIZARD) - proc_ids={} - proc_dict={} + # each instance is a process, you can have multiple processes w/same name + processLocalizedName = win32pdhutil.find_pdh_counter_localized_name("Process") + junk, instances = win32pdh.EnumObjectItems(None, None, processLocalizedName, win32pdh.PERF_DETAIL_WIZARD) + proc_ids = {} + proc_dict = {} for instance in instances: if instance in proc_dict: proc_dict[instance] = proc_dict[instance] + 1 else: - proc_dict[instance]=0 + proc_dict[instance] = 0 + idProcessLocalizedName = win32pdhutil.find_pdh_counter_localized_name("ID Process") for instance, max_instances in proc_dict.items(): - for inum in xrange(max_instances+1): - hq = win32pdh.OpenQuery() # initializes the query handle - path = win32pdh.MakeCounterPath( (None,'process',instance, None, inum,'ID Process') ) - counter_handle=win32pdh.AddCounter(hq, path) - win32pdh.CollectQueryData(hq) #collects data for the counter + for inum in xrange(max_instances + 1): + hq = win32pdh.OpenQuery() # initializes the query handle + path = win32pdh.MakeCounterPath((None, processLocalizedName, instance, None, inum, idProcessLocalizedName)) + counter_handle = win32pdh.AddCounter(hq, path) + win32pdh.CollectQueryData(hq) # collects data for the counter type, val = win32pdh.GetFormattedCounterValue(counter_handle, win32pdh.PDH_FMT_LONG) - proc_ids[str(val)]=instance; - win32pdh.CloseQuery(hq) + proc_ids[str(val)] = instance; + win32pdh.CloseQuery(hq) return proc_ids def process_running_nt(pid): - if process_list_nt().get(pid,"") != "": + if process_list_nt().get(pid, "") != "": return True else: return False