chg: always wait for pager
authorJun Wu <quark@fb.com>
Tue, 11 Apr 2017 18:31:40 -0700
changeset 31890 ca7af5d15b21
parent 31889 a02e773008f5
child 31891 87f293edabb6
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.
contrib/chg/chg.c
tests/test-chg.t
--- 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