From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS43289 178.17.160.0/20 X-Spam-Status: No, score=-3.3 required=3.0 tests=AWL,BAYES_00,RCVD_IN_XBL, SPF_FAIL,SPF_HELO_FAIL,TO_EQ_FM_DOM_SPF_FAIL shortcircuit=no autolearn=no autolearn_force=no version=3.4.2 Received: from 80x24.org (178-17-174-14.static.as43289.net [178.17.174.14]) by dcvr.yhbt.net (Postfix) with ESMTP id 912B7211B3 for ; Thu, 6 Dec 2018 10:40:11 +0000 (UTC) From: Eric Wong To: spew@80x24.org Subject: [PATCH] flushing Date: Thu, 6 Dec 2018 10:40:08 +0000 Message-Id: <20181206104008.29153-1-e@80x24.org> List-Id: From: Eric Wong --- io.c | 56 +++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/io.c b/io.c index 1a22d34c50..0db1f2c0a8 100644 --- a/io.c +++ b/io.c @@ -144,6 +144,10 @@ off_t __syscall(quad_t number, ...); # define RUBY_PIPE_NONBLOCK_DEFAULT (0) #endif +#define RB_F_NONBLOCK_MTX (1) +#define RB_F_NONBLOCK_IO (2) +#define RB_F_NONBLOCK_ALL (RB_F_NONBLOCK_MTX|RB_F_NONBLOCK_IO) + VALUE rb_cIO; VALUE rb_eEOFError; VALUE rb_eIOError; @@ -478,6 +482,7 @@ rb_cloexec_fcntl_dupfd(int fd, int minfd) #endif static int io_fflush(rb_io_t *); +static int io_fflush2(rb_io_t *, int flags); static rb_io_t *flush_before_seek(rb_io_t *fptr); #define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE) @@ -841,13 +846,13 @@ rb_io_check_char_readable(rb_io_t *fptr) rb_raise(rb_eIOError, "not opened for reading"); } if (fptr->wbuf.len) { - if (io_fflush(fptr) < 0) + if (io_fflush2(fptr, RB_F_NONBLOCK_ALL) < 0) rb_sys_fail(0); } if (fptr->tied_io_for_writing) { rb_io_t *wfptr; GetOpenFile(fptr->tied_io_for_writing, wfptr); - if (io_fflush(wfptr) < 0) + if (io_fflush2(wfptr, RB_F_NONBLOCK_ALL) < 0) rb_sys_fail(0); } } @@ -1139,13 +1144,26 @@ io_flush_buffer_async2(VALUE arg) } static inline int -io_flush_buffer(rb_io_t *fptr) +io_flush_buffer(rb_io_t *fptr, int flags) { if (fptr->write_lock) { - if (rb_mutex_owned_p(fptr->write_lock)) + if (rb_mutex_owned_p(fptr->write_lock)) { return (int)io_flush_buffer_async2((VALUE)fptr); - else + } + else if (flags & RB_F_NONBLOCK_MTX) { + int ret = -1, err = EAGAIN; + + if (rb_mutex_trylock(fptr->write_lock) != Qfalse) { + ret = io_flush_buffer_async2((VALUE)fptr); + if (ret < 0) err = errno; + rb_mutex_unlock(fptr->write_lock); + } + errno = err; + return ret; + } + else { return (int)rb_mutex_synchronize(fptr->write_lock, io_flush_buffer_async2, (VALUE)fptr); + } } else { return (int)io_flush_buffer_async((VALUE)fptr); @@ -1153,13 +1171,16 @@ io_flush_buffer(rb_io_t *fptr) } static int -io_fflush(rb_io_t *fptr) +io_fflush2(rb_io_t *fptr, int flags) { rb_io_check_closed(fptr); if (fptr->wbuf.len == 0) return 0; - rb_io_check_closed(fptr); - while (fptr->wbuf.len > 0 && io_flush_buffer(fptr) != 0) { + while (fptr->wbuf.len > 0 && io_flush_buffer(fptr, flags) != 0) { + if (flags & RB_F_NONBLOCK_IO) { + rb_io_check_closed(fptr); + return 0; + } if (!rb_io_wait_writable(fptr->fd)) return -1; rb_io_check_closed(fptr); @@ -1167,6 +1188,12 @@ io_fflush(rb_io_t *fptr) return 0; } +static int +io_fflush(rb_io_t *fptr) +{ + return io_fflush2(fptr, 0); +} + int rb_io_wait_readable(int f) { @@ -2995,13 +3022,16 @@ io_write_nonblock(VALUE io, VALUE str, VALUE ex) io = GetWriteIO(io); GetOpenFile(io, fptr); rb_io_check_writable(fptr); - - if (io_fflush(fptr) < 0) - rb_sys_fail(0); - rb_io_set_nonblock(fptr); - n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str)); + /* + * We must block on fptr->write_lock because I/O multiplexers + * can't help with mutexes, but we may do non-blocking I/O + */ + n = (long)io_fflush2(fptr, RB_F_NONBLOCK_IO); + if (n == 0) { + n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str)); + } if (n < 0) { int e = errno; if (e == EWOULDBLOCK || e == EAGAIN) {