mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* 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
This commit is contained in:
parent
20f5c2a3ba
commit
b17c5eba46
4 changed files with 60 additions and 52 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
||||||
|
Fri Dec 26 14:01:38 2008 Tanaka Akira <akr@fsij.org>
|
||||||
|
|
||||||
|
* 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 <naruse@ruby-lang.org>
|
Thu Dec 25 20:57:01 2008 NARUSE, Yui <naruse@ruby-lang.org>
|
||||||
|
|
||||||
* transcode.c (str_transcode0): set encoding when String#encode was
|
* transcode.c (str_transcode0): set encoding when String#encode was
|
||||||
|
|
|
@ -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 */
|
/* raise an error if the last rb_econv_convert is error */
|
||||||
void rb_econv_check_error(rb_econv_t *ec);
|
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);
|
int rb_econv_putbackable(rb_econv_t *ec);
|
||||||
void rb_econv_putback(rb_econv_t *ec, unsigned char *p, int n);
|
void rb_econv_putback(rb_econv_t *ec, unsigned char *p, int n);
|
||||||
|
|
||||||
|
|
91
io.c
91
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 IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
|
||||||
#define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
|
#define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
|
||||||
|
|
||||||
static void
|
static VALUE
|
||||||
finish_writeconv(rb_io_t *fptr, int noraise)
|
finish_writeconv(rb_io_t *fptr)
|
||||||
{
|
{
|
||||||
unsigned char *ds, *dp, *de;
|
unsigned char *ds, *dp, *de;
|
||||||
rb_econv_result_t res;
|
rb_econv_result_t res;
|
||||||
|
VALUE err;
|
||||||
|
|
||||||
if (!fptr->wbuf) {
|
if (!fptr->wbuf) {
|
||||||
unsigned char buf[1024];
|
unsigned char buf[1024];
|
||||||
|
@ -3058,104 +3059,90 @@ finish_writeconv(rb_io_t *fptr, int noraise)
|
||||||
ds += r;
|
ds += r;
|
||||||
}
|
}
|
||||||
if (rb_io_wait_writable(fptr->fd)) {
|
if (rb_io_wait_writable(fptr->fd)) {
|
||||||
if (!noraise)
|
if (fptr->fd < 0)
|
||||||
rb_io_check_closed(fptr);
|
return rb_exc_new3(rb_eIOError, rb_str_new_cstr("closed stream"));
|
||||||
else if (fptr->fd < 0)
|
|
||||||
return;
|
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
return;
|
return INT2NUM(errno);
|
||||||
}
|
|
||||||
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;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = econv_destination_buffer_full;
|
res = econv_destination_buffer_full;
|
||||||
while (res == econv_destination_buffer_full) {
|
while (res == econv_destination_buffer_full) {
|
||||||
if (fptr->wbuf_len == fptr->wbuf_capa) {
|
if (fptr->wbuf_len == fptr->wbuf_capa) {
|
||||||
if (io_fflush(fptr) < 0 && !noraise)
|
if (io_fflush(fptr) < 0)
|
||||||
rb_sys_fail(0);
|
return INT2NUM(errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
ds = dp = (unsigned char *)fptr->wbuf + fptr->wbuf_off + fptr->wbuf_len;
|
ds = dp = (unsigned char *)fptr->wbuf + fptr->wbuf_off + fptr->wbuf_len;
|
||||||
de = (unsigned char *)fptr->wbuf + fptr->wbuf_capa;
|
de = (unsigned char *)fptr->wbuf + fptr->wbuf_capa;
|
||||||
res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
|
res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
|
||||||
fptr->wbuf_len += dp - ds;
|
fptr->wbuf_len += dp - ds;
|
||||||
if (!noraise) {
|
if (!NIL_P(err = rb_econv_make_exception(fptr->writeconv)))
|
||||||
rb_econv_check_error(fptr->writeconv);
|
return err;
|
||||||
}
|
|
||||||
if (res == econv_invalid_byte_sequence ||
|
|
||||||
res == econv_incomplete_input ||
|
|
||||||
res == econv_undefined_conversion) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct finish_writeconv_arg {
|
|
||||||
rb_io_t *fptr;
|
|
||||||
int noraise;
|
|
||||||
};
|
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
finish_writeconv_sync(VALUE arg)
|
finish_writeconv_sync(VALUE arg)
|
||||||
{
|
{
|
||||||
struct finish_writeconv_arg *p = (struct finish_writeconv_arg *)arg;
|
rb_io_t *fptr = (rb_io_t *)arg;
|
||||||
finish_writeconv(p->fptr, p->noraise);
|
return finish_writeconv(fptr);
|
||||||
return Qnil;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fptr_finalize(rb_io_t *fptr, int noraise)
|
fptr_finalize(rb_io_t *fptr, int noraise)
|
||||||
{
|
{
|
||||||
int close_failure = 0;
|
VALUE err = Qnil;
|
||||||
if (fptr->writeconv) {
|
if (fptr->writeconv) {
|
||||||
if (fptr->write_lock) {
|
if (fptr->write_lock) {
|
||||||
struct finish_writeconv_arg arg;
|
err = rb_mutex_synchronize(fptr->write_lock, finish_writeconv_sync, (VALUE)fptr);
|
||||||
arg.fptr = fptr;
|
|
||||||
arg.noraise = noraise;
|
|
||||||
rb_mutex_synchronize(fptr->write_lock, finish_writeconv_sync, (VALUE)&arg);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
finish_writeconv(fptr, noraise);
|
err = finish_writeconv(fptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fptr->wbuf_len) {
|
if (fptr->wbuf_len) {
|
||||||
if (io_fflush(fptr) < 0 && !noraise)
|
if (io_fflush(fptr) < 0 && NIL_P(err))
|
||||||
rb_sys_fail(0);
|
err = INT2NUM(errno);
|
||||||
}
|
}
|
||||||
if (IS_PREP_STDIO(fptr) ||
|
if (IS_PREP_STDIO(fptr) || fptr->fd <= 2) {
|
||||||
fptr->fd <= 2) {
|
goto check_err;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (fptr->stdio_file) {
|
if (fptr->stdio_file) {
|
||||||
/* fptr->stdio_file is deallocated anyway
|
/* fptr->stdio_file is deallocated anyway
|
||||||
* even if fclose failed. */
|
* even if fclose failed. */
|
||||||
if (fclose(fptr->stdio_file) < 0)
|
if (fclose(fptr->stdio_file) < 0 && NIL_P(err))
|
||||||
close_failure = 1;
|
err = INT2NUM(errno);
|
||||||
}
|
}
|
||||||
else if (0 <= fptr->fd) {
|
else if (0 <= fptr->fd) {
|
||||||
/* fptr->fd may be closed even if close fails.
|
/* fptr->fd may be closed even if close fails.
|
||||||
* POSIX doesn't specify it.
|
* POSIX doesn't specify it.
|
||||||
* We assumes it is closed. */
|
* We assumes it is closed. */
|
||||||
if (close(fptr->fd) < 0)
|
if (close(fptr->fd) < 0 && NIL_P(err))
|
||||||
close_failure = 1;
|
err = INT2NUM(errno);
|
||||||
}
|
}
|
||||||
fptr->fd = -1;
|
fptr->fd = -1;
|
||||||
fptr->stdio_file = 0;
|
fptr->stdio_file = 0;
|
||||||
fptr->mode &= ~(FMODE_READABLE|FMODE_WRITABLE);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3854,6 +3854,12 @@ econv_set_replacement(VALUE self, VALUE arg)
|
||||||
return arg;
|
return arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VALUE
|
||||||
|
rb_econv_make_exception(rb_econv_t *ec)
|
||||||
|
{
|
||||||
|
return make_econv_exception(ec);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
rb_econv_check_error(rb_econv_t *ec)
|
rb_econv_check_error(rb_econv_t *ec)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue