Recently, when helping to convert a feature suite to use
capybara-webkit, we ran into a
problem where, about halfway through, the tests would start erroring out with
Errno::EPIPE
.
Errno::EPIPE
is a “Broken Pipe” error. A pipe in Unix is a way for data to
flow from one process to another, and a
broken pipe means that one end of the pipe isn’t connected anymore. In this
case, the pipe was broken because the webkit-server process that capybara-webkit
uses went away. And since well-behaved processes don’t normally go away unless
you ask them to, we assumed it was crashing.
With a little of digging, we found the feature that was causing the problem. Annoyingly, the error never popped up when the feature was run alone, meaning it was the interaction of multiple features or steps. After whittling away the options, we found the right situation to force the error: a feature using capybara-webkit followed by one specific scenario in a different feature (which, oddly, didn’t use any Javascript at all). Being able to reliably reproduce the error is a big step towards finding a solution.
Knowing what scenario we were dealing with, we could find the specific step that
was the source of the problem. The step makes a call to
fork
. The way
that capybara-webkit closes the browser when the tests are over is by using an
at_exit
hook, which is called when Ruby is just about to close. Forking a process clones
everything about it, including, in the case of Ruby, its at_exit
hooks. So,
what happened was that the fork executed what it needed to execute and then
exited like normal, but it meant that it took the webkit-server process with it
because of the at_exit
hooks it inherited, leaving no browser to run the
javascript-enabled features.
This was good news, though. The webkit-server process wasn’t crashing! It was
behaving exactly like it was expected to, but just a little premature. To get
around the at_exit
hooks, we call
exit!
in
the forked process, which specifically bypasses at_exit
hooks. This lets our
fork get on with its work, and it keeps the server running for the rest of the
test suite to use.
So, if you’re in the position where you have to fork in a cucumber suite and
you’re using capybara-webkit, make sure you exit!
from the fork, and you’ll
save yourself some headaches. If you can help fix this problem for good, pull
requests are welcome.