23
23
import subprocess
24
24
import sys
25
25
import yaml
26
+ import errno
27
+ import time
26
28
27
29
SYNAPSE = [sys .executable , "-B" , "-m" , "synapse.app.homeserver" ]
28
30
29
31
GREEN = "\x1b [1;32m"
32
+ YELLOW = "\x1b [1;33m"
30
33
RED = "\x1b [1;31m"
31
34
NORMAL = "\x1b [m"
32
35
33
36
37
+ def pid_running (pid ):
38
+ try :
39
+ os .kill (pid , 0 )
40
+ return True
41
+ except OSError , err :
42
+ if err .errno == errno .EPERM :
43
+ return True
44
+ return False
45
+
46
+
34
47
def write (message , colour = NORMAL , stream = sys .stdout ):
35
48
if colour == NORMAL :
36
49
stream .write (message + "\n " )
37
50
else :
38
51
stream .write (colour + message + NORMAL + "\n " )
39
52
40
53
54
+ def abort (message , colour = RED , stream = sys .stderr ):
55
+ write (message , colour , stream )
56
+ sys .exit (1 )
57
+
58
+
41
59
def start (configfile ):
42
60
write ("Starting ..." )
43
61
args = SYNAPSE
44
62
args .extend (["--daemonize" , "-c" , configfile ])
45
63
46
64
try :
47
65
subprocess .check_call (args )
48
- write ("started synapse.app.homeserver(%r)" % (configfile ,), colour = GREEN )
66
+ write ("started synapse.app.homeserver(%r)" %
67
+ (configfile ,), colour = GREEN )
49
68
except subprocess .CalledProcessError as e :
50
69
write (
51
70
"error starting (exit code: %d); see above for logs" % e .returncode ,
@@ -76,8 +95,16 @@ def start_worker(app, configfile, worker_configfile):
76
95
def stop (pidfile , app ):
77
96
if os .path .exists (pidfile ):
78
97
pid = int (open (pidfile ).read ())
79
- os .kill (pid , signal .SIGTERM )
80
- write ("stopped %s" % (app ,), colour = GREEN )
98
+ try :
99
+ os .kill (pid , signal .SIGTERM )
100
+ write ("stopped %s" % (app ,), colour = GREEN )
101
+ except OSError , err :
102
+ if err .errno == errno .ESRCH :
103
+ write ("%s not running" % (app ,), colour = YELLOW )
104
+ elif err .errno == errno .EPERM :
105
+ abort ("Cannot stop %s: Operation not permitted" % (app ,))
106
+ else :
107
+ abort ("Cannot stop %s: Unknown error" % (app ,))
81
108
82
109
83
110
Worker = collections .namedtuple ("Worker" , [
@@ -175,7 +202,8 @@ def main():
175
202
worker_app = worker_config ["worker_app" ]
176
203
worker_pidfile = worker_config ["worker_pid_file" ]
177
204
worker_daemonize = worker_config ["worker_daemonize" ]
178
- assert worker_daemonize # TODO print something more user friendly
205
+ assert worker_daemonize , "In config %r: expected '%s' to be True" % (
206
+ worker_configfile , "worker_daemonize" )
179
207
worker_cache_factor = worker_config .get ("synctl_cache_factor" )
180
208
workers .append (Worker (
181
209
worker_app , worker_configfile , worker_pidfile , worker_cache_factor ,
@@ -190,7 +218,19 @@ def main():
190
218
if start_stop_synapse :
191
219
stop (pidfile , "synapse.app.homeserver" )
192
220
193
- # TODO: Wait for synapse to actually shutdown before starting it again
221
+ # Wait for synapse to actually shutdown before starting it again
222
+ if action == "restart" :
223
+ running_pids = []
224
+ if start_stop_synapse and os .path .exists (pidfile ):
225
+ running_pids .append (int (open (pidfile ).read ()))
226
+ for worker in workers :
227
+ if os .path .exists (worker .pidfile ):
228
+ running_pids .append (int (open (worker .pidfile ).read ()))
229
+ if len (running_pids ) > 0 :
230
+ write ("Waiting for process to exit before restarting..." )
231
+ for running_pid in running_pids :
232
+ while pid_running (running_pid ):
233
+ time .sleep (0.2 )
194
234
195
235
if action == "start" or action == "restart" :
196
236
if start_stop_synapse :
0 commit comments