chg: start server at a unique address
authorJun Wu <quark@fb.com>
Mon, 19 Dec 2016 22:09:49 +0000
changeset 30620 937c52f06709
parent 30619 88efb4fb1975
child 30621 d7875bfbfccb
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.
contrib/chg/chg.c
tests/test-chg.t
--- 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)
--- 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: