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