diff options
author | Eric Wong <e@yhbt.net> | 2010-09-28 00:03:39 +0000 |
---|---|---|
committer | Eric Wong <e@yhbt.net> | 2010-09-28 00:05:33 +0000 |
commit | 2c64a1fc07d3b9a80d112e3b0e2baa7ec29c2f47 (patch) | |
tree | bef8df8273c04648c809d058b369d0ec01340024 | |
parent | f2ea9918655e8ee0576bee2950d16485031fc361 (diff) | |
download | kgio-2c64a1fc07d3b9a80d112e3b0e2baa7ec29c2f47.tar.gz |
It's possible for applications to modify the buffer during reads and writes, so make a best effort to account for those.
-rw-r--r-- | ext/kgio/kgio_ext.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/ext/kgio/kgio_ext.c b/ext/kgio/kgio_ext.c index f6f5d3e..ac6f448 100644 --- a/ext/kgio/kgio_ext.c +++ b/ext/kgio/kgio_ext.c @@ -97,6 +97,10 @@ static int read_check(struct io_args *a, long n, const char *msg, int io_wait) if (errno == EAGAIN) { if (io_wait) { wait_readable(a->io, a->fd); + + /* buf may be modified in other thread/fiber */ + rb_str_resize(a->buf, a->len); + a->ptr = RSTRING_PTR(a->buf); return -1; } else { a->buf = mKgio_WaitReadable; @@ -215,13 +219,22 @@ static void prepare_write(struct io_args *a, VALUE io, VALUE str) static int write_check(struct io_args *a, long n, const char *msg, int io_wait) { if (a->len == n) { +done: a->buf = Qnil; } else if (n == -1) { if (errno == EINTR) return -1; if (errno == EAGAIN) { if (io_wait) { + long written = RSTRING_LEN(a->buf) - a->len; + wait_writable(a->io, a->fd); + + /* buf may be modified in other thread/fiber */ + a->len = RSTRING_LEN(a->buf) - written; + if (a->len <= 0) + goto done; + a->ptr = RSTRING_PTR(a->buf) + written; return -1; } else { a->buf = mKgio_WaitWritable; |