* 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.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42212 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
glass 2013-07-28 08:49:25 +00:00
Родитель 0a7785431c
Коммит dd8f7a6cfd
5 изменённых файлов: 51 добавлений и 3 удалений

Просмотреть файл

@ -1,3 +1,12 @@
Sun Jul 28 17:38:32 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 13:04:39 2013 Masaki Matsushita <glass.saga@gmail.com> Sun Jul 28 13:04:39 2013 Masaki Matsushita <glass.saga@gmail.com>
* io.c (interpret_seek_whence): support SEEK_DATA and SEEK_HOLE. * io.c (interpret_seek_whence): support SEEK_DATA and SEEK_HOLE.

Просмотреть файл

@ -419,6 +419,7 @@ 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)
void rb_str_fill_terminator(VALUE str, const int termlen); void rb_str_fill_terminator(VALUE str, const int termlen);
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);

23
io.c
Просмотреть файл

@ -2061,15 +2061,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;
} }

Просмотреть файл

@ -1871,6 +1871,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)
{ {

Просмотреть файл

@ -2801,4 +2801,18 @@ 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
end end