* io.c (rb_io_wait_readable, rb_io_wait_writable): check if the file

descriptor is closed.

* thread.c (rb_thread_wait_fd_rw): ditto.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@18027 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2008-07-11 11:51:39 +00:00
Родитель 4532c0d81e
Коммит f3fcd2e4a0
5 изменённых файлов: 53 добавлений и 16 удалений

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

@ -1,3 +1,10 @@
Fri Jul 11 20:51:36 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
* io.c (rb_io_wait_readable, rb_io_wait_writable): check if the file
descriptor is closed.
* thread.c (rb_thread_wait_fd_rw): ditto.
Fri Jul 11 16:16:43 2008 NAKAMURA Usaku <usa@ruby-lang.org>
* win32/win32.c (rb_w32_accept, rb_w32_socket, rb_w32_socketpair):

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

@ -188,7 +188,7 @@ def assert_valid_syntax(testsrc, message = '')
}
end
def assert_normal_exit(testsrc, message = '')
def assert_normal_exit(testsrc, message = '', ignore_signals = nil)
newtest
$stderr.puts "\##{@count} #{@location}" if @verbose
faildesc = nil
@ -205,28 +205,33 @@ def assert_normal_exit(testsrc, message = '')
if status.signaled?
signo = status.termsig
signame = Signal.list.invert[signo]
sigdesc = "signal #{signo}"
if signame
sigdesc = "SIG#{signame} (#{sigdesc})"
end
faildesc = pretty(testsrc, "killed by #{sigdesc}", nil)
stderr_log = File.read("assert_normal_exit_stderr.log")
if !stderr_log.empty?
faildesc << "\n" if /\n\z/ !~ faildesc
stderr_log << "\n" if /\n\z/ !~ stderr_log
stderr_log.gsub!(/^.*\n/) { '| ' + $& }
faildesc << stderr_log
unless ignore_signals and ignore_signals.include?(signame)
sigdesc = "signal #{signo}"
if signame
sigdesc = "SIG#{signame} (#{sigdesc})"
end
faildesc = pretty(testsrc, "killed by #{sigdesc}", nil)
stderr_log = File.read("assert_normal_exit_stderr.log")
if !stderr_log.empty?
faildesc << "\n" if /\n\z/ !~ faildesc
stderr_log << "\n" if /\n\z/ !~ stderr_log
stderr_log.gsub!(/^.*\n/) { '| ' + $& }
faildesc << stderr_log
end
end
end
if !faildesc
$stderr.print '.'
true
else
$stderr.print 'F'
error faildesc, message
false
end
rescue Exception => err
$stderr.print 'E'
error err.message, message
false
end
def assert_finish(timeout_seconds, testsrc, message = '')

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

@ -73,3 +73,22 @@ assert_equal 'ok', %q{
assert_normal_exit %q{
ARGF.set_encoding "foo"
}
50.times do
assert_normal_exit %q{
at_exit { p :foo }
megacontent = "abc" * 12345678
File.open("megasrc", "w") {|f| f << megacontent }
Thread.new { sleep rand*0.2; Process.kill(:INT, $$) }
r1, w1 = IO.pipe
r2, w2 = IO.pipe
t1 = Thread.new { w1 << megacontent; w1.close }
t2 = Thread.new { r2.read }
IO.copy_stream(r1, w2) rescue nil
r2.close; w2.close
r1.close; w1.close
}, '', ["INT"] or break
end

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

@ -608,6 +608,9 @@ rb_io_wait_readable(int f)
{
rb_fdset_t rfds;
if (f < 0) {
rb_raise(rb_eIOError, "closed stream");
}
switch (errno) {
case EINTR:
#if defined(ERESTART)
@ -650,6 +653,9 @@ rb_io_wait_writable(int f)
{
rb_fdset_t wfds;
if (f < 0) {
rb_raise(rb_eIOError, "closed stream");
}
switch (errno) {
case EINTR:
#if defined(ERESTART)
@ -1484,11 +1490,8 @@ io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock)
if (RSTRING_LEN(str) != len) goto modified;
if (nonblock) {
rb_io_set_nonblock(fptr);
n = rb_read_internal(fptr->fd, RSTRING_PTR(str), len);
}
else {
n = rb_read_internal(fptr->fd, RSTRING_PTR(str), len);
}
n = rb_read_internal(fptr->fd, RSTRING_PTR(str), len);
if (n < 0) {
if (!nonblock && rb_io_wait_readable(fptr->fd))
goto again;

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

@ -2018,6 +2018,9 @@ rb_thread_wait_fd_rw(int fd, int read)
int result = 0;
thread_debug("rb_thread_wait_fd_rw(%d, %s)\n", fd, read ? "read" : "write");
if (fd < 0) {
rb_raise(rb_eIOError, "closed stream");
}
while (result <= 0) {
rb_fdset_t set;
rb_fd_init(&set);