# HG changeset patch # User Jun Wu # Date 1482185389 0 # Node ID 937c52f0670999ee58c9653d8475b192a7e745ff # Parent 88efb4fb197506b509260393ce1ca13f1e891b2a 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. diff -r 88efb4fb1975 -r 937c52f06709 contrib/chg/chg.c --- a/contrib/chg/chg.c Mon Dec 19 22:07:41 2016 +0000 +++ b/contrib/chg/chg.c Mon Dec 19 22:09:49 2016 +0000 @@ -31,6 +31,7 @@ struct cmdserveropts { char sockname[UNIX_PATH_MAX]; + char initsockname[UNIX_PATH_MAX]; char redirectsockname[UNIX_PATH_MAX]; char lockfile[UNIX_PATH_MAX]; size_t argsize; @@ -163,6 +164,10 @@ r = snprintf(opts->lockfile, sizeof(opts->lockfile), lockfmt, basename); if (r < 0 || (size_t)r >= sizeof(opts->lockfile)) abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r); + r = snprintf(opts->initsockname, sizeof(opts->initsockname), + "%s.%u", opts->sockname, (unsigned)getpid()); + if (r < 0 || (size_t)r >= sizeof(opts->initsockname)) + abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r); } /* @@ -223,7 +228,7 @@ hgcmd, "serve", "--cmdserver", "chgunix", - "--address", opts->sockname, + "--address", opts->initsockname, "--daemon-postexec", "chdir:/", }; size_t baseargvsize = sizeof(baseargv) / sizeof(baseargv[0]); @@ -247,7 +252,7 @@ static const struct timespec sleepreq = {0, 10 * 1000000}; int pst = 0; - debugmsg("try connect to %s repeatedly", opts->sockname); + debugmsg("try connect to %s repeatedly", opts->initsockname); unsigned int timeoutsec = 60; /* default: 60 seconds */ const char *timeoutenv = getenv("CHGTIMEOUT"); @@ -255,9 +260,15 @@ sscanf(timeoutenv, "%u", &timeoutsec); for (unsigned int i = 0; !timeoutsec || i < timeoutsec * 100; i++) { - hgclient_t *hgc = hgc_open(opts->sockname); - if (hgc) + hgclient_t *hgc = hgc_open(opts->initsockname); + if (hgc) { + debugmsg("rename %s to %s", opts->initsockname, + opts->sockname); + int r = rename(opts->initsockname, opts->sockname); + if (r != 0) + abortmsgerrno("cannot rename"); return hgc; + } if (pid > 0) { /* collect zombie if child process fails to start */ @@ -269,7 +280,7 @@ nanosleep(&sleepreq, NULL); } - abortmsg("timed out waiting for cmdserver %s", opts->sockname); + abortmsg("timed out waiting for cmdserver %s", opts->initsockname); return NULL; cleanup: @@ -312,7 +323,7 @@ if (sockname == opts->redirectsockname) unlink(opts->sockname); - debugmsg("start cmdserver at %s", opts->sockname); + debugmsg("start cmdserver at %s", opts->initsockname); pid_t pid = fork(); if (pid < 0) diff -r 88efb4fb1975 -r 937c52f06709 tests/test-chg.t --- a/tests/test-chg.t Mon Dec 19 22:07:41 2016 +0000 +++ b/tests/test-chg.t Mon Dec 19 22:09:49 2016 +0000 @@ -46,7 +46,7 @@ warm up server: $ CHGDEBUG= chg log 2>&1 | egrep 'instruction|start' - chg: debug: start cmdserver at $TESTTMP/extreload/chgsock/server + chg: debug: start cmdserver at $TESTTMP/extreload/chgsock/server.* (glob) new server should be started if extension modified: @@ -55,7 +55,7 @@ $ CHGDEBUG= chg log 2>&1 | egrep 'instruction|start' chg: debug: instruction: unlink $TESTTMP/extreload/chgsock/server-* (glob) chg: debug: instruction: reconnect - chg: debug: start cmdserver at $TESTTMP/extreload/chgsock/server + chg: debug: start cmdserver at $TESTTMP/extreload/chgsock/server.* (glob) old server will shut down, while new server should still be reachable: @@ -77,7 +77,7 @@ (this test makes sure that old server shut down automatically) $ CHGDEBUG= chg log 2>&1 | egrep 'instruction|start' - chg: debug: start cmdserver at $TESTTMP/extreload/chgsock/server + chg: debug: start cmdserver at $TESTTMP/extreload/chgsock/server.* (glob) shut down servers and restore environment: