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
Obscure bug: SIGPIPE and stack smashing when cancelling file download on Flask app that uses rpy2 #809
Comments
gunicorn uses signals to communicate between its workers: https://docs.gunicorn.org/en/stable/signals.html as means of internal communication. It appears that those get propagated to R thread (but they should not). If you can provide a minimal reproducible example that could help to fix that (which might not be easy or possible), but otherwise I would suggest to restructure you app so that R does not run in the same process as gunicorn (maybe a subprocess?) or to use a different server like Apache with mod_wsgi. |
It also happens with Flask's development server, not just with Gunicorn. But I think only on Linux, not on Windows. |
This happens on Mac as well, with django's built-in server
|
Could this be a variant of issue #769 ? |
I think what is happening is that a SIGPIPE is being generated on the python side, by the client disconnecting. However, the R thread just happens to be running at that point and the kernel delivers the SIGPIPE to it, which of course it is not ready to handle. As mentioned by @krassowski and shown here https://stackoverflow.com/a/49013048, R being in a separate process should stop this happening. |
By default R will not run in a thread. If Flask starts threads with connections a few things could go wrong since R cannot handle multithreading (see https://rpy2.github.io/doc/v3.4.x/html/rinterface.html#multithreading). |
I was running Django 'single-threaded', but in reality there were three threads for the process. The following snippet is single threaded. If you run it and send a SIGPIPE to the process it will exit in not exactly the same way as above.
I guess R installs a handler that gets the SIGPIPE - I don't know how this would be solved, as R and python both need to handle SIGPIPEs separately. |
It seems that is indeed trying to handle SIGPIPE, and this the cause of issue (e.g., rstudio/httpuv#168). I hope I can at least prevent the stack smashing from happening though. |
If I understand the R doc correctly (https://cran.r-project.org/doc/manuals/r-patched/R-exts.html#Threading-issues) it should be possible to silence R's handling of SIGPIPE. This is what line 165 in rlib.R_SignalHandlers = 0 So may be the issue is that instead of silencing R's handling or SIGPIPE there should be a custom handler to defers to the Python default handler. |
Ha! Can someone check if revision 9de03e4 solves the issue? |
This seems to solve my issues - thanks for looking into it. |
Move setting of R_SignalHandlers to before R is initialized. The fix for issue #809 will be in release 3.4.5.
Move setting of R_SignalHandlers to before R is initialized. The fix for issue #809 will be in release 3.4.5.
The fix is in the main dev branch and in release 3.4.5 (now on pypi). Closing. |
The title says it all. I have a Flask-based webapp that uses rpy2 to do some computations. The app's front end also has an unrelated download link, which I serve using Flask's
send_from_directory
method. If I start downloading the file and then cancel the download midway, I get this on Gunicorn:And this on Flask's development server:
This doesn't happen if I allow the download to complete. I'm using the latest version of rpy2. Very strange!
The text was updated successfully, but these errors were encountered: