about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <e@yhbt.net>2010-09-28 00:03:39 +0000
committerEric Wong <e@yhbt.net>2010-09-28 00:05:33 +0000
commit2c64a1fc07d3b9a80d112e3b0e2baa7ec29c2f47 (patch)
treebef8df8273c04648c809d058b369d0ec01340024
parentf2ea9918655e8ee0576bee2950d16485031fc361 (diff)
downloadkgio-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.c13
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;