From 3b174fb7d6a8883ec64b4f866992b66d86ab3c42 Mon Sep 17 00:00:00 2001 From: normal Date: Thu, 21 Dec 2017 00:26:24 +0000 Subject: 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 --- io.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'io.c') 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); } -- cgit v1.2.3