contrib/chg/chg.c
branchstable
changeset 50383 cf4d2f31660d
parent 47024 8fcc0a829f3d
child 50430 d06e43cd393f
--- a/contrib/chg/chg.c	Fri Apr 07 12:11:44 2023 +0200
+++ b/contrib/chg/chg.c	Mon Mar 27 17:30:14 2023 -0400
@@ -232,12 +232,17 @@
 			hgcmd = "hg";
 #endif
 	}
+	/* Set $CHGHG to the path to the seleted hg executable if it wasn't
+	 * already set. This has the effect of ensuring that a new command
+	 * server will be spawned if the existing command server is running from
+	 * an executable at a different path. */
+	if (setenv("CHGHG", hgcmd, 1) != 0)
+		abortmsgerrno("failed to setenv");
 	return hgcmd;
 }
 
-static void execcmdserver(const struct cmdserveropts *opts)
+static void execcmdserver(const char *hgcmd, const struct cmdserveropts *opts)
 {
-	const char *hgcmd = gethgcmd();
 
 	const char *baseargv[] = {
 	    hgcmd,     "serve",     "--no-profile",     "--cmdserver",
@@ -375,11 +380,16 @@
 
 	debugmsg("start cmdserver at %s", opts->initsockname);
 
+	/* Get the path to the hg executable before we fork because this
+	 * function might update the environment, and we want this to be
+	 * reflected in both the parent and child processes. */
+	const char *hgcmd = gethgcmd();
+
 	pid_t pid = fork();
 	if (pid < 0)
 		abortmsg("failed to fork cmdserver process");
 	if (pid == 0) {
-		execcmdserver(opts);
+		execcmdserver(hgcmd, opts);
 	} else {
 		hgc = retryconnectcmdserver(opts, pid);
 	}
@@ -484,7 +494,7 @@
 		abortmsgerrno("failed to exec original hg");
 }
 
-int main(int argc, const char *argv[], const char *envp[])
+int main(int argc, const char *argv[])
 {
 	if (getenv("CHGDEBUG"))
 		enabledebugmsg();
@@ -519,7 +529,10 @@
 		hgc = connectcmdserver(&opts);
 		if (!hgc)
 			abortmsg("cannot open hg client");
-		hgc_setenv(hgc, envp);
+		/* Use `environ(7)` instead of the optional `envp` argument to
+		 * `main` because `envp` does not update when the environment
+		 * changes, but `environ` does. */
+		hgc_setenv(hgc, (const char *const *)environ);
 		const char **insts = hgc_validate(hgc, argv + 1, argc - 1);
 		int needreconnect = runinstructions(&opts, insts);
 		free(insts);