chg: detect chg started by chg

Sometimes people may create a symbol link from hg to chg, or write a wrapper
script named hg calling chg. Without $HG and $CHGHG set, this will lead to
chg executes itself causing deadlock. The user will notice chg hangs for some
time and aborts with a timed out message, without knowing the root cause and
how to solve it.

This patch sets a dummy environment variable before executing hg to detect
this situation, and print a fatal message with some possible solutions.

CHGINTERNALMARK is set by chg client to detect the situation that chg is
started by chg. It is temporary and should be dropped to avoid possible
side effects.
This commit is contained in:
Jun Wu 2016-02-26 14:13:12 +00:00
parent 2aca7b6e3b
commit 93e167796f
2 changed files with 13 additions and 0 deletions

View File

@ -227,6 +227,8 @@ static void execcmdserver(const struct cmdserveropts *opts)
memcpy(argv + baseargvsize, opts->args, sizeof(char *) * opts->argsize);
argv[argsize - 1] = NULL;
if (putenv("CHGINTERNALMARK=") != 0)
abortmsg("failed to putenv (errno = %d)", errno);
if (execvp(hgcmd, (char **)argv) < 0)
abortmsg("failed to exec cmdserver (errno = %d)", errno);
free(argv);
@ -490,6 +492,12 @@ int main(int argc, const char *argv[], const char *envp[])
if (getenv("CHGDEBUG"))
enabledebugmsg();
if (getenv("CHGINTERNALMARK"))
abortmsg("chg started by chg detected.\n"
"Please make sure ${HG:-hg} is not a symlink or "
"wrapper to chg. Alternatively, set $CHGHG to the "
"path of real hg.");
if (isunsupported(argc - 1, argv + 1))
execoriginalhg(argv);

View File

@ -472,3 +472,8 @@ class chgunixservice(commandserver.unixservice):
def uisetup(ui):
commandserver._servicemap['chgunix'] = chgunixservice
# CHGINTERNALMARK is temporarily set by chg client to detect if chg will
# start another chg. drop it to avoid possible side effects.
if 'CHGINTERNALMARK' in os.environ:
del os.environ['CHGINTERNALMARK']