diff options
author | Ron Yorston <rmy@pobox.com> | 2018-12-11 15:52:31 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2018-12-11 15:52:31 +0000 |
commit | 68ddd4ec3c1275c66e01172498055817cbb10f04 (patch) | |
tree | e31826ae839535bef102a7ad61bc0e029b20ffae | |
parent | 6c3fd20e67cab2331b1e862c03eeb95a70625454 (diff) | |
download | busybox-w32-68ddd4ec3c1275c66e01172498055817cbb10f04.tar.gz busybox-w32-68ddd4ec3c1275c66e01172498055817cbb10f04.tar.bz2 busybox-w32-68ddd4ec3c1275c66e01172498055817cbb10f04.zip |
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;
-rw-r--r-- | archival/tar.c | 2 | ||||
-rw-r--r-- | coreutils/tee.c | 2 | ||||
-rw-r--r-- | include/libbb.h | 2 | ||||
-rw-r--r-- | include/mingw.h | 4 | ||||
-rw-r--r-- | libbb/u_signal_names.c | 4 | ||||
-rw-r--r-- | shell/ash.c | 6 | ||||
-rw-r--r-- | win32/winansi.c | 26 |
7 files changed, 32 insertions, 14 deletions
diff --git a/archival/tar.c b/archival/tar.c index 22ad0e0f2..7dd89a282 100644 --- a/archival/tar.c +++ b/archival/tar.c | |||
@@ -1122,9 +1122,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv) | |||
1122 | 1122 | ||
1123 | if (opt & OPT_2COMMAND) { | 1123 | if (opt & OPT_2COMMAND) { |
1124 | putenv((char*)"TAR_FILETYPE=f"); | 1124 | putenv((char*)"TAR_FILETYPE=f"); |
1125 | #ifdef SIGPIPE | ||
1126 | signal(SIGPIPE, SIG_IGN); | 1125 | signal(SIGPIPE, SIG_IGN); |
1127 | #endif | ||
1128 | tar_handle->action_data = data_extract_to_command; | 1126 | tar_handle->action_data = data_extract_to_command; |
1129 | IF_FEATURE_TAR_TO_COMMAND(tar_handle->tar__to_command_shell = xstrdup(get_shell_name());) | 1127 | IF_FEATURE_TAR_TO_COMMAND(tar_handle->tar__to_command_shell = xstrdup(get_shell_name());) |
1130 | } | 1128 | } |
diff --git a/coreutils/tee.c b/coreutils/tee.c index d0ded58c4..f0ec791bb 100644 --- a/coreutils/tee.c +++ b/coreutils/tee.c | |||
@@ -69,11 +69,9 @@ int tee_main(int argc, char **argv) | |||
69 | signal(SIGINT, SIG_IGN); /* TODO - switch to sigaction. (why?) */ | 69 | signal(SIGINT, SIG_IGN); /* TODO - switch to sigaction. (why?) */ |
70 | } | 70 | } |
71 | retval = EXIT_SUCCESS; | 71 | retval = EXIT_SUCCESS; |
72 | #ifdef SIGPIPE | ||
73 | /* gnu tee ignores SIGPIPE in case one of the output files is a pipe | 72 | /* gnu tee ignores SIGPIPE in case one of the output files is a pipe |
74 | * that doesn't consume all its input. Good idea... */ | 73 | * that doesn't consume all its input. Good idea... */ |
75 | signal(SIGPIPE, SIG_IGN); | 74 | signal(SIGPIPE, SIG_IGN); |
76 | #endif | ||
77 | 75 | ||
78 | /* Allocate an array of FILE *'s, with one extra for a sentinel. */ | 76 | /* Allocate an array of FILE *'s, with one extra for a sentinel. */ |
79 | fp = files = xzalloc(sizeof(FILE *) * (argc + 2)); | 77 | fp = files = xzalloc(sizeof(FILE *) * (argc + 2)); |
diff --git a/include/libbb.h b/include/libbb.h index 4ac749fd3..a17da9c1f 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -536,9 +536,7 @@ enum { | |||
536 | #endif | 536 | #endif |
537 | + (1LL << SIGINT) | 537 | + (1LL << SIGINT) |
538 | + (1LL << SIGTERM) | 538 | + (1LL << SIGTERM) |
539 | #ifdef SIGPIPE | ||
540 | + (1LL << SIGPIPE) // Write to pipe with no readers | 539 | + (1LL << SIGPIPE) // Write to pipe with no readers |
541 | #endif | ||
542 | #ifdef SIGQUIT | 540 | #ifdef SIGQUIT |
543 | + (1LL << SIGQUIT) // Quit from keyboard | 541 | + (1LL << SIGQUIT) // Quit from keyboard |
544 | #endif | 542 | #endif |
diff --git a/include/mingw.h b/include/mingw.h index a1869227d..8a695d2d2 100644 --- a/include/mingw.h +++ b/include/mingw.h | |||
@@ -93,10 +93,14 @@ IMPL(getpwent,struct passwd *,NULL,void) | |||
93 | * signal.h | 93 | * signal.h |
94 | */ | 94 | */ |
95 | #define SIGKILL 9 | 95 | #define SIGKILL 9 |
96 | #define SIGPIPE 13 | ||
96 | 97 | ||
97 | #define SIG_UNBLOCK 1 | 98 | #define SIG_UNBLOCK 1 |
98 | 99 | ||
99 | NOIMPL(FAST_FUNC sigprocmask_allsigs, int how UNUSED_PARAM); | 100 | NOIMPL(FAST_FUNC sigprocmask_allsigs, int how UNUSED_PARAM); |
101 | typedef void (*sighandler_t)(int); | ||
102 | sighandler_t winansi_signal(int signum, sighandler_t handler); | ||
103 | #define signal(s, h) winansi_signal(s, h) | ||
100 | 104 | ||
101 | /* | 105 | /* |
102 | * stdio.h | 106 | * stdio.h |
diff --git a/libbb/u_signal_names.c b/libbb/u_signal_names.c index f7d598c7a..036ad0038 100644 --- a/libbb/u_signal_names.c +++ b/libbb/u_signal_names.c | |||
@@ -27,6 +27,10 @@ | |||
27 | 27 | ||
28 | #include "libbb.h" | 28 | #include "libbb.h" |
29 | 29 | ||
30 | #if ENABLE_PLATFORM_MINGW32 | ||
31 | # undef SIGPIPE | ||
32 | #endif | ||
33 | |||
30 | /* Believe it or not, but some arches have more than 32 SIGs! | 34 | /* Believe it or not, but some arches have more than 32 SIGs! |
31 | * HPPA: SIGSTKFLT == 36. */ | 35 | * HPPA: SIGSTKFLT == 36. */ |
32 | 36 | ||
diff --git a/shell/ash.c b/shell/ash.c index 22dedc1b6..2e3b22850 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -4410,11 +4410,7 @@ sprint_status48(char *s, int status, int sigonly) | |||
4410 | #endif | 4410 | #endif |
4411 | st = WTERMSIG(status); | 4411 | st = WTERMSIG(status); |
4412 | if (sigonly) { | 4412 | if (sigonly) { |
4413 | #ifdef SIGPIPE | ||
4414 | if (st == SIGINT || st == SIGPIPE) | 4413 | if (st == SIGINT || st == SIGPIPE) |
4415 | #else | ||
4416 | if (st == SIGINT) | ||
4417 | #endif | ||
4418 | goto out; | 4414 | goto out; |
4419 | #if JOBS | 4415 | #if JOBS |
4420 | if (WIFSTOPPED(status)) | 4416 | if (WIFSTOPPED(status)) |
@@ -14951,7 +14947,7 @@ forkshell_openhere(struct forkshell *fs) | |||
14951 | ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN); | 14947 | ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN); |
14952 | ignoresig(SIGHUP); //signal(SIGHUP, SIG_IGN); | 14948 | ignoresig(SIGHUP); //signal(SIGHUP, SIG_IGN); |
14953 | ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN); | 14949 | ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN); |
14954 | //signal(SIGPIPE, SIG_DFL); | 14950 | signal(SIGPIPE, SIG_DFL); |
14955 | if (redir->type == NHERE) { | 14951 | if (redir->type == NHERE) { |
14956 | size_t len = strlen(redir->nhere.doc->narg.text); | 14952 | size_t len = strlen(redir->nhere.doc->narg.text); |
14957 | full_write(pip[1], redir->nhere.doc->narg.text, len); | 14953 | full_write(pip[1], redir->nhere.doc->narg.text, len); |
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) | |||
475 | return (winansi_fputs(s, stdout) == EOF || putchar('\n') == EOF) ? EOF : 0; | 475 | return (winansi_fputs(s, stdout) == EOF || putchar('\n') == EOF) ? EOF : 0; |
476 | } | 476 | } |
477 | 477 | ||
478 | static sighandler_t sigpipe_handler = SIG_DFL; | ||
479 | |||
480 | #undef signal | ||
481 | sighandler_t winansi_signal(int signum, sighandler_t handler) | ||
482 | { | ||
483 | sighandler_t old; | ||
484 | |||
485 | if (signum == SIGPIPE) { | ||
486 | old = sigpipe_handler; | ||
487 | sigpipe_handler = handler; | ||
488 | return old; | ||
489 | } | ||
490 | return signal(signum, handler); | ||
491 | } | ||
492 | |||
478 | static void check_pipe_fd(int fd) | 493 | static void check_pipe_fd(int fd) |
479 | { | 494 | { |
480 | if (GetLastError() == ERROR_NO_DATA) { | 495 | int error = GetLastError(); |
481 | if (GetFileType((HANDLE)_get_osfhandle(fd)) == FILE_TYPE_PIPE) { | 496 | |
497 | if ((error == ERROR_NO_DATA && | ||
498 | GetFileType((HANDLE)_get_osfhandle(fd)) == FILE_TYPE_PIPE) || | ||
499 | error == ERROR_BROKEN_PIPE) { | ||
500 | if (sigpipe_handler == SIG_DFL) | ||
501 | exit(128+SIGPIPE); | ||
502 | else /* SIG_IGN */ | ||
482 | errno = EPIPE; | 503 | errno = EPIPE; |
483 | } | ||
484 | } | 504 | } |
485 | } | 505 | } |
486 | 506 | ||