From 68ddd4ec3c1275c66e01172498055817cbb10f04 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Tue, 11 Dec 2018 15:52:31 +0000 Subject: win32: emulate SIGPIPE The code to check whether a write error is due to a broken pipe can now either: - return with error EPIPE; - cause the process to exit with code 128+SIGPIPE. The default is the latter but the behaviour can be changed by issuing signal(SIGPIPE, SIG_IGN) and signal(SIGPIPE, SIG_DFL) calls. No actual signal is involved so kill can't send SIGPIPE and handlers other than SIG_IGN and SIG_DFL aren't supported. This does, however, avoid unsightly 'broken pipe' errors from commands like the example in GitHub issue #99: dd if=/dev/urandom | tr -dc _A-Z-a-z-0-9 | head -c${1:-32};echo; --- win32/winansi.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) (limited to 'win32') diff --git a/win32/winansi.c b/win32/winansi.c index a8f5dba79..167b4b0b1 100644 --- a/win32/winansi.c +++ b/win32/winansi.c @@ -475,12 +475,32 @@ int winansi_puts(const char *s) return (winansi_fputs(s, stdout) == EOF || putchar('\n') == EOF) ? EOF : 0; } +static sighandler_t sigpipe_handler = SIG_DFL; + +#undef signal +sighandler_t winansi_signal(int signum, sighandler_t handler) +{ + sighandler_t old; + + if (signum == SIGPIPE) { + old = sigpipe_handler; + sigpipe_handler = handler; + return old; + } + return signal(signum, handler); +} + static void check_pipe_fd(int fd) { - if (GetLastError() == ERROR_NO_DATA) { - if (GetFileType((HANDLE)_get_osfhandle(fd)) == FILE_TYPE_PIPE) { + int error = GetLastError(); + + if ((error == ERROR_NO_DATA && + GetFileType((HANDLE)_get_osfhandle(fd)) == FILE_TYPE_PIPE) || + error == ERROR_BROKEN_PIPE) { + if (sigpipe_handler == SIG_DFL) + exit(128+SIGPIPE); + else /* SIG_IGN */ errno = EPIPE; - } } } -- cgit v1.2.3-55-g6feb