From b17c5eba46d608f61e6035f203f49184fc43bdd0 Mon Sep 17 00:00:00 2001 From: akr Date: Fri, 26 Dec 2008 05:04:39 +0000 Subject: [PATCH] * io.c (fptr_finalize): close the IO object even if finish_writeconv or flush is failed. (finish_writeconv): don't raise. return errno or exception. (finish_writeconv_arg): removed. (finish_writeconv_sync): follow finish_writeconv change. * transcode.c (rb_econv_make_exception): new function. * include/ruby/encoding.h (rb_econv_make_exception): declared. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21059 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 12 ++++++ include/ruby/encoding.h | 3 ++ io.c | 91 ++++++++++++++++++----------------------- transcode.c | 6 +++ 4 files changed, 60 insertions(+), 52 deletions(-) diff --git a/ChangeLog b/ChangeLog index b83dde94ae..5155eb1e17 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +Fri Dec 26 14:01:38 2008 Tanaka Akira + + * io.c (fptr_finalize): close the IO object even if finish_writeconv or + flush is failed. + (finish_writeconv): don't raise. return errno or exception. + (finish_writeconv_arg): removed. + (finish_writeconv_sync): follow finish_writeconv change. + + * transcode.c (rb_econv_make_exception): new function. + + * include/ruby/encoding.h (rb_econv_make_exception): declared. + Thu Dec 25 20:57:01 2008 NARUSE, Yui * transcode.c (str_transcode0): set encoding when String#encode was diff --git a/include/ruby/encoding.h b/include/ruby/encoding.h index 64bfff5944..6a808a58cb 100644 --- a/include/ruby/encoding.h +++ b/include/ruby/encoding.h @@ -248,6 +248,9 @@ const char *rb_econv_encoding_to_insert_output(rb_econv_t *ec); /* raise an error if the last rb_econv_convert is error */ void rb_econv_check_error(rb_econv_t *ec); +/* returns an exception object or nil */ +VALUE rb_econv_make_exception(rb_econv_t *ec); + int rb_econv_putbackable(rb_econv_t *ec); void rb_econv_putback(rb_econv_t *ec, unsigned char *p, int n); diff --git a/io.c b/io.c index 1287d94f5e..aaa20c6e99 100644 --- a/io.c +++ b/io.c @@ -3034,11 +3034,12 @@ rb_io_set_close_on_exec(VALUE io, VALUE arg) #define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP) #define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv)) -static void -finish_writeconv(rb_io_t *fptr, int noraise) +static VALUE +finish_writeconv(rb_io_t *fptr) { unsigned char *ds, *dp, *de; rb_econv_result_t res; + VALUE err; if (!fptr->wbuf) { unsigned char buf[1024]; @@ -3058,104 +3059,90 @@ finish_writeconv(rb_io_t *fptr, int noraise) ds += r; } if (rb_io_wait_writable(fptr->fd)) { - if (!noraise) - rb_io_check_closed(fptr); - else if (fptr->fd < 0) - return; + if (fptr->fd < 0) + return rb_exc_new3(rb_eIOError, rb_str_new_cstr("closed stream")); goto retry; } - return; - } - if (!noraise) { - rb_econv_check_error(fptr->writeconv); - } - if (res == econv_invalid_byte_sequence || - res == econv_incomplete_input || - res == econv_undefined_conversion) { - break; + return INT2NUM(errno); } + if (!NIL_P(err = rb_econv_make_exception(fptr->writeconv))) + return err; } - return; + return Qnil; } res = econv_destination_buffer_full; while (res == econv_destination_buffer_full) { if (fptr->wbuf_len == fptr->wbuf_capa) { - if (io_fflush(fptr) < 0 && !noraise) - rb_sys_fail(0); + if (io_fflush(fptr) < 0) + return INT2NUM(errno); } ds = dp = (unsigned char *)fptr->wbuf + fptr->wbuf_off + fptr->wbuf_len; de = (unsigned char *)fptr->wbuf + fptr->wbuf_capa; res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0); fptr->wbuf_len += dp - ds; - if (!noraise) { - rb_econv_check_error(fptr->writeconv); - } - if (res == econv_invalid_byte_sequence || - res == econv_incomplete_input || - res == econv_undefined_conversion) { - break; - } + if (!NIL_P(err = rb_econv_make_exception(fptr->writeconv))) + return err; } - + return Qnil; } -struct finish_writeconv_arg { - rb_io_t *fptr; - int noraise; -}; - static VALUE finish_writeconv_sync(VALUE arg) { - struct finish_writeconv_arg *p = (struct finish_writeconv_arg *)arg; - finish_writeconv(p->fptr, p->noraise); - return Qnil; + rb_io_t *fptr = (rb_io_t *)arg; + return finish_writeconv(fptr); } static void fptr_finalize(rb_io_t *fptr, int noraise) { - int close_failure = 0; + VALUE err = Qnil; if (fptr->writeconv) { if (fptr->write_lock) { - struct finish_writeconv_arg arg; - arg.fptr = fptr; - arg.noraise = noraise; - rb_mutex_synchronize(fptr->write_lock, finish_writeconv_sync, (VALUE)&arg); + err = rb_mutex_synchronize(fptr->write_lock, finish_writeconv_sync, (VALUE)fptr); } else { - finish_writeconv(fptr, noraise); + err = finish_writeconv(fptr); } } if (fptr->wbuf_len) { - if (io_fflush(fptr) < 0 && !noraise) - rb_sys_fail(0); + if (io_fflush(fptr) < 0 && NIL_P(err)) + err = INT2NUM(errno); } - if (IS_PREP_STDIO(fptr) || - fptr->fd <= 2) { - return; + if (IS_PREP_STDIO(fptr) || fptr->fd <= 2) { + goto check_err; } if (fptr->stdio_file) { /* fptr->stdio_file is deallocated anyway * even if fclose failed. */ - if (fclose(fptr->stdio_file) < 0) - close_failure = 1; + if (fclose(fptr->stdio_file) < 0 && NIL_P(err)) + err = INT2NUM(errno); } else if (0 <= fptr->fd) { /* fptr->fd may be closed even if close fails. * POSIX doesn't specify it. * We assumes it is closed. */ - if (close(fptr->fd) < 0) - close_failure = 1; + if (close(fptr->fd) < 0 && NIL_P(err)) + err = INT2NUM(errno); } fptr->fd = -1; fptr->stdio_file = 0; fptr->mode &= ~(FMODE_READABLE|FMODE_WRITABLE); - if (close_failure && !noraise) { - rb_sys_fail_path(fptr->pathv); + + check_err: + if (!NIL_P(err) && !noraise) { + switch(TYPE(err)) { + case T_FIXNUM: + case T_BIGNUM: + errno = NUM2INT(err); + rb_sys_fail_path(fptr->pathv); + + default: + rb_exc_raise(err); + } } } diff --git a/transcode.c b/transcode.c index 7cdda7b7b2..72e26f6df2 100644 --- a/transcode.c +++ b/transcode.c @@ -3854,6 +3854,12 @@ econv_set_replacement(VALUE self, VALUE arg) return arg; } +VALUE +rb_econv_make_exception(rb_econv_t *ec) +{ + return make_econv_exception(ec); +} + void rb_econv_check_error(rb_econv_t *ec) {