summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-12-21 00:26:24 +0000
committernormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-12-21 00:26:24 +0000
commit3b174fb7d6a8883ec64b4f866992b66d86ab3c42 (patch)
tree8a909a744d983ccbfc70ad514594654b95d2a9e2
parentb895c402a5c27f8b4604bc2293cf616c89dc41f2 (diff)
io.c: IO#pwrite uses tmp buffer to avoid parallel modification
Since we release GVL, we must freeze and duplicate the string buffer to prevent other threads from modifying our buffer while we are waiting on pwrite(2). * io.c (rb_io_pwrite): use_rb_str_tmp_frozen_{acquire/release} [Bug #14195] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61376 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--io.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/io.c b/io.c
index 24f721e8fd..f2d1f84be8 100644
--- a/io.c
+++ b/io.c
@@ -5186,12 +5186,11 @@ rb_io_pwrite(VALUE io, VALUE str, VALUE offset)
rb_io_t *fptr;
ssize_t n;
struct prdwr_internal_arg arg;
+ VALUE tmp;
if (!RB_TYPE_P(str, T_STRING))
str = rb_obj_as_string(str);
- arg.buf = RSTRING_PTR(str);
- arg.count = (size_t)RSTRING_LEN(str);
arg.offset = NUM2OFFT(offset);
io = GetWriteIO(io);
@@ -5199,10 +5198,13 @@ rb_io_pwrite(VALUE io, VALUE str, VALUE offset)
rb_io_check_writable(fptr);
arg.fd = fptr->fd;
- n = (ssize_t)rb_thread_io_blocking_region(internal_pwrite_func, &arg, fptr->fd);
- RB_GC_GUARD(str);
+ tmp = rb_str_tmp_frozen_acquire(str);
+ arg.buf = RSTRING_PTR(tmp);
+ arg.count = (size_t)RSTRING_LEN(tmp);
+ n = (ssize_t)rb_thread_io_blocking_region(internal_pwrite_func, &arg, fptr->fd);
if (n == -1) rb_sys_fail_path(fptr->pathv);
+ rb_str_tmp_frozen_release(str, tmp);
return SSIZET2NUM(n);
}