summaryrefslogtreecommitdiff
path: root/io.c
diff options
context:
space:
mode:
authornormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-12-21 00:26:24 (GMT)
committernormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-12-21 00:26:24 (GMT)
commit3b174fb7d6a8883ec64b4f866992b66d86ab3c42 (patch)
tree8a909a744d983ccbfc70ad514594654b95d2a9e2 /io.c
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
Diffstat (limited to 'io.c')
-rw-r--r--io.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/io.c b/io.c
index 24f721e..f2d1f84 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);
}