summaryrefslogtreecommitdiff
path: root/io.c
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-12-26 09:05:47 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-12-26 09:05:47 +0000
commitb729ec53a240564bdb94b1a6c5ae943c67f8c49d (patch)
tree17b9b2a8f52450416d205cfe3f2350b1ce29fb28 /io.c
parent3beeeffb97386cf7c96c98e2c6b4f1fee0735c06 (diff)
* io.c (fptr_finalize): don't allocate objects if noraise.
(finish_writeconv): add noalloc argument to be able to avoid object allocation. (finish_writeconv_arg): introduced again. (finish_writeconv_sync): follow the above change. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21068 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'io.c')
-rw-r--r--io.c45
1 files changed, 29 insertions, 16 deletions
diff --git a/io.c b/io.c
index aaa20c6e99..ce0c35048b 100644
--- a/io.c
+++ b/io.c
@@ -3035,11 +3035,10 @@ rb_io_set_close_on_exec(VALUE io, VALUE arg)
#define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
static VALUE
-finish_writeconv(rb_io_t *fptr)
+finish_writeconv(rb_io_t *fptr, int noalloc)
{
unsigned char *ds, *dp, *de;
rb_econv_result_t res;
- VALUE err;
if (!fptr->wbuf) {
unsigned char buf[1024];
@@ -3060,13 +3059,16 @@ finish_writeconv(rb_io_t *fptr)
}
if (rb_io_wait_writable(fptr->fd)) {
if (fptr->fd < 0)
- return rb_exc_new3(rb_eIOError, rb_str_new_cstr("closed stream"));
+ return noalloc ? Qtrue : rb_exc_new3(rb_eIOError, rb_str_new_cstr("closed stream"));
goto retry;
}
- return INT2NUM(errno);
+ return noalloc ? Qtrue : INT2NUM(errno);
+ }
+ if (res == econv_invalid_byte_sequence ||
+ res == econv_incomplete_input ||
+ res == econv_undefined_conversion) {
+ return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
}
- if (!NIL_P(err = rb_econv_make_exception(fptr->writeconv)))
- return err;
}
return Qnil;
@@ -3076,24 +3078,32 @@ finish_writeconv(rb_io_t *fptr)
while (res == econv_destination_buffer_full) {
if (fptr->wbuf_len == fptr->wbuf_capa) {
if (io_fflush(fptr) < 0)
- return INT2NUM(errno);
+ return noalloc ? Qtrue : 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 (!NIL_P(err = rb_econv_make_exception(fptr->writeconv)))
- return err;
+ if (res == econv_invalid_byte_sequence ||
+ res == econv_incomplete_input ||
+ res == econv_undefined_conversion) {
+ return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
+ }
}
return Qnil;
}
+struct finish_writeconv_arg {
+ rb_io_t *fptr;
+ int noalloc;
+};
+
static VALUE
finish_writeconv_sync(VALUE arg)
{
- rb_io_t *fptr = (rb_io_t *)arg;
- return finish_writeconv(fptr);
+ struct finish_writeconv_arg *p = (struct finish_writeconv_arg *)arg;
+ return finish_writeconv(p->fptr, p->noalloc);
}
static void
@@ -3102,15 +3112,18 @@ fptr_finalize(rb_io_t *fptr, int noraise)
VALUE err = Qnil;
if (fptr->writeconv) {
if (fptr->write_lock) {
- err = rb_mutex_synchronize(fptr->write_lock, finish_writeconv_sync, (VALUE)fptr);
+ struct finish_writeconv_arg arg;
+ arg.fptr = fptr;
+ arg.noalloc = noraise;
+ err = rb_mutex_synchronize(fptr->write_lock, finish_writeconv_sync, (VALUE)&arg);
}
else {
- err = finish_writeconv(fptr);
+ err = finish_writeconv(fptr, noraise);
}
}
if (fptr->wbuf_len) {
if (io_fflush(fptr) < 0 && NIL_P(err))
- err = INT2NUM(errno);
+ err = noraise ? Qtrue : INT2NUM(errno);
}
if (IS_PREP_STDIO(fptr) || fptr->fd <= 2) {
goto check_err;
@@ -3119,14 +3132,14 @@ fptr_finalize(rb_io_t *fptr, int noraise)
/* fptr->stdio_file is deallocated anyway
* even if fclose failed. */
if (fclose(fptr->stdio_file) < 0 && NIL_P(err))
- err = INT2NUM(errno);
+ err = noraise ? Qtrue : 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 && NIL_P(err))
- err = INT2NUM(errno);
+ err = noraise ? Qtrue : INT2NUM(errno);
}
fptr->fd = -1;
fptr->stdio_file = 0;