##// END OF EJS Templates
server: add an error feedback mechanism for when the daemon fails to launch...
Matt Harbison -
r37229:f09a2eab default
parent child Browse files
Show More
@@ -30,6 +30,27 b' def runservice(opts, parentfn=None, init'
30 runargs=None, appendpid=False):
30 runargs=None, appendpid=False):
31 '''Run a command as a service.'''
31 '''Run a command as a service.'''
32
32
33 # When daemonized on Windows, redirect stdout/stderr to the lockfile (which
34 # gets cleaned up after the child is up and running), so that the parent can
35 # read and print the error if this child dies early. See 594dd384803c. On
36 # other platforms, the child can write to the parent's stdio directly, until
37 # it is redirected prior to runfn().
38 if pycompat.iswindows and opts['daemon_postexec']:
39 for inst in opts['daemon_postexec']:
40 if inst.startswith('unlink:'):
41 lockpath = inst[7:]
42 if os.path.exists(lockpath):
43 procutil.stdout.flush()
44 procutil.stderr.flush()
45
46 fd = os.open(lockpath,
47 os.O_WRONLY | os.O_APPEND | os.O_BINARY)
48 try:
49 os.dup2(fd, 1)
50 os.dup2(fd, 2)
51 finally:
52 os.close(fd)
53
33 def writepid(pid):
54 def writepid(pid):
34 if opts['pid_file']:
55 if opts['pid_file']:
35 if appendpid:
56 if appendpid:
@@ -61,6 +82,12 b' def runservice(opts, parentfn=None, init'
61 return not os.path.exists(lockpath)
82 return not os.path.exists(lockpath)
62 pid = procutil.rundetached(runargs, condfn)
83 pid = procutil.rundetached(runargs, condfn)
63 if pid < 0:
84 if pid < 0:
85 # If the daemonized process managed to write out an error msg,
86 # report it.
87 if pycompat.iswindows and os.path.exists(lockpath):
88 with open(lockpath) as log:
89 for line in log:
90 procutil.stderr.write(line)
64 raise error.Abort(_('child process failed to start'))
91 raise error.Abort(_('child process failed to start'))
65 writepid(pid)
92 writepid(pid)
66 finally:
93 finally:
@@ -81,10 +108,11 b' def runservice(opts, parentfn=None, init'
81 os.setsid()
108 os.setsid()
82 except AttributeError:
109 except AttributeError:
83 pass
110 pass
111
112 lockpath = None
84 for inst in opts['daemon_postexec']:
113 for inst in opts['daemon_postexec']:
85 if inst.startswith('unlink:'):
114 if inst.startswith('unlink:'):
86 lockpath = inst[7:]
115 lockpath = inst[7:]
87 os.unlink(lockpath)
88 elif inst.startswith('chdir:'):
116 elif inst.startswith('chdir:'):
89 os.chdir(inst[6:])
117 os.chdir(inst[6:])
90 elif inst != 'none':
118 elif inst != 'none':
@@ -107,6 +135,11 b' def runservice(opts, parentfn=None, init'
107 if logfile and logfilefd not in (0, 1, 2):
135 if logfile and logfilefd not in (0, 1, 2):
108 os.close(logfilefd)
136 os.close(logfilefd)
109
137
138 # Only unlink after redirecting stdout/stderr, so Windows doesn't
139 # complain about a sharing violation.
140 if lockpath:
141 os.unlink(lockpath)
142
110 if runfn:
143 if runfn:
111 return runfn()
144 return runfn()
112
145
General Comments 0
You need to be logged in to leave comments. Login now