merge revision(s) 42212,42214: [Backport #8669]

* string.c: add internal API rb_str_locktmp_ensure().

	* io.c (io_fread): use rb_str_locktmp_ensure().
	  [ruby-core:56121] [Bug #8669]

	* test/ruby/test_io.rb: add a test for above.

	* io.c (io_getpartial): use rb_str_locktmp_ensure().
	  [ruby-core:56121] [Bug #8669]

	* io.c (rb_io_sysread): ditto.

	* test/ruby/test_io.rb: add tests for above.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_0_0@42216 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nagachika 2013-07-28 12:58:48 +00:00
parent 0f1fb6ff36
commit a728dd2584
6 changed files with 115 additions and 9 deletions

View file

@ -1,3 +1,21 @@
Sun Jul 28 21:50:34 2013 Masaki Matsushita <glass.saga@gmail.com>
* io.c (io_getpartial): use rb_str_locktmp_ensure().
[ruby-core:56121] [Bug #8669]
* io.c (rb_io_sysread): ditto.
* test/ruby/test_io.rb: add tests for above.
Sun Jul 28 21:50:34 2013 Masaki Matsushita <glass.saga@gmail.com>
* string.c: add internal API rb_str_locktmp_ensure().
* io.c (io_fread): use rb_str_locktmp_ensure().
[ruby-core:56121] [Bug #8669]
* test/ruby/test_io.rb: add a test for above.
Sun Jul 28 21:44:57 2013 Eric Hodel <drbrain@segment7.net> Sun Jul 28 21:44:57 2013 Eric Hodel <drbrain@segment7.net>
* ext/openssl/ossl_asn1.c (asn1time_to_time): Implement YYMMDDhhmmZ * ext/openssl/ossl_asn1.c (asn1time_to_time): Implement YYMMDDhhmmZ

View file

@ -282,6 +282,7 @@ VALUE rb_str_quote_unprintable(VALUE);
VALUE rb_id_quote_unprintable(ID); VALUE rb_id_quote_unprintable(ID);
#define QUOTE(str) rb_str_quote_unprintable(str) #define QUOTE(str) rb_str_quote_unprintable(str)
#define QUOTE_ID(id) rb_id_quote_unprintable(id) #define QUOTE_ID(id) rb_id_quote_unprintable(id)
VALUE rb_str_locktmp_ensure(VALUE str, VALUE (*func)(VALUE), VALUE arg);
/* struct.c */ /* struct.c */
VALUE rb_struct_init_copy(VALUE copy, VALUE s); VALUE rb_struct_init_copy(VALUE copy, VALUE s);

54
io.c
View file

@ -2021,15 +2021,32 @@ io_bufread(char *ptr, long len, rb_io_t *fptr)
static void io_setstrbuf(VALUE *str, long len); static void io_setstrbuf(VALUE *str, long len);
struct bufread_arg {
char *str_ptr;
long len;
rb_io_t *fptr;
};
static VALUE
bufread_call(VALUE arg)
{
struct bufread_arg *p = (struct bufread_arg *)arg;
p->len = io_bufread(p->str_ptr, p->len, p->fptr);
return Qundef;
}
static long static long
io_fread(VALUE str, long offset, long size, rb_io_t *fptr) io_fread(VALUE str, long offset, long size, rb_io_t *fptr)
{ {
long len; long len;
struct bufread_arg arg;
io_setstrbuf(&str, offset + size); io_setstrbuf(&str, offset + size);
rb_str_locktmp(str); arg.str_ptr = RSTRING_PTR(str) + offset;
len = io_bufread(RSTRING_PTR(str) + offset, size, fptr); arg.len = size;
rb_str_unlocktmp(str); arg.fptr = fptr;
rb_str_locktmp_ensure(str, bufread_call, (VALUE)&arg);
len = arg.len;
if (len < 0) rb_sys_fail_path(fptr->pathv); if (len < 0) rb_sys_fail_path(fptr->pathv);
return len; return len;
} }
@ -2337,12 +2354,27 @@ rb_io_set_nonblock(rb_io_t *fptr)
} }
} }
struct read_internal_arg {
int fd;
char *str_ptr;
long len;
};
static VALUE
read_internal_call(VALUE arg)
{
struct read_internal_arg *p = (struct read_internal_arg *)arg;
p->len = rb_read_internal(p->fd, p->str_ptr, p->len);
return Qundef;
}
static VALUE static VALUE
io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock) io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock)
{ {
rb_io_t *fptr; rb_io_t *fptr;
VALUE length, str; VALUE length, str;
long n, len; long n, len;
struct read_internal_arg arg;
rb_scan_args(argc, argv, "11", &length, &str); rb_scan_args(argc, argv, "11", &length, &str);
@ -2368,9 +2400,11 @@ io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock)
rb_io_set_nonblock(fptr); rb_io_set_nonblock(fptr);
} }
io_setstrbuf(&str, len); io_setstrbuf(&str, len);
rb_str_locktmp(str); arg.fd = fptr->fd;
n = rb_read_internal(fptr->fd, RSTRING_PTR(str), len); arg.str_ptr = RSTRING_PTR(str);
rb_str_unlocktmp(str); arg.len = len;
rb_str_locktmp_ensure(str, read_internal_call, (VALUE)&arg);
n = arg.len;
if (n < 0) { if (n < 0) {
if (!nonblock && rb_io_wait_readable(fptr->fd)) if (!nonblock && rb_io_wait_readable(fptr->fd))
goto again; goto again;
@ -4508,6 +4542,7 @@ rb_io_sysread(int argc, VALUE *argv, VALUE io)
VALUE len, str; VALUE len, str;
rb_io_t *fptr; rb_io_t *fptr;
long n, ilen; long n, ilen;
struct read_internal_arg arg;
rb_scan_args(argc, argv, "11", &len, &str); rb_scan_args(argc, argv, "11", &len, &str);
ilen = NUM2LONG(len); ilen = NUM2LONG(len);
@ -4537,8 +4572,11 @@ rb_io_sysread(int argc, VALUE *argv, VALUE io)
io_setstrbuf(&str, ilen); io_setstrbuf(&str, ilen);
rb_str_locktmp(str); rb_str_locktmp(str);
n = rb_read_internal(fptr->fd, RSTRING_PTR(str), ilen); arg.fd = fptr->fd;
rb_str_unlocktmp(str); arg.str_ptr = RSTRING_PTR(str);
arg.len = ilen;
rb_ensure(read_internal_call, (VALUE)&arg, rb_str_unlocktmp, str);
n = arg.len;
if (n == -1) { if (n == -1) {
rb_sys_fail_path(fptr->pathv); rb_sys_fail_path(fptr->pathv);

View file

@ -1826,6 +1826,13 @@ rb_str_unlocktmp(VALUE str)
return str; return str;
} }
VALUE
rb_str_locktmp_ensure(VALUE str, VALUE (*func)(VALUE), VALUE arg)
{
rb_str_locktmp(str);
return rb_ensure(func, arg, rb_str_unlocktmp, str);
}
void void
rb_str_set_len(VALUE str, long len) rb_str_set_len(VALUE str, long len)
{ {

View file

@ -2710,4 +2710,46 @@ End
end end
} }
end if /mswin|mingw/ =~ RUBY_PLATFORM end if /mswin|mingw/ =~ RUBY_PLATFORM
def test_read_unlocktmp_ensure
bug8669 = '[ruby-core:56121] [Bug #8669]'
str = ""
r, = IO.pipe
t = Thread.new { r.read(nil, str) }
sleep 0.1 until t.stop?
t.raise
sleep 0.1 while t.alive?
assert_nothing_raised(RuntimeError, bug8669) { str.clear }
ensure
t.kill
end
def test_readpartial_unlocktmp_ensure
bug8669 = '[ruby-core:56121] [Bug #8669]'
str = ""
r, = IO.pipe
t = Thread.new { r.readpartial(4096, str) }
sleep 0.1 until t.stop?
t.raise
sleep 0.1 while t.alive?
assert_nothing_raised(RuntimeError, bug8669) { str.clear }
ensure
t.kill
end
def test_sysread_unlocktmp_ensure
bug8669 = '[ruby-core:56121] [Bug #8669]'
str = ""
r, = IO.pipe
t = Thread.new { r.sysread(4096, str) }
sleep 0.1 until t.stop?
t.raise
sleep 0.1 while t.alive?
assert_nothing_raised(RuntimeError, bug8669) { str.clear }
ensure
t.kill
end
end end

View file

@ -1,6 +1,6 @@
#define RUBY_VERSION "2.0.0" #define RUBY_VERSION "2.0.0"
#define RUBY_RELEASE_DATE "2013-07-28" #define RUBY_RELEASE_DATE "2013-07-28"
#define RUBY_PATCHLEVEL 281 #define RUBY_PATCHLEVEL 282
#define RUBY_RELEASE_YEAR 2013 #define RUBY_RELEASE_YEAR 2013
#define RUBY_RELEASE_MONTH 7 #define RUBY_RELEASE_MONTH 7