Broken pipe (Errno::EPIPE)
It means that whatever connection print is outputting to is no longer connected. Presumably the program began as input to some other program:
% ruby_program | another_program
What's happened is that another_program
has exited sometime before the print
in question.
Errno::EPIPE: Broken pipe exception is raised
Not sure why this has taken so long to get answered. I suspect this is "fixed" in current versions of ruby as I was unable to replicate using simplified versions of your code, but for future reference, here's how I would have structured the code:
def test_my_pipes
rd, wr = IO.pipe
fork do
rd.close
sleep 5
wr.write "Hello world"
wr.close
end
wr.close # essential
puts "Waiting for sleepy fork"
puts rd.read
rd.close
end
Note that both inside and outside the fork block, we close both rd and wr. In actual fact, only the parent process wr.close
is essential, but definitely better to close all the ends of the pipe when not needed.
If this code still breaks, would be interested to see what versions of ruby they break for.
Ruby Broken pipe @ io_write - STDOUT
Introduction
Firstly, an explanation can be found here.
Anyways, here's my thought...
When a pipe is used like this:
a | b
Both a and b are executed concurrently. b waits for standard input from a.
Speaking of Errno::EPIPE
, The Linux man page of write says:
EPIPE fd is connected to a pipe or socket whose reading end is
closed. When this happens the writing process will also
receive a SIGPIPE signal. (Thus, the write return value is
seen only if the program catches, blocks or ignores this
signal.)
Talking about the problem in the question:
When the program whoami
is run, it exits and no longer accepts standard inputs that ruby program hello.rb
is sending - resulting in a broken pipe.
Here I wrote 2 ruby programs, named p.rb and q.rb to test that:
- p.rb
#!/usr/bin/env ruby
print ?* * 100_000
- q.rb
#!/usr/bin/ruby
exit! 0
Running:
bash[~] $ ruby p.rb | ruby q.rb
Traceback (most recent call last):
2: from p.rb:2:in `<main>'
1: from p.rb:2:in `print'
p.rb:2:in `write': Broken pipe @ io_write - <STDOUT> (Errno::EPIPE)
Let's change the code of q.rb a bit, so that it accepts inputs:
#!/usr/bin/ruby -w
STDIN.gets
Running:
bash[~] $ ruby p.rb | ruby q.rb
Right, it displays nothing actually. The reason is that q.rb now waits for standard inputs. Apparently, the waiting is what matters the most here. Now, p.rb will not crash with even with STDOUT.sync
or STDOUT.flush
when piped to this q.rb.
Another Example:
- p.rb
STDOUT.sync = true
loop until print("\e[2K<<<#{Time.now.strftime('%H:%M:%S:%2N')}>>>\r")
[warning: the loop without sleep may bring up your CPU usage]
- q.rb
sleep 3
Running:
bash[~] $ time ruby p.rb | q.rb
Traceback (most recent call last):
2: from p.rb:2:in `<main>'
1: from p.rb:2:in `print'
p.rb:2:in `write': Broken pipe @ io_write - <STDOUT> (Errno::EPIPE)
real 0m3.186s
user 0m0.282s
sys 0m0.083s
You see the program crashed after 3 seconds. It will crash after 5.1 seconds if q.rb had sleep 5
. Similarly sleep 0
in q.rb will crash p.rb after 0.1 seconds. I guess the additional 0.1 seconds depends on the system because my system takes 0.1 seconds to load the ruby interpreter.
I wrote p.cr and q.cr Crystal programs to test. Crystal is compiled and doesn't take the long 0.1 seconds to load up.
The Crystal Programs:
- p.cr
STDOUT.sync = true
loop do print("\e[2KHi!\r") end rescue exit
- q.cr
sleep 3
I compiled them, and ran:
bash[~] $ time ./p | ./q
real 0m3.013s
user 0m0.007s
sys 0m0.019s
The binary ./p, in very close to 3 seconds, handles Unhandled exception: Error writing file: Broken pipe (Errno)
and exits. Again, 0.01 seconds may be taken by the two crystal programs to execute and maybe the Kernel also takes a bit time to run the processes.
Also note that STDERR#print
, STDERR#puts
, STDERR#putc
, STDERR#printf
, STDERR#write
, STDERR#syswrite
doesn't raise Errno::EPIPE even if the output is in sync.
Conclusion
Pipe is arcane. Setting STDOUT#sync
to true or using STDOUT#flush
flushes all buffered data to the underlying operating system.
When running hello.rb | whoami
, without sync, I can write 8191 bytes of data, and the program hello.rb doesn't crash. But with sync, writing 1 byte via pipe will crash hello.rb.
So when hello.rb synchronizes standard outputs with the piped program whoami
, and whoami
doesn't wait for hello.rb; hello.rb raises Errno::EPIPE
because the pipe between these two programs is broken (correct me if I am lost here).
Errno::EPIPE: Broken pipe with Net::FTP
put: PORT 10,142,96,98,199,111
You are using FTP in active mode with the private IP address 10.142.96.199. With active mode the server must create a data connection to your host, while with passive mode (PASV command instead of PORT command) the client will connect to the server.
Since the server is not on the same private network as your host (otherwise you would not be able to connect from a remote system to it) it will not be able to connect to the private IP of 10.142.96.98 given in the PORT command, because private IP addresses can not be accessed from the internet. The server will probably realize this, send some error back and close the connection. Your FTP client will probably try to send another command (like QUIT or ABOR) but since the server has already closed the connection this send will result in EPIPE.
FileZilla works probably because it will use passive mode instead of active mode. To use passive mode with Net::FTP you have to set ftp.passive = true
.
ERROR Errno::EPIPE: Broken pipe with Culerity
i believe that an upgrade of jruby to a version matching the patch level of ruby that we were running solved our issue, we had to install jruby from source to get the right one
Exception Errno::EPIPE in Passenger RequestHandler (Broken pipe)
It looks like the bug you're having was merged into Passenger master but not yet released. You can try it out by checking Passenger out from the following repository:
http://github.com/FooBarWidget/passenger/tree/master
Once you've checked it out, you want to run:
./bin/passenger-install-apache2-module
for Apache Passenger, or:
./bin/passenger-install-nginx-module
for Nginx Passenger. Since this particular issue was addressed, it should work for you.
Related Topics
What's the Difference Between Gets.Chomp() VS. Stdin.Gets.Chomp()
Differencebetween Integer and Fixnum
How to Generate Zip File Without Saving to the Disk with Ruby
How to Cleanly Initialize Attributes in Ruby with New
Ruby on Rails Rmagick on Windows 7
Rails, Postgresql, and History Triggers
Role Does Not Exist and Unable to Create Database When Using Postgresql
Devise Logged in Root Route Rails 3
Calling Another Method in Super Class in Ruby
Monkey Patching Devise (Or Any Rails Gem)
Finding Out Current Index in Each Loop (Ruby)
Asynchronous Http Request in Ruby
How to Iterate Activerecord Attributes, Including Attr_Accessor Methods
Weird Imoperfection in Ruby Blocks