##// END OF EJS Templates
server: use tryunlink
Ryan McElroy -
r31548:ce4ddcda default
parent child Browse files
Show More
@@ -1,162 +1,157 b''
1 # server.py - utility and factory of server
1 # server.py - utility and factory of server
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import errno
11 import os
10 import os
12 import sys
11 import sys
13 import tempfile
12 import tempfile
14
13
15 from .i18n import _
14 from .i18n import _
16
15
17 from . import (
16 from . import (
18 chgserver,
17 chgserver,
19 commandserver,
18 commandserver,
20 error,
19 error,
21 hgweb,
20 hgweb,
22 util,
21 util,
23 )
22 )
24
23
25 def runservice(opts, parentfn=None, initfn=None, runfn=None, logfile=None,
24 def runservice(opts, parentfn=None, initfn=None, runfn=None, logfile=None,
26 runargs=None, appendpid=False):
25 runargs=None, appendpid=False):
27 '''Run a command as a service.'''
26 '''Run a command as a service.'''
28
27
29 def writepid(pid):
28 def writepid(pid):
30 if opts['pid_file']:
29 if opts['pid_file']:
31 if appendpid:
30 if appendpid:
32 mode = 'a'
31 mode = 'a'
33 else:
32 else:
34 mode = 'w'
33 mode = 'w'
35 fp = open(opts['pid_file'], mode)
34 fp = open(opts['pid_file'], mode)
36 fp.write(str(pid) + '\n')
35 fp.write(str(pid) + '\n')
37 fp.close()
36 fp.close()
38
37
39 if opts['daemon'] and not opts['daemon_postexec']:
38 if opts['daemon'] and not opts['daemon_postexec']:
40 # Signal child process startup with file removal
39 # Signal child process startup with file removal
41 lockfd, lockpath = tempfile.mkstemp(prefix='hg-service-')
40 lockfd, lockpath = tempfile.mkstemp(prefix='hg-service-')
42 os.close(lockfd)
41 os.close(lockfd)
43 try:
42 try:
44 if not runargs:
43 if not runargs:
45 runargs = util.hgcmd() + sys.argv[1:]
44 runargs = util.hgcmd() + sys.argv[1:]
46 runargs.append('--daemon-postexec=unlink:%s' % lockpath)
45 runargs.append('--daemon-postexec=unlink:%s' % lockpath)
47 # Don't pass --cwd to the child process, because we've already
46 # Don't pass --cwd to the child process, because we've already
48 # changed directory.
47 # changed directory.
49 for i in xrange(1, len(runargs)):
48 for i in xrange(1, len(runargs)):
50 if runargs[i].startswith('--cwd='):
49 if runargs[i].startswith('--cwd='):
51 del runargs[i]
50 del runargs[i]
52 break
51 break
53 elif runargs[i].startswith('--cwd'):
52 elif runargs[i].startswith('--cwd'):
54 del runargs[i:i + 2]
53 del runargs[i:i + 2]
55 break
54 break
56 def condfn():
55 def condfn():
57 return not os.path.exists(lockpath)
56 return not os.path.exists(lockpath)
58 pid = util.rundetached(runargs, condfn)
57 pid = util.rundetached(runargs, condfn)
59 if pid < 0:
58 if pid < 0:
60 raise error.Abort(_('child process failed to start'))
59 raise error.Abort(_('child process failed to start'))
61 writepid(pid)
60 writepid(pid)
62 finally:
61 finally:
63 try:
62 util.tryunlink(lockpath)
64 os.unlink(lockpath)
65 except OSError as e:
66 if e.errno != errno.ENOENT:
67 raise
68 if parentfn:
63 if parentfn:
69 return parentfn(pid)
64 return parentfn(pid)
70 else:
65 else:
71 return
66 return
72
67
73 if initfn:
68 if initfn:
74 initfn()
69 initfn()
75
70
76 if not opts['daemon']:
71 if not opts['daemon']:
77 writepid(util.getpid())
72 writepid(util.getpid())
78
73
79 if opts['daemon_postexec']:
74 if opts['daemon_postexec']:
80 try:
75 try:
81 os.setsid()
76 os.setsid()
82 except AttributeError:
77 except AttributeError:
83 pass
78 pass
84 for inst in opts['daemon_postexec']:
79 for inst in opts['daemon_postexec']:
85 if inst.startswith('unlink:'):
80 if inst.startswith('unlink:'):
86 lockpath = inst[7:]
81 lockpath = inst[7:]
87 os.unlink(lockpath)
82 os.unlink(lockpath)
88 elif inst.startswith('chdir:'):
83 elif inst.startswith('chdir:'):
89 os.chdir(inst[6:])
84 os.chdir(inst[6:])
90 elif inst != 'none':
85 elif inst != 'none':
91 raise error.Abort(_('invalid value for --daemon-postexec: %s')
86 raise error.Abort(_('invalid value for --daemon-postexec: %s')
92 % inst)
87 % inst)
93 util.hidewindow()
88 util.hidewindow()
94 util.stdout.flush()
89 util.stdout.flush()
95 util.stderr.flush()
90 util.stderr.flush()
96
91
97 nullfd = os.open(os.devnull, os.O_RDWR)
92 nullfd = os.open(os.devnull, os.O_RDWR)
98 logfilefd = nullfd
93 logfilefd = nullfd
99 if logfile:
94 if logfile:
100 logfilefd = os.open(logfile, os.O_RDWR | os.O_CREAT | os.O_APPEND)
95 logfilefd = os.open(logfile, os.O_RDWR | os.O_CREAT | os.O_APPEND)
101 os.dup2(nullfd, 0)
96 os.dup2(nullfd, 0)
102 os.dup2(logfilefd, 1)
97 os.dup2(logfilefd, 1)
103 os.dup2(logfilefd, 2)
98 os.dup2(logfilefd, 2)
104 if nullfd not in (0, 1, 2):
99 if nullfd not in (0, 1, 2):
105 os.close(nullfd)
100 os.close(nullfd)
106 if logfile and logfilefd not in (0, 1, 2):
101 if logfile and logfilefd not in (0, 1, 2):
107 os.close(logfilefd)
102 os.close(logfilefd)
108
103
109 if runfn:
104 if runfn:
110 return runfn()
105 return runfn()
111
106
112 _cmdservicemap = {
107 _cmdservicemap = {
113 'chgunix': chgserver.chgunixservice,
108 'chgunix': chgserver.chgunixservice,
114 'pipe': commandserver.pipeservice,
109 'pipe': commandserver.pipeservice,
115 'unix': commandserver.unixforkingservice,
110 'unix': commandserver.unixforkingservice,
116 }
111 }
117
112
118 def _createcmdservice(ui, repo, opts):
113 def _createcmdservice(ui, repo, opts):
119 mode = opts['cmdserver']
114 mode = opts['cmdserver']
120 try:
115 try:
121 return _cmdservicemap[mode](ui, repo, opts)
116 return _cmdservicemap[mode](ui, repo, opts)
122 except KeyError:
117 except KeyError:
123 raise error.Abort(_('unknown mode %s') % mode)
118 raise error.Abort(_('unknown mode %s') % mode)
124
119
125 def _createhgwebservice(ui, repo, opts):
120 def _createhgwebservice(ui, repo, opts):
126 # this way we can check if something was given in the command-line
121 # this way we can check if something was given in the command-line
127 if opts.get('port'):
122 if opts.get('port'):
128 opts['port'] = util.getport(opts.get('port'))
123 opts['port'] = util.getport(opts.get('port'))
129
124
130 alluis = set([ui])
125 alluis = set([ui])
131 if repo:
126 if repo:
132 baseui = repo.baseui
127 baseui = repo.baseui
133 alluis.update([repo.baseui, repo.ui])
128 alluis.update([repo.baseui, repo.ui])
134 else:
129 else:
135 baseui = ui
130 baseui = ui
136 webconf = opts.get('web_conf') or opts.get('webdir_conf')
131 webconf = opts.get('web_conf') or opts.get('webdir_conf')
137 if webconf:
132 if webconf:
138 # load server settings (e.g. web.port) to "copied" ui, which allows
133 # load server settings (e.g. web.port) to "copied" ui, which allows
139 # hgwebdir to reload webconf cleanly
134 # hgwebdir to reload webconf cleanly
140 servui = ui.copy()
135 servui = ui.copy()
141 servui.readconfig(webconf, sections=['web'])
136 servui.readconfig(webconf, sections=['web'])
142 alluis.add(servui)
137 alluis.add(servui)
143 else:
138 else:
144 servui = ui
139 servui = ui
145
140
146 optlist = ("name templates style address port prefix ipv6"
141 optlist = ("name templates style address port prefix ipv6"
147 " accesslog errorlog certificate encoding")
142 " accesslog errorlog certificate encoding")
148 for o in optlist.split():
143 for o in optlist.split():
149 val = opts.get(o, '')
144 val = opts.get(o, '')
150 if val in (None, ''): # should check against default options instead
145 if val in (None, ''): # should check against default options instead
151 continue
146 continue
152 for u in alluis:
147 for u in alluis:
153 u.setconfig("web", o, val, 'serve')
148 u.setconfig("web", o, val, 'serve')
154
149
155 app = hgweb.createapp(baseui, repo, webconf)
150 app = hgweb.createapp(baseui, repo, webconf)
156 return hgweb.httpservice(servui, app, opts)
151 return hgweb.httpservice(servui, app, opts)
157
152
158 def createservice(ui, repo, opts):
153 def createservice(ui, repo, opts):
159 if opts["cmdserver"]:
154 if opts["cmdserver"]:
160 return _createcmdservice(ui, repo, opts)
155 return _createcmdservice(ui, repo, opts)
161 else:
156 else:
162 return _createhgwebservice(ui, repo, opts)
157 return _createhgwebservice(ui, repo, opts)
General Comments 0
You need to be logged in to leave comments. Login now