Mercurial > hg
comparison contrib/chg/chg.c @ 30620:937c52f06709
chg: start server at a unique address
See the previous patch for motivation. Previously, the server is started at
a globally shared address. This patch appends pid to the address so it
becomes unique.
Note: with Linux pid namespace, the address may be non-unique, but it does
not affect correctness of chg - chg client will receive an redirection and
that's it.
author | Jun Wu <quark@fb.com> |
---|---|
date | Mon, 19 Dec 2016 22:09:49 +0000 |
parents | ff7df4bb75de |
children | d7875bfbfccb |
comparison
equal
deleted
inserted
replaced
30619:88efb4fb1975 | 30620:937c52f06709 |
---|---|
29 #define UNIX_PATH_MAX (sizeof(((struct sockaddr_un *)NULL)->sun_path)) | 29 #define UNIX_PATH_MAX (sizeof(((struct sockaddr_un *)NULL)->sun_path)) |
30 #endif | 30 #endif |
31 | 31 |
32 struct cmdserveropts { | 32 struct cmdserveropts { |
33 char sockname[UNIX_PATH_MAX]; | 33 char sockname[UNIX_PATH_MAX]; |
34 char initsockname[UNIX_PATH_MAX]; | |
34 char redirectsockname[UNIX_PATH_MAX]; | 35 char redirectsockname[UNIX_PATH_MAX]; |
35 char lockfile[UNIX_PATH_MAX]; | 36 char lockfile[UNIX_PATH_MAX]; |
36 size_t argsize; | 37 size_t argsize; |
37 const char **args; | 38 const char **args; |
38 int lockfd; | 39 int lockfd; |
161 if (r < 0 || (size_t)r >= sizeof(opts->sockname)) | 162 if (r < 0 || (size_t)r >= sizeof(opts->sockname)) |
162 abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r); | 163 abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r); |
163 r = snprintf(opts->lockfile, sizeof(opts->lockfile), lockfmt, basename); | 164 r = snprintf(opts->lockfile, sizeof(opts->lockfile), lockfmt, basename); |
164 if (r < 0 || (size_t)r >= sizeof(opts->lockfile)) | 165 if (r < 0 || (size_t)r >= sizeof(opts->lockfile)) |
165 abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r); | 166 abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r); |
167 r = snprintf(opts->initsockname, sizeof(opts->initsockname), | |
168 "%s.%u", opts->sockname, (unsigned)getpid()); | |
169 if (r < 0 || (size_t)r >= sizeof(opts->initsockname)) | |
170 abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r); | |
166 } | 171 } |
167 | 172 |
168 /* | 173 /* |
169 * Acquire a file lock that indicates a client is trying to start and connect | 174 * Acquire a file lock that indicates a client is trying to start and connect |
170 * to a server, before executing a command. The lock is released upon exit or | 175 * to a server, before executing a command. The lock is released upon exit or |
221 | 226 |
222 const char *baseargv[] = { | 227 const char *baseargv[] = { |
223 hgcmd, | 228 hgcmd, |
224 "serve", | 229 "serve", |
225 "--cmdserver", "chgunix", | 230 "--cmdserver", "chgunix", |
226 "--address", opts->sockname, | 231 "--address", opts->initsockname, |
227 "--daemon-postexec", "chdir:/", | 232 "--daemon-postexec", "chdir:/", |
228 }; | 233 }; |
229 size_t baseargvsize = sizeof(baseargv) / sizeof(baseargv[0]); | 234 size_t baseargvsize = sizeof(baseargv) / sizeof(baseargv[0]); |
230 size_t argsize = baseargvsize + opts->argsize + 1; | 235 size_t argsize = baseargvsize + opts->argsize + 1; |
231 | 236 |
245 static hgclient_t *retryconnectcmdserver(struct cmdserveropts *opts, pid_t pid) | 250 static hgclient_t *retryconnectcmdserver(struct cmdserveropts *opts, pid_t pid) |
246 { | 251 { |
247 static const struct timespec sleepreq = {0, 10 * 1000000}; | 252 static const struct timespec sleepreq = {0, 10 * 1000000}; |
248 int pst = 0; | 253 int pst = 0; |
249 | 254 |
250 debugmsg("try connect to %s repeatedly", opts->sockname); | 255 debugmsg("try connect to %s repeatedly", opts->initsockname); |
251 | 256 |
252 unsigned int timeoutsec = 60; /* default: 60 seconds */ | 257 unsigned int timeoutsec = 60; /* default: 60 seconds */ |
253 const char *timeoutenv = getenv("CHGTIMEOUT"); | 258 const char *timeoutenv = getenv("CHGTIMEOUT"); |
254 if (timeoutenv) | 259 if (timeoutenv) |
255 sscanf(timeoutenv, "%u", &timeoutsec); | 260 sscanf(timeoutenv, "%u", &timeoutsec); |
256 | 261 |
257 for (unsigned int i = 0; !timeoutsec || i < timeoutsec * 100; i++) { | 262 for (unsigned int i = 0; !timeoutsec || i < timeoutsec * 100; i++) { |
258 hgclient_t *hgc = hgc_open(opts->sockname); | 263 hgclient_t *hgc = hgc_open(opts->initsockname); |
259 if (hgc) | 264 if (hgc) { |
265 debugmsg("rename %s to %s", opts->initsockname, | |
266 opts->sockname); | |
267 int r = rename(opts->initsockname, opts->sockname); | |
268 if (r != 0) | |
269 abortmsgerrno("cannot rename"); | |
260 return hgc; | 270 return hgc; |
271 } | |
261 | 272 |
262 if (pid > 0) { | 273 if (pid > 0) { |
263 /* collect zombie if child process fails to start */ | 274 /* collect zombie if child process fails to start */ |
264 int r = waitpid(pid, &pst, WNOHANG); | 275 int r = waitpid(pid, &pst, WNOHANG); |
265 if (r != 0) | 276 if (r != 0) |
267 } | 278 } |
268 | 279 |
269 nanosleep(&sleepreq, NULL); | 280 nanosleep(&sleepreq, NULL); |
270 } | 281 } |
271 | 282 |
272 abortmsg("timed out waiting for cmdserver %s", opts->sockname); | 283 abortmsg("timed out waiting for cmdserver %s", opts->initsockname); |
273 return NULL; | 284 return NULL; |
274 | 285 |
275 cleanup: | 286 cleanup: |
276 if (WIFEXITED(pst)) { | 287 if (WIFEXITED(pst)) { |
277 if (WEXITSTATUS(pst) == 0) | 288 if (WEXITSTATUS(pst) == 0) |
310 * address does not work. we do not want to connect to the server | 321 * address does not work. we do not want to connect to the server |
311 * again because it will probably tell us the same thing. */ | 322 * again because it will probably tell us the same thing. */ |
312 if (sockname == opts->redirectsockname) | 323 if (sockname == opts->redirectsockname) |
313 unlink(opts->sockname); | 324 unlink(opts->sockname); |
314 | 325 |
315 debugmsg("start cmdserver at %s", opts->sockname); | 326 debugmsg("start cmdserver at %s", opts->initsockname); |
316 | 327 |
317 pid_t pid = fork(); | 328 pid_t pid = fork(); |
318 if (pid < 0) | 329 if (pid < 0) |
319 abortmsg("failed to fork cmdserver process"); | 330 abortmsg("failed to fork cmdserver process"); |
320 if (pid == 0) { | 331 if (pid == 0) { |