Skip to content

Commit 2b90e73

Browse files
committedOct 2, 2015
Passes all but one select spec which is related to thread sleeping
Fixed +timeout+ handling so that a nil timeout is respected. Prior to this we were allocating timeval structs every time and it turns out that an empty struct and a nil value are not equivalent in behavior. Took the opportunity to refactor and DRY up some code that validated IO.select arguments.
1 parent acd40bd commit 2b90e73

File tree

1 file changed

+30
-55
lines changed

1 file changed

+30
-55
lines changed
 

‎kernel/common/io.rb

+30-55
Original file line numberDiff line numberDiff line change
@@ -713,12 +713,12 @@ def self.timer_sub(time1, time2, result)
713713
end
714714

715715
def self.make_timeval_timeout(timeout)
716-
limit = Timeval_t.new
717-
future = Timeval_t.new
718-
719716
if timeout
717+
limit = Timeval_t.new
718+
future = Timeval_t.new
719+
720720
limit[:tv_sec] = (timeout / 1_000_000.0).to_i
721-
limit[:tv_usec] = (timeout % 1_000_000.0)
721+
limit[:tv_usec] = (timeout % 1_000_000.0).to_i
722722

723723
# Get current time to be used if select is interrupted and we have to recalculate the sleep time
724724
if FFI.call_failed?(FFI::Platform::POSIX.gettimeofday(future, nil))
@@ -745,21 +745,14 @@ def self.select(readables, writables, errorables, timeout)
745745
read_set, highest_read_fd = readables.nil? ? [nil, nil] : fd_set_from_array(readables)
746746
write_set, highest_write_fd = writables.nil? ? [nil, nil] : fd_set_from_array(writables)
747747
error_set, highest_err_fd = errorables.nil? ? [nil, nil] : fd_set_from_array(errorables)
748-
max_fd = [highest_read_fd, highest_write_fd, highest_err_fd].compact.max
748+
max_fd = [highest_read_fd, highest_write_fd, highest_err_fd].compact.max || -1
749749

750750
unless const_defined?(:Timeval_t)
751751
# This is a complete hack.
752752
IO.class_eval(Rubinius::Config['rbx.platform.timeval.class'])
753753
end
754754

755755
time_limit, future = make_timeval_timeout(timeout)
756-
# debugging only...
757-
# file = File.open("/tmp/select", 'w+')
758-
# set = read_set.to_set
759-
# file.puts set.class
760-
# file.puts set.inspect
761-
# file.puts(sprintf("0x%x", set.address))
762-
# set.read_array_of_char(10).each { |char| file.puts(sprintf("%b ", char)) }
763756

764757
events = 0
765758
loop do
@@ -780,7 +773,7 @@ def self.select(readables, writables, errorables, timeout)
780773

781774
break
782775
end
783-
776+
784777
return nil if events.zero?
785778

786779
output_fds = []
@@ -789,6 +782,27 @@ def self.select(readables, writables, errorables, timeout)
789782
output_fds << collect_set_fds(errorables, error_set)
790783
return output_fds
791784
end
785+
786+
def self.validate_and_convert_argument(objects)
787+
if objects
788+
raise TypeError, "Argument must be an Array" unless objects.respond_to?(:to_ary)
789+
objects =
790+
objects.to_ary.map do |obj|
791+
if obj.kind_of? IO
792+
raise IOError, "closed stream" if obj.closed?
793+
obj
794+
else
795+
raise TypeError unless obj.respond_to?(:to_io)
796+
io = obj.to_io
797+
raise TypeError unless io
798+
raise IOError, "closed stream" if io.closed?
799+
[obj, io]
800+
end
801+
end
802+
end
803+
804+
objects
805+
end
792806
end # class Select
793807

794808
attr_accessor :external
@@ -1415,48 +1429,9 @@ def self.select(readables=nil, writables=nil, errorables=nil, timeout=nil)
14151429
timeout = Integer(timeout * 1_000_000)
14161430
end
14171431

1418-
if readables
1419-
readables =
1420-
readables.to_ary.map do |obj|
1421-
if obj.kind_of? IO
1422-
raise IOError, "closed stream" if obj.closed?
1423-
return [[obj],[],[]] unless obj.buffer_empty? # FIXME: eliminated buffer_empty? so what do we check here?
1424-
obj
1425-
else
1426-
io = obj.to_io
1427-
raise IOError, "closed stream" if io.closed?
1428-
[obj, io]
1429-
end
1430-
end
1431-
end
1432-
1433-
if writables
1434-
writables =
1435-
writables.to_ary.map do |obj|
1436-
if obj.kind_of? IO
1437-
raise IOError, "closed stream" if obj.closed?
1438-
obj
1439-
else
1440-
io = obj.to_io
1441-
raise IOError, "closed stream" if io.closed?
1442-
[obj, io]
1443-
end
1444-
end
1445-
end
1446-
1447-
if errorables
1448-
errorables =
1449-
errorables.to_ary.map do |obj|
1450-
if obj.kind_of? IO
1451-
raise IOError, "closed stream" if obj.closed?
1452-
obj
1453-
else
1454-
io = obj.to_io
1455-
raise IOError, "closed stream" if io.closed?
1456-
[obj, io]
1457-
end
1458-
end
1459-
end
1432+
readables = IO::Select.validate_and_convert_argument(readables)
1433+
writables = IO::Select.validate_and_convert_argument(writables)
1434+
errorables = IO::Select.validate_and_convert_argument(errorables)
14601435

14611436
IO::Select.select(readables, writables, errorables, timeout)
14621437
end

0 commit comments

Comments
 (0)
Please sign in to comment.