<p>I'm reading lines of input on a TCP socket, similar to this:</p>

<pre><code>class Bla  
  def getcmd
    @sock.gets unless @sock.closed?
  end

  def start     
    srv = TCPServer.new(5000)
    @sock = srv.accept
    while ! @sock.closed?
      ans = getcmd
    end
  end
end
</code></pre>

<p>If the endpoint terminates the connection while getline() is running then gets() hangs. </p>

<p>How can I work around this? Is it necessary to do non-blocking or timed I/O?</p>

[{'answer_id': 61732, 'author': 'Orion Edwards', 'author_id': 234, 'author_profile': 'https://Stackoverflow.com/users/234', 'pm_score': -1, 'selected': False, 'text': '<p>If you believe the <a href="http://www.ruby-doc.org/stdlib/libdoc/socket/rdoc/index.html" rel="nofollow noreferrer">rdoc</a> for ruby sockets, they don\'t implement <code>gets</code>. This leads me to believe gets is being provided by a higher level of abstraction (maybe the IO libraries?) and probably isn\'t aware of socket-specific things like \'connection closed.\'</p>\n\n<p>Try using <a href="http://www.ruby-doc.org/stdlib/libdoc/socket/rdoc/classes/Socket.html#M004238" rel="nofollow noreferrer"><code>recvfrom</code></a> instead of <code>gets</code></p>\n'}, {'answer_id': 64313, 'author': 'manveru', 'author_id': 8367, 'author_profile': 'https://Stackoverflow.com/users/8367', 'pm_score': 3, 'selected': False, 'text': '<p>You can use select to see whether you can safely gets from the socket, see following implementation of a TCPServer using this technique.</p>\n\n<pre><code>require \'socket\'\n\nhost, port = \'localhost\', 7000\n\nTCPServer.open(host, port) do |server|\n  while client = server.accept\n    readfds = true\n    got = nil\n    begin\n      readfds, writefds, exceptfds = select([client], nil, nil, 0.1)\n      p :r =&gt; readfds, :w =&gt; writefds, :e =&gt; exceptfds\n\n      if readfds\n        got = client.gets \n        p got\n      end\n    end while got\n  end\nend\n</code></pre>\n\n<p>And here a client that tries to break the server:</p>\n\n<pre><code>require \'socket\'\n\nhost, port = \'localhost\', 7000\n\nTCPSocket.open(host, port) do |socket|\n  socket.puts "Hey there"\n  socket.write \'he\'\n  socket.flush\n  socket.close\nend\n</code></pre>\n'}, {'answer_id': 92255, 'author': 'Roman', 'author_id': 12695, 'author_profile': 'https://Stackoverflow.com/users/12695', 'pm_score': 2, 'selected': False, 'text': '<p>The IO#closed? returns true when both reader and writer are closed.\nIn your case, the @sock.gets returns nil, and then you call the getcmd again, and this runs in a never ending loop. You can either use select, or close the socket when gets returns nil.</p>\n'}, {'answer_id': 6005803, 'author': 'Ben Flynn', 'author_id': 449161, 'author_profile': 'https://Stackoverflow.com/users/449161', 'pm_score': 0, 'selected': False, 'text': '<p>I recommend using readpartial to read from your socket and also catching peer resets:</p>\n\n<pre><code>while true\n    sockets_ready = select(@sockets, nil, nil, nil)\n    if sockets_ready != nil\n      sockets_ready[0].each do |socket|\n        begin\n          if (socket == @server_socket)\n            # puts "Connection accepted!"\n            @sockets &lt;&lt; @server_socket.accept\n          else\n            # Received something on a client socket\n            if socket.eof?\n              # puts "Disconnect!"\n              socket.close\n              @sockets.delete(socket)\n            else\n              data = ""\n              recv_length = 256\n              while (tmp = socket.readpartial(recv_length))\n                data += tmp\n                break if (!socket.ready?)\n              end\n              listen socket, data\n            end\n          end\n        rescue Exception =&gt; exception\n          case exception\n            when Errno::ECONNRESET,Errno::ECONNABORTED,Errno::ETIMEDOUT\n              # puts "Socket: #{exception.class}"\n              @sockets.delete(socket)\n            else\n              raise exception\n          end\n        end\n      end\n    end\n  end\n</code></pre>\n\n<p>This code borrows heavily from some <a href="https://www6.software.ibm.com/developerworks/education/l-rubysocks/l-rubysocks-a4.pdf" rel="nofollow">nice IBM code</a> by M. Tim Jones. Note that @server_socket is initialized by:    </p>\n\n<pre><code>@server_socket = TCPServer.open(port)\n</code></pre>\n\n<p>@sockets is just an array of sockets.</p>\n'}, {'answer_id': 36076434, 'author': 'wakeupbuddy', 'author_id': 1464263, 'author_profile': 'https://Stackoverflow.com/users/1464263', 'pm_score': 0, 'selected': False, 'text': '<p>I simply pgrep "ruby" to find the pid, and kill -9 the pid and restart.</p>\n'}]
['https://Stackoverflow.com/questions/61675', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/3796/']