trying to make tracebacks reproducible

Brodie Rao brodie at bitheap.org
Tue Jul 6 23:05:10 CDT 2010


On Jul 6, 2010, at 4:16 AM, Christian Ebert wrote:

> * Matt Mackall on Monday, July 05, 2010 at 14:05:49 -0500
>> 
>> 
>> You've probably found a kernel bug. In particular, some failure to
>> save/restore floating point state correctly during task switch. Since
>> this is expensive, most operating systems try to avoid doing it if
>> floating point is not in use by a given task.
> 
> I see (sort of). Nothing one can do about it then?
> 
> @Brodie out of curiosity: what errors did you get without your
> patch using just util.popen (as far as I understand)?

This wasn't something I was able to reproduce easily myself, but a user reported a symptom of the problem on the main mailing list:

On 23 March 2010 20:05, Björn Herzig wrote:

> I'm having a weird problem with the mercurial pager extension. Whenever I fire it up the Terminal gets messed up. The prompt shows up within the pager and after quitting i can't see what I'm typing anymore. This keeps me from using the pager extension at all.

The approach Git takes to prevent this kind of problem is to launch the pager as a child process and use waitpid() to keep git running until the pager exits. This approach is nice, and would work on Windows, but I had issues integrating it into the pager extension. I opted for running the pager in the parent process instead.

If you're curious, I started with something like this:

diff --git a/hgext/pager.py b/hgext/pager.py
--- a/hgext/pager.py
+++ b/hgext/pager.py
@@ -60,9 +60,16 @@ def uisetup(ui):
             if (cmd in attend or
                 (cmd not in ui.configlist('pager', 'ignore') and not attend)):
                 ui.setconfig('ui', 'interactive', False)
-                sys.stderr = sys.stdout = util.popen(p, "wb")
+                sys.stderr = sys.stdout = proc = util.popen(p, "wb")
                 if ui.configbool('pager', 'quiet'):
                     signal.signal(signal.SIGPIPE, signal.SIG_DFL)
+                def waitdispatch(orig, args):
+                    try:
+                        orig(args)
+                    finally:
+                        # wait until the pager has exited before returning
+                        proc.close()
+                extensions.wrapfunction(dispatch, 'dispatch', waitdispatch)
         return orig(ui, options, cmd, cmdfunc)

You can't wrap dispatch while dispatch is running uisetup() though, so that doesn't work as is. Issuing waitpid() for all child processes in dispatch directly also won't work as Windows only supports doing waitpid() for specific processes.

You also need to call waitpid/pclose on SIGINT, SIGHUP, SIGTERM, SIGQUIT, and SIGPIPE, and then restore the original signal handler and issue the signal again.


More information about the Mercurial-devel mailing list