comparison mercurial/server.py @ 37215:73a60281a861

server: refactor 'daemon_postexec' instructions into a dictionary
author Matt Harbison <matt_harbison@yahoo.com>
date Fri, 30 Mar 2018 23:21:46 -0400
parents f09a2eab11cf
children d2bd29dffc6c
comparison
equal deleted inserted replaced
37214:3bc609bcfe77 37215:73a60281a861
28 28
29 def runservice(opts, parentfn=None, initfn=None, runfn=None, logfile=None, 29 def runservice(opts, parentfn=None, initfn=None, runfn=None, logfile=None,
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 postexecargs = {}
34
35 if opts['daemon_postexec']:
36 for inst in opts['daemon_postexec']:
37 if inst.startswith('unlink:'):
38 postexecargs['unlink'] = inst[7:]
39 elif inst.startswith('chdir:'):
40 postexecargs['chdir'] = inst[6:]
41 elif inst != 'none':
42 raise error.Abort(_('invalid value for --daemon-postexec: %s')
43 % inst)
44
33 # When daemonized on Windows, redirect stdout/stderr to the lockfile (which 45 # 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 46 # 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 47 # 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 48 # other platforms, the child can write to the parent's stdio directly, until
37 # it is redirected prior to runfn(). 49 # it is redirected prior to runfn().
38 if pycompat.iswindows and opts['daemon_postexec']: 50 if pycompat.iswindows and opts['daemon_postexec']:
39 for inst in opts['daemon_postexec']: 51 if 'unlink' in postexecargs and os.path.exists(postexecargs['unlink']):
40 if inst.startswith('unlink:'): 52 procutil.stdout.flush()
41 lockpath = inst[7:] 53 procutil.stderr.flush()
42 if os.path.exists(lockpath): 54
43 procutil.stdout.flush() 55 fd = os.open(postexecargs['unlink'],
44 procutil.stderr.flush() 56 os.O_WRONLY | os.O_APPEND | os.O_BINARY)
45 57 try:
46 fd = os.open(lockpath, 58 os.dup2(fd, 1)
47 os.O_WRONLY | os.O_APPEND | os.O_BINARY) 59 os.dup2(fd, 2)
48 try: 60 finally:
49 os.dup2(fd, 1) 61 os.close(fd)
50 os.dup2(fd, 2)
51 finally:
52 os.close(fd)
53 62
54 def writepid(pid): 63 def writepid(pid):
55 if opts['pid_file']: 64 if opts['pid_file']:
56 if appendpid: 65 if appendpid:
57 mode = 'ab' 66 mode = 'ab'
107 try: 116 try:
108 os.setsid() 117 os.setsid()
109 except AttributeError: 118 except AttributeError:
110 pass 119 pass
111 120
112 lockpath = None 121 if 'chdir' in postexecargs:
113 for inst in opts['daemon_postexec']: 122 os.chdir(postexecargs['chdir'])
114 if inst.startswith('unlink:'):
115 lockpath = inst[7:]
116 elif inst.startswith('chdir:'):
117 os.chdir(inst[6:])
118 elif inst != 'none':
119 raise error.Abort(_('invalid value for --daemon-postexec: %s')
120 % inst)
121 procutil.hidewindow() 123 procutil.hidewindow()
122 procutil.stdout.flush() 124 procutil.stdout.flush()
123 procutil.stderr.flush() 125 procutil.stderr.flush()
124 126
125 nullfd = os.open(os.devnull, os.O_RDWR) 127 nullfd = os.open(os.devnull, os.O_RDWR)
135 if logfile and logfilefd not in (0, 1, 2): 137 if logfile and logfilefd not in (0, 1, 2):
136 os.close(logfilefd) 138 os.close(logfilefd)
137 139
138 # Only unlink after redirecting stdout/stderr, so Windows doesn't 140 # Only unlink after redirecting stdout/stderr, so Windows doesn't
139 # complain about a sharing violation. 141 # complain about a sharing violation.
140 if lockpath: 142 if 'unlink' in postexecargs:
141 os.unlink(lockpath) 143 os.unlink(postexecargs['unlink'])
142 144
143 if runfn: 145 if runfn:
144 return runfn() 146 return runfn()
145 147
146 _cmdservicemap = { 148 _cmdservicemap = {