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

fwrite: errno=11 in StreamIO #596

Closed
marek-obuchowicz opened this issue Sep 21, 2018 · 4 comments
Closed

fwrite: errno=11 in StreamIO #596

marek-obuchowicz opened this issue Sep 21, 2018 · 4 comments
Assignees
Milestone

Comments

@marek-obuchowicz
Copy link
Contributor

marek-obuchowicz commented Sep 21, 2018

I still have found one fwrite error case, which is not explained in the other issues. After short code analysis, it seems to me that fwrite does not handle correctly errno=11 (E_AGAIN / E_WOULDBLOCK)

Our setup and observations

  • in rabbitmq server logs I see indeed client unexpectedly closed TCP connection
  • i am connecting through AWS ELB, with idle timeout set to 3600s
  • client crashes instantly after running, no more than one second since starting, so i don't suspect connection being closed by the loadbalancer
  • client recieves error: fwrite(): send of 49 bytes failed with errno=11, in stack trace I can see that it's thrown in StreamIO->write()
  • we don't set AMQP_WITHOUT_SIGNALS and we have PHP extension pcntl installed

fwrite docs

This is explaination of errno=11

The file descriptor fd refers to a file other than a socket
and has been marked nonblocking (O_NONBLOCK), and the write
would block.  See open(2) for further details on the
O_NONBLOCK flag.

Findings in code

When looking on the implementation of StreamIO, I see that for our case isPcntlSignalEnabled() == true, so it sets socket to non-blocking. I see a select command being called in read method before calling read sysctl, but I don't see select call before write. This is OK in most cases, but according to POSIX specs, write could return errno = E_AGAIN or E_WOULDBLOCK and in that case the proper way would be to call select and then write again.

@marek-obuchowicz
Copy link
Contributor Author

I have tested workaround with define('AMQP_WITHOUT_SIGNALS', true);. This define causes StreamIO to work with stream in blocking mode and the exception stopped happening. It suggests that the blocking implementation is fine and something is not correct with non-blocking stream implementation. If you are fine with that, I can prepare a pull request with fix. Just let me know.

@lukebakken lukebakken added this to the 2.8.0 milestone Oct 8, 2018
@lukebakken lukebakken self-assigned this Oct 8, 2018
@lukebakken
Copy link
Collaborator

I'm planning on releasing an RC for 2.8.0 this week, so a pull request would be great. Thank you!

@marek-obuchowicz
Copy link
Contributor Author

marek-obuchowicz commented Oct 9, 2018

I see that it was indeed handled, but error handler was using error message to find out if it's E_AGAIN. Our app can change LANG environmental variable and cause error messages to be localised.

#599 - it changes implementation to use errno instead of error string.

@lukebakken
Copy link
Collaborator

Fixed in #599

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants