Switch from readpartial to read_nonblock, which works around an OpenSSL deadlock. This also adds support for the openssl-nonblock gem's specific exceptions

git-svn-id: file:///home/svn/framework3/trunk@12414 4d416f70-5f16-0410-b530-b9f4589650da
unstable
HD Moore 2011-04-23 20:45:49 +00:00
parent 56049012cb
commit 9d715a1492
1 changed files with 25 additions and 13 deletions

View File

@ -47,15 +47,19 @@ module Stream
total_sent += sent total_sent += sent
end end
end end
rescue ::Errno::EAGAIN rescue ::Exception => e
# Sleep for a half a second, or until we can write again # This allows non-existent class names to be used in the rescue filter
Rex::ThreadSafe.select( nil, [ fd ], nil, 0.5 ) case e.class.to_s
# Decrement the block size to handle full sendQs better when 'Errno::EAGAIN', 'IO::WaitWritable'
block_size = 1024 # Sleep for a half a second, or until we can write again
# Try to write the data again Rex::ThreadSafe.select( nil, [ fd ], nil, 0.5 )
retry # Decrement the block size to handle full sendQs better
rescue ::IOError, ::Errno::EPIPE block_size = 1024
return nil if (fd.abortive_close == true) # Try to write the data again
retry
when 'IOError', 'Errno::EPIPE'
return nil if (fd.abortive_close == true)
end
raise $! raise $!
end end
total_sent total_sent
@ -65,11 +69,19 @@ module Stream
# This method reads data of the supplied length from the stream. # This method reads data of the supplied length from the stream.
# #
def read(length = nil, opts = {}) def read(length = nil, opts = {})
# XXX handle length being nil
begin begin
fd.readpartial(length) return fd.read_nonblock( length )
rescue ::IOError, ::EOFError, ::Errno::EPIPE rescue ::Exception => e
return nil if (fd.abortive_close == true) # This allows non-existent class names to be used in the rescue filter
case e.class.to_s
when 'Errno::EAGAIN', 'IO::WaitReadable'
# Sleep for a half a second, or until we can read again
Rex::ThreadSafe.select( [ fd ], nil, nil, 0.5 )
# Decrement the block size to handle full sendQs better
retry
when 'IOError', 'Errno::EPIPE'
return nil if (fd.abortive_close == true)
end
raise $! raise $!
end end
end end