changeset 31890:ca7af5d15b21

chg: always wait for pager Previously, when runcommand raises, chg aborts with, and does not wait for pager. The call stack is like: hgc_runcommand -> handleresponse -> readchannel -> debugmsg("failed to read channel") -> exit(255) That means, chg returns to the shell, then both the pager and the shell will read from the terminal at the same time, causing problems. This patch fixes that by using "atexit" to register the pager cleanup function so chg will always wait for pager even if runcommand raises.
author Jun Wu <quark@fb.com>
date Tue, 11 Apr 2017 18:31:40 -0700
parents a02e773008f5
children 87f293edabb6
files contrib/chg/chg.c tests/test-chg.t
diffstat 2 files changed, 32 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/contrib/chg/chg.c	Sun Apr 09 19:09:07 2017 +0200
+++ b/contrib/chg/chg.c	Tue Apr 11 18:31:40 2017 -0700
@@ -447,11 +447,11 @@
 	}
 
 	setupsignalhandler(hgc_peerpid(hgc), hgc_peerpgid(hgc));
+	atexit(waitpager);
 	int exitcode = hgc_runcommand(hgc, argv + 1, argc - 1);
 	restoresignalhandler();
 	hgc_close(hgc);
 	freecmdserveropts(&opts);
-	waitpager();
 
 	return exitcode;
 }
--- a/tests/test-chg.t	Sun Apr 09 19:09:07 2017 +0200
+++ b/tests/test-chg.t	Tue Apr 11 18:31:40 2017 -0700
@@ -102,6 +102,37 @@
   $ chg log -l1 -q --config ui.formatted=False
   0:1f7b0de80e11
 
+chg waits for pager if runcommand raises
+
+  $ cat > $TESTTMP/crash.py <<EOF
+  > from mercurial import cmdutil
+  > cmdtable = {}
+  > command = cmdutil.command(cmdtable)
+  > @command('crash')
+  > def pagercrash(ui, repo, *pats, **opts):
+  >     ui.write('going to crash\n')
+  >     raise Exception('.')
+  > EOF
+
+  $ cat > $TESTTMP/fakepager.py <<EOF
+  > import sys, time
+  > for line in iter(sys.stdin.readline, ''):
+  >     if 'crash' in line: # only interested in lines containing 'crash'
+  >         # if chg exits when pager is sleeping (incorrectly), the output
+  >         # will be captured by the next test case
+  >         time.sleep(1)
+  >         sys.stdout.write('crash-pager: %s' % line)
+  > EOF
+
+  $ cat >> .hg/hgrc <<EOF
+  > [extensions]
+  > crash = $TESTTMP/crash.py
+  > EOF
+
+  $ chg crash --pager=on --config ui.formatted=True 2>/dev/null
+  crash-pager: going to crash
+  [255]
+
   $ cd ..
 
 server lifecycle