sapling/tests/test-atexit-epipe.t
Jun Wu 7873db8242 ui: silent stdio write errors during atexit
Summary:
This is the first diff of an alternative fix of D14528603. See also D14603974
for context.

We'd like atexit handlers to not crash with EPIPE or SIGPIPE when writing to
stderr or stdout. Therefore disable SIGPIPE signal handler and patch ui methods
to do so.

Differential Revision: D14607159

fbshipit-source-id: 274c5174813d402a7e0b8b5be7c8fcb0524fcdb3
2019-03-25 18:33:05 -07:00

52 lines
1.6 KiB
Perl

$ cat > a.py << EOF
> import os
> def uisetup(ui):
> # make the test slightly more interesting
> ui.fout = os.fdopen(ui.fout.fileno(), "wb", 1)
> @ui.atexit
> def printlines():
> ui.write("line1\n")
> ui.write("line2\n" * 10000) # probably triggers EPIPE or SIGPIPE
> open("executed-here1", "w").close()
> EOF
This should not trigger StdioError (IOError), or BrokenPipeError (OSError):
$ hg --config extensions.a=a.py init foo1 | head -1
line1
'executed-here1' should exist to indicate the execution flow:
$ [ -f executed-here1 ]
Try again, using a pager:
$ cat > b.py << EOF
> import os
> def uisetup(ui):
> ui.fout = os.fdopen(ui.fout.fileno(), "wb", 1)
> @ui.atexit
> def printlines():
> # This is hacky. But it makes sure pager is running.
> # Using --pager=always is not enough, because killpager is also
> # an atexit handler and gets executed before this one.
> ui.pager("internal-always-atexit")
> # Redo signal.signal(signal.SIGPIPE, signal.SIG_IGN) called by
> # _runexithandlers.
> import signal
> signal.signal(signal.SIGPIPE, signal.SIG_IGN)
> ui.write("line1\n")
> ui.write("line2\n" * 10000) # probably triggers EPIPE or SIGPIPE
> open("executed-here2", "w").close()
> EOF
This should not raise SignalInterrupt (KeyboardInterrupt):
$ hg --config extensions.b=b.py --config 'pager.pager=head -1' init foo2
line1
'executed-here2' should exist to indicate the execution flow:
$ [ -f executed-here2 ]