Skip to content

Commit

Permalink
Merge branch 'master' into 1849_controllerException
Browse files Browse the repository at this point in the history
* master:
  [playframework#1244] doc(release): add documentation for 1.5.1
  [#1896] fix play daemon stacktrace on [re]start-stop
  • Loading branch information
Fraserhardy committed Jul 18, 2018
2 parents b41ebc3 + 2637d90 commit 97c3ebc
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 32 deletions.
@@ -0,0 +1,37 @@
h1. Play 1.5.1 -- Release notes

Play 1.5.1 has been released of the master branch.

The changes in this release are listed in the "Play 1.5.1 milestone":https://play.lighthouseapp.com/projects/57987-play-framework/milestones/230972-151 on Lighthouse and "1.5.1 on github":https://github.com/playframework/play1/milestone/2836691 including 24 resolved tickets.


h2. What's new in Play 1.5.1

* "#2173":https://play.lighthouseapp.com/projects/57987/tickets/2173 : Add LocalDateTime binder
* "#1133":https://github.com/playframework/play1/issues/1133 : Allow customization of @CacheFor cache key
* "#1186":https://github.com/playframework/play1/issues/1186 : [#2138]enhance the function for the injector (Add the injectable interface)
* "#1193":https://github.com/playframework/play1/issues/1193 : Update select.tag to support "null" option of select with attribute "showEmpty: true"
* "#1232":https://github.com/playframework/play1/issues/1232 : Update HikariCP to 2.7.9
* "#1233":https://github.com/playframework/play1/issues/1233 : [#1232] feat(libs)/ update hikari CP from 2.6.3 to 2.7.9


h2. What's fixed in Play 1.5.1

* "#1158":https://github.com/playframework/play1/issues/1158 : [#1896] fix play daemon stacktrace on [re]start-stop
* "#1166":https://github.com/playframework/play1/issues/1166 : Allow customization of @CacheFor cache key
* "#1192":https://github.com/playframework/play1/issues/1192 : Update Configuration.java
* "#1208":https://github.com/playframework/play1/issues/1208 : [#2140] Make FunctionalTest compatible with Response.writeChunk()
* "#1219":https://github.com/playframework/play1/issues/1219 : [#2154] fix NPE on @On annotation
* "#2154":https://play.lighthouseapp.com/projects/57987/tickets/2154 : fix NPE on @On annotation
* "#1220":https://github.com/playframework/play1/issues/1220 : [#2154, #1219] Fixes NPE for @On annotation
* "#1223":https://github.com/playframework/play1/issues/1223 : [#1823] Fix play.exceptions.CompilationException (fix for the fix #786)
* "#1224":https://github.com/playframework/play1/issues/1224 : [#1823] Fix play.exceptions.CompilationException (fix for the fix #786)
* "#1225":https://github.com/playframework/play1/issues/1225 : PlayController implemented
* "#1226":https://github.com/playframework/play1/issues/1226 : #1237 Use secure websocket protocol for secure pages
* "#1228":https://github.com/playframework/play1/issues/1228 : Fixing spelling mistake (runing -> running)
* "#1229":https://github.com/playframework/play1/issues/1229 : 1228 fix spellling mistake
* "#1237":https://github.com/playframework/play1/issues/1237 : Do not allow mixed-content WebSockets
* "#1910":https://play.lighthouseapp.com/projects/57987/tickets/1910 : Stacktrace when running play start with existing pid but no process
* "#1896":https://play.lighthouseapp.com/projects/57987/tickets/1896 : play daemon [re]start-stop (python traceback)
* "#2140":https://play.lighthouseapp.com/projects/57987/tickets/2140 : Chunked responses are not testable by FunctionalTest
* "#1244":https://github.com/playframework/play1/issues/1244 : Prepare release 1.5.1
1 change: 1 addition & 0 deletions documentation/manual/releases/releases.textile
Expand Up @@ -4,6 +4,7 @@ You can download Play releases "here":https://www.playframework.com/download. Ea

h2. Play 1.5.x

# "Play 1.5.1":release1.5.x/releasenotes-1.5.1
# "Play 1.5.0":release1.5.x/releasenotes-1.5.0

h2. Play 1.4.x
Expand Down
80 changes: 48 additions & 32 deletions 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']

Expand All @@ -15,6 +18,7 @@
'out': 'Follow logs/system.out file'
}


def execute(**kargs):
command = kargs.get("command")
app = kargs.get("app")
Expand All @@ -32,20 +36,22 @@ 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:
print "~ removing pid file %s for not running pid %s" % (os.path.normpath(app.pid_path()), pid)
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:
Expand All @@ -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()):
Expand All @@ -87,20 +94,20 @@ 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:
print "Could not execute the java executable, please make sure the JAVA_HOME environment variable is set properly (the java executable should reside at JAVA_HOME/bin/java). "
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
Expand All @@ -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')):
Expand All @@ -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)
Expand All @@ -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

0 comments on commit 97c3ebc

Please sign in to comment.