diff options
author | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2020-04-15 01:25:04 +0900 |
---|---|---|
committer | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2020-04-15 21:05:39 +0900 |
commit | 155f64e3c4ba23f0e85e8d69facceb21a487dccd (patch) | |
tree | f0c79b8bc3ddeedd98326dc45a5dd8cfc1917d08 | |
parent | d72fd1e45b192ab507f8170ceec1328c2aae7bb1 (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.md | 5 | ||||
-rw-r--r-- | eval.c | 6 | ||||
-rw-r--r-- | eval_error.c | 4 | ||||
-rw-r--r-- | io.c | 17 |
4 files changed, 23 insertions, 9 deletions
@@ -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 @@ -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); } @@ -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) |