Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

suspicion: EPIPE coming out of register on OSX #582

Closed
alexcrichton opened this issue Apr 2, 2017 · 2 comments · Fixed by #584
Closed

suspicion: EPIPE coming out of register on OSX #582

alexcrichton opened this issue Apr 2, 2017 · 2 comments · Fixed by #584

Comments

@alexcrichton
Copy link
Contributor

We're seeing some odd behavior on OSX in rust-lang/rust right now. We're using sccache to compile LLVM, which executes a whole lot of tokio + mio on each run. We've also got a lot of spurious failures, one of the most notorious right now is "broken pipe", which arises during this spawn.

From here on out, a lot of this is guesswork unfortunately. I've never been able to personally reproduce this, but here's my hunches. The main error happening here is that spawning a process somehow returns EPIPE. Now that's pretty odd because reviewing the syscalls that Command::spawn takes it turns out none of them can return EPIPE! I would also find it quite odd if this is the first time we find this error in process spawning, surely it seems like it would have happened before now I'd guess.

So digging more the spawn here actually translates to CommandExt::spawn_async. Note that the function there can fail for more than one reason, not just Command::spawn. The register_* functions are also fallible. They can either fail in fcntl (which I don't think can return EPIPE) or they can fail in PollEvented::new which internally bottoms out to registering an object.

So at this point my best suspicion is that register is returning EPIPE, although I have no idea why. One interesting observation is that we've only witnessed this on OSX, not on Linux or Windows. That itself is quite interesting as well! Trawling around for information on the internet related to this I stumbled across a commit in libevent which translates EPIPE from kevent to a writable notification. (e.g. doesn't punt it back to the user). That commit claims that if you register half of a broken pipe you'll get an EPIPE. Sure enough it looks like xnu does return EPIPE on a broken pipe.

So that sounds great and all until it turns out I can't even reproduce this with a broken pipe. That program works successfully! (no errors)

So all in all there's something that's:

  • OSX specific
  • Likely related to tokio/mio, but not 100% certain
  • Likely related to Poll::register, but not certain
  • Likely related to broken pipes (as this only happens under high load)

Where this leaves me I'm not entirely sure. I wanted to jot down thoughts and ideas to make sure they're written, but I'm curious what you think as well @carllerche. I could add some code to hopefully handle EPIPE and somehow translate it to writable/readable (as appropriate), but I have no way of testing such a change. We could deploy it to rust-lang/rust and pray it fixes things, but we wouldn't really know for a few weeks whether it actually worked.

@alexcrichton
Copy link
Contributor Author

Note that if we conclude and/or can prove register is returning EPIPE I'm also not certain that the fix should go in mio, it may be more suitable in tokio-core. There's a bug somewhere, just not guarnateed that it's in mio.

alexcrichton added a commit to alexcrichton/mio that referenced this issue Apr 4, 2017
This commit updates mio to ignore `EPIPE` coming out of `kevent`. It
turns out that older versions of OSX (10.10 and 10.11 have been
confirmed) will return an `EPIPE` when registering one half of a pipe
where the other half has been closed. On other platforms this is an ok
operation which just returns that the pipe is readable/writable (to
return an error/eof), so this brings the OSX behavior in line by
ignoring the error and moving to the next event.

Closes tokio-rs#582
@alexcrichton
Copy link
Contributor Author

Ok confirmed, 10.10 and 10.11 both don't like registering half of a broken pipe, I have sent #583

carllerche added a commit that referenced this issue Apr 7, 2017
This commit updates mio to ignore `EPIPE` coming out of `kevent`. It
turns out that older versions of OSX (10.10 and 10.11 have been
confirmed) will return an `EPIPE` when registering one half of a pipe
where the other half has been closed. On other platforms this is an ok
operation which just returns that the pipe is readable/writable (to
return an error/eof), so this brings the OSX behavior in line by
ignoring the error and moving to the next event.

Closes #582
alexcrichton added a commit to mozilla/sccache that referenced this issue Apr 28, 2017
Contains tokio-rs/mio#583 to fix tokio-rs/mio#582, transitively fixing
flakiness discovered in rust-lang/rust#40240.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
1 participant