Bug #11009

closed STDOUT status does not get inherited to children processes created with exec

Added by costi (Constantin Gavrilescu) about 5 years ago. Updated about 5 years ago.

Target version:
ruby -v:
ruby 2.1.5p273 (2014-11-13 revision 48405) [x86_64-linux]


When closing STDOUT, then STDOUT.closed? returns true. In a child process started with exec, STDOUT is closed but it does closed? returns false.

Also, in the child process, writing to STDOUT fails silently, so the user has no idea that his stdout is closed.

Ruby should return the proper response to closed? and not fail silently when writing to the closed STDOUT stream.

child_mode = true if ARGV[0] == 'child_mode'
process_name = child_mode ? "CHILD" : "PARENT"

if !child_mode
  STDERR.puts "Closing stdout and forking"
  STDERR.puts "#{process_name} STDOUT closed? #{STDOUT.closed?}"
  exec 'ruby', $0, "child_mode"
  STDERR.puts "#{process_name} STDOUT closed? #{STDOUT.closed?}"

STDERR.puts "Trying to write to STDOUT a test line"
STDOUT.puts "#{process_name} test puts to STDOUT" 
STDERR.puts "Done writing STDOUT. Did you see anything?"

Updated by costi (Constantin Gavrilescu) about 5 years ago

The output of the script is:

Closing stdout and forking
PARENT STDOUT closed? true
CHILD STDOUT closed? false
Trying to write to STDOUT a test line
Done writing STDOUT. Did you see anything?

Updated by costi (Constantin Gavrilescu) about 5 years ago

Actually, the fails this way only in 1.8.7.
Ruby 2.1 child process reports the STDOUT as open and uses successfully STDOUT, even if the parent closed it, which is also strange, but not as bad.


Updated by nobu (Nobuyoshi Nakada) about 5 years ago

  • Description updated (diff)
  • Status changed from Open to Rejected

Ruby does not close the standard file descriptors 0..2 actually, but just disconnects them from the corresponding IO objects, since r23705.
And they are filled with broken pipes unless opened, since r33567.
This is because closing these descriptors often results in unexpected and bad side-effects.

You can close stdout of a child process by exec(... out: :close) if you really need it.

Also available in: Atom PDF