Project

General

Profile

Actions

Feature #18357

open

Proposal: stop raising when block passed to IO#each_* closes the IO

Added by georgeclaghorn (George Claghorn) over 2 years ago.

Status:
Open
Assignee:
-
Target version:
-
[ruby-core:106215]

Description

As of #17661, all of the enumeration methods on IO—e.g. each_line, each_byte, each_codepoint—raise IOError when the given block closes the IO. For example, the following code raises an IOError if the peer sends a line containing only quit:

socket.each_line do |line|
  if line.casecmp?("quit\n")
    socket.puts "Goodbye"
    socket.close
  end
end

In this example, it’s trivial to break after closing the client socket. However, in real code, it’s likely that the command-handling code will be further away from the loop and unable to break out of the loop. Either the command-handling method and all intervening methods need to pass an indication of whether to keep reading back down the stack, or the block needs to include an explicit break if io.closed?.

In my experience, when I close an IOwithin a read loop, I intend to immediately stop reading as well. It would be more agreeable if each_line et al. simply stopped reading when the IO is closed in the block instead of raising IOError.

I recognize this may be considered a breaking change. The patch for #17661 was backported to 3.0, and each_line has behaved this way for longer. This may be workable as an option to the enumeration methods, but I’m not sure an option is worth its weight compared to explicit break if io.closed?. I’m mostly asking for a decision on whether the implicit behavior is worth changing for convenience and developer happiness (and aware the answer may be no).

I’ve attached a patch containing a sample implementation for IO#each_line and updated specs. I believe this change can be implemented similarly for all other enumeration methods.


Files

patch.diff (1.66 KB) patch.diff georgeclaghorn (George Claghorn), 11/22/2021 09:02 PM

No data to display

Actions

Also available in: Atom PDF

Like0