summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2018-12-11 15:52:31 +0000
committerRon Yorston <rmy@pobox.com>2018-12-11 15:52:31 +0000
commit68ddd4ec3c1275c66e01172498055817cbb10f04 (patch)
treee31826ae839535bef102a7ad61bc0e029b20ffae
parent6c3fd20e67cab2331b1e862c03eeb95a70625454 (diff)
downloadbusybox-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.c2
-rw-r--r--coreutils/tee.c2
-rw-r--r--include/libbb.h2
-rw-r--r--include/mingw.h4
-rw-r--r--libbb/u_signal_names.c4
-rw-r--r--shell/ash.c6
-rw-r--r--win32/winansi.c26
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
99NOIMPL(FAST_FUNC sigprocmask_allsigs, int how UNUSED_PARAM); 100NOIMPL(FAST_FUNC sigprocmask_allsigs, int how UNUSED_PARAM);
101typedef void (*sighandler_t)(int);
102sighandler_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
478static sighandler_t sigpipe_handler = SIG_DFL;
479
480#undef signal
481sighandler_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
478static void check_pipe_fd(int fd) 493static 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