select(p1, p2 = v2, p3 = v3, p4 = v4) public

Calls select(2) system call. It monitors given arrays of IO objects, waits one or more of IO objects ready for reading, are ready for writing, and have pending exceptions respectively, and returns an array that contains arrays of those IO objects. It will return nil if optional timeout value is given and no IO object is ready in timeout seconds. peeks the buffer of IO objects for testing readability. If the IO buffer is not empty, immediately notify readability. This “peek” is only happen for IO objects. It is not happen for IO-like objects such as OpenSSL::SSL::SSLSocket.

The best way to use is invoking it after nonblocking methods such as read_nonblock, write_nonblock, etc. The methods raises an exception which is extended by IO::WaitReadable or IO::WaitWritable. The modules notify how the caller should wait with If IO::WaitReadable is raised, the caller should wait for reading. If IO::WaitWritable is raised, the caller should wait for writing.

So, blocking read (readpartial) can be emulated using read_nonblock and as follows:

  result = io_like.read_nonblock(maxlen)
rescue IO::WaitReadable[io_like])
rescue IO::WaitWritable, [io_like])

Especially, the combination of nonblocking methods and is preferred for IO like objects such as OpenSSL::SSL::SSLSocket. It has to_io method to return underlying IO object. calls to_io to obtain the file descriptor to wait.

This means that readability notified by doesn’t mean readability from OpenSSL::SSL::SSLSocket object.

Most possible situation is OpenSSL::SSL::SSLSocket buffers some data. doesn’t see the buffer. So can block when OpenSSL::SSL::SSLSocket#readpartial doesn’t block.

However several more complicated situation exists.

SSL is a protocol which is sequence of records. The record consists multiple bytes. So, the remote side of SSL sends a partial record, notifies readability but OpenSSL::SSL::SSLSocket cannot decrypt a byte and OpenSSL::SSL::SSLSocket#readpartial will blocks.

Also, the remote side can request SSL renegotiation which forces the local SSL engine writes some data. This means OpenSSL::SSL::SSLSocket#readpartial may invoke write system call and it can block. In such situation, OpenSSL::SSL::SSLSocket#read_nonblock raises IO::WaitWritable instead of blocking. So, the caller should wait for ready for writability as above example.

The combination of nonblocking methods and is also useful for streams such as tty, pipe socket socket when multiple process read form a stream.

Finally, Linux kernel developers doesn’t guarantee that readability of select(2) means readability of following read(2) even for single process. See select(2) manual on GNU/Linux system.

Invoking before IO#readpartial works well in usual. However it is not the best way to use

The writability notified by select(2) doesn’t show how many bytes writable. IO#write method blocks until given whole string is written. So, IO#write(two or more bytes) can block after writability is notified by IO#write_nonblock is required to avoid the blocking.

Blocking write (write) can be emulated using write_nonblock and as follows: IO::WaitReadable should also be rescued for SSL renegotiation in OpenSSL::SSL::SSLSocket.

while 0 < string.bytesize
    written = io_like.write_nonblock(string)
  rescue IO::WaitReadable[io_like])
  rescue IO::WaitWritable, [io_like])
  string = string.byteslice(written..-1)



an array of IO objects that wait until ready for read


an array of IO objects that wait until ready for write


an array of IO objects that wait for exceptions


a numeric value in second


rp, wp = IO.pipe
mesg = "ping "
100.times {
  # follows IO#read.  Not the best way to use
  rs, ws, =[rp], [wp])
  if r = rs[0]
    ret =
    print ret
    case ret
    when /ping/
      mesg = "pong\n"
    when /pong/
      mesg = "ping "
  if w = ws[0]


ping pong
ping pong
ping pong
Show source
Register or log in to add new notes.
November 20, 2008
1 thank