diff options
author | normal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-12-21 00:26:24 +0000 |
---|---|---|
committer | normal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2017-12-21 00:26:24 +0000 |
commit | 3b174fb7d6a8883ec64b4f866992b66d86ab3c42 (patch) | |
tree | 8a909a744d983ccbfc70ad514594654b95d2a9e2 /io.c | |
parent | b895c402a5c27f8b4604bc2293cf616c89dc41f2 (diff) | |
download | ruby-3b174fb7d6a8883ec64b4f866992b66d86ab3c42.tar.gz |
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.c | 10 |
1 files changed, 6 insertions, 4 deletions
@@ -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); } |