summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2020-04-15 01:25:04 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2020-04-15 21:05:39 +0900
commit155f64e3c4ba23f0e85e8d69facceb21a487dccd (patch)
treef0c79b8bc3ddeedd98326dc45a5dd8cfc1917d08
parentd72fd1e45b192ab507f8170ceec1328c2aae7bb1 (diff)
Raise EPIPE at broken pipe for the backward compatibility
Instead of SignalException for SIGPIPE, raise `Errno::EPIPE` with instance variable `signo` and re-send that signal at exit. [Feature #14413]
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/3035
-rw-r--r--NEWS.md5
-rw-r--r--eval.c6
-rw-r--r--eval_error.c4
-rw-r--r--io.c17
4 files changed, 23 insertions, 9 deletions
diff --git a/NEWS.md b/NEWS.md
index 890306ca86..2322e468b7 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -149,9 +149,8 @@ Excluding feature bug fixes.
* This is experimental; if it brings a big incompatibility issue,
it may be reverted until 2.8/3.0 release.
-* When writing to STDOUT redirected to a closed pipe, SignalException
- is raised now instead of Errno::EPIPE, so that no broken pipe error
- message will be shown. [[Feature #14413]]
+* When writing to STDOUT redirected to a closed pipe, no broken pipe
+ error message will be shown now. [[Feature #14413]]
## Stdlib compatibility issues
diff --git a/eval.c b/eval.c
index 0102171205..dc71073fec 100644
--- a/eval.c
+++ b/eval.c
@@ -243,6 +243,7 @@ rb_ec_cleanup(rb_execution_context_t *ec, volatile int ex)
state = 0;
for (nerr = 0; nerr < numberof(errs); ++nerr) {
VALUE err = ATOMIC_VALUE_EXCHANGE(errs[nerr], Qnil);
+ VALUE sig;
if (!RTEST(err)) continue;
@@ -258,6 +259,11 @@ rb_ec_cleanup(rb_execution_context_t *ec, volatile int ex)
state = NUM2INT(sig);
break;
}
+ else if (rb_obj_is_kind_of(err, rb_eSystemCallError) &&
+ FIXNUM_P(sig = rb_attr_get(err, id_signo))) {
+ state = NUM2INT(sig);
+ break;
+ }
else if (sysex == EXIT_SUCCESS) {
sysex = EXIT_FAILURE;
}
diff --git a/eval_error.c b/eval_error.c
index 847072ab98..74f09a8d8b 100644
--- a/eval_error.c
+++ b/eval_error.c
@@ -474,6 +474,10 @@ error_handle(rb_execution_context_t *ec, int ex)
rb_ivar_get(errinfo, id_signo) != INT2FIX(SIGSEGV)) {
/* no message when exiting by signal */
}
+ else if (rb_obj_is_kind_of(errinfo, rb_eSystemCallError) &&
+ FIXNUM_P(rb_attr_get(errinfo, id_signo))) {
+ /* no message when exiting by error to be mapped to signal */
+ }
else {
rb_ec_error_print(ec, errinfo);
}
diff --git a/io.c b/io.c
index 4be5f05d2f..7f43ca36d6 100644
--- a/io.c
+++ b/io.c
@@ -545,10 +545,12 @@ static rb_io_t *flush_before_seek(rb_io_t *fptr);
(fptr)->mode |= FMODE_SIGNAL_ON_EPIPE : \
(fptr)->mode &= ~FMODE_SIGNAL_ON_EPIPE)
-static int
-errno_on_write(rb_io_t *fptr)
+extern ID ruby_static_id_signo;
+
+NORETURN(static void raise_on_write(rb_io_t *fptr, int e, VALUE errinfo));
+static void
+raise_on_write(rb_io_t *fptr, int e, VALUE errinfo)
{
- int e = errno;
#if defined EPIPE
if (fptr_signal_on_epipe(fptr) && (e == EPIPE)) {
const VALUE sig =
@@ -556,14 +558,17 @@ errno_on_write(rb_io_t *fptr)
INT2FIX(SIGPIPE) - INT2FIX(0) +
# endif
INT2FIX(0);
- rb_exc_raise(rb_class_new_instance(1, &sig, rb_eSignal));
+ rb_ivar_set(errinfo, ruby_static_id_signo, sig);
}
#endif
- return e;
+ rb_exc_raise(errinfo);
}
#define rb_sys_fail_on_write(fptr) \
- rb_syserr_fail_path(errno_on_write(fptr), (fptr)->pathv)
+ do { \
+ int e = errno; \
+ raise_on_write(fptr, e, rb_syserr_new_path(e, (fptr)->pathv)); \
+ } while (0)
#define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE)
#define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) ((fptr)->mode & FMODE_TEXTMODE)