miguelgrinberg / turbo-flask

Integration of Hotwire's Turbo library with Flask.
MIT License
301 stars 35 forks source link

BrokenPipeError: [Errno 32] Broken pipe #9

Closed azat385 closed 3 years ago

azat385 commented 3 years ago

After several hours ws is crashing:

Exception in thread Thread-3:
Traceback (most recent call last):
  File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/home/azat/modbus_online/web.py", line 81, in update_load
    turbo.push(turbo.replace(render_template('loadme.html'), 'load'))
  File "/home/azat/modbus_online/venv/lib/python3.8/site-packages/turbo_flask/turbo.py", line 180, in push
    ws.send(stream)
  File "/home/azat/modbus_online/venv/lib/python3.8/site-packages/simple_websocket/ws.py", line 60, in send
    self.sock.send(out_data)
BrokenPipeError: [Errno 32] Broken pipe

turbo-flask is used according to load example

@app.context_processor
def inject_load():
    ...
    return {'data': response,}

@app.before_first_request
def before_first_request():
    threading.Thread(target=update_load).start()

def update_load():
    with app.app_context():
        while True:
            time.sleep(0.5)
            turbo.push(turbo.replace(render_template('loadme.html'), 'load'))
azat385 commented 3 years ago

How to avoid this problem?

miguelgrinberg commented 3 years ago

This occurs when the client abruptly closes their side of the connection. I have to add special handling for this situation so that the error is suppressed and the client removed from the active connection list.

miguelgrinberg commented 3 years ago

@azat385 Can I ask you to try the main branch of this repository to see if the fix addresses your problem? Thanks.

azat385 commented 3 years ago

try the main branch..

@miguelgrinberg i'd like to try. But could you explain please how to use this repository instead pip version in virtual env?

miguelgrinberg commented 3 years ago

Use this command:

pip install https://github.com/miguelgrinberg/turbo-flask/archive/main.zip
azat385 commented 3 years ago
(venv) azat@334783-azat385vds:~/modbus_online$ pip freeze
attrs==21.2.0
click==8.0.1
Flask==2.0.1
flask-sock==0.4.0
gunicorn==20.1.0
h11==0.12.0
iniconfig==1.1.1
itsdangerous==2.0.1
Jinja2==3.0.1
MarkupSafe==2.0.1
packaging==21.0
pluggy==0.13.1
py==1.10.0
pyparsing==2.4.7
pyserial==3.5
pytest==6.2.4
python-dotenv==0.19.0
simple-websocket==0.2.0
toml==0.10.2
Turbo-Flask==0.6.1.dev0
uModbus==1.0.4
Werkzeug==2.0.1
wsproto==1.0.0

While directly running app throug flask Turbo-Flask==0.6.1.dev0 works great! But with gunicorn get some error messages and turbo is stopping refreshing after a while (approx ~30sec)

(venv) azat@334783-azat385vds:~/modbus_online$ gunicorn -b 0.0.0.0:5000 web:app
[2021-08-04 13:24:24 +0300] [98694] [INFO] Starting gunicorn 20.1.0
[2021-08-04 13:24:24 +0300] [98694] [INFO] Listening at: http://0.0.0.0:5000 (98694)
[2021-08-04 13:24:24 +0300] [98694] [INFO] Using worker: sync
[2021-08-04 13:24:24 +0300] [98696] [INFO] Booting worker with pid: 98696
[2021-08-04 13:25:02 +0300] [98694] [CRITICAL] WORKER TIMEOUT (pid:98696)
[2021-08-04 13:25:02 +0300] [98696] [INFO] Worker exiting (pid: 98696)
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/home/azat/modbus_online/web.py", line 103, in update_load
    turbo.push(turbo.replace(render_template('loadme.html'), 'load'))
  File "/home/azat/modbus_online/venv/lib/python3.8/site-packages/turbo_flask/turbo.py", line 182, in push
    ws.send(stream)
  File "/home/azat/modbus_online/venv/lib/python3.8/site-packages/simple_websocket/ws.py", line 60, in send
    self.sock.send(out_data)
OSError: [Errno 9] Bad file descriptor
[2021-08-04 13:25:03 +0300] [98694] [WARNING] Worker with pid 98696 was terminated due to signal 9

what should i do next? Thank you.

miguelgrinberg commented 3 years ago

@azat385 your Gunicorn worker is timing out and restarting. Do you have any long running requests? Gunicorn has a 30 second timeout by default, your routes need to return before that time or else the worker is assumed to be hung and it is killed and restarted.

azat385 commented 3 years ago
def update_load():
    with app.app_context():
        while True:
            time.sleep(0.5)
            turbo.push(turbo.replace(render_template('loadme.html'), 'load'))

I have an infinite update cycle every second!

you can have a look on http://modbus.online/ image

reg 6 updates every sec

miguelgrinberg commented 3 years ago

How are you running Gunicorn? You need to either use threads, or an async server such as gevent or eventlet. See https://flask-sock.readthedocs.io/en/latest/web_servers.html for instructions on how to deploy Flask-Sock (the WebSocket extension used by Turbo-Flask).

azat385 commented 3 years ago

Before: gunicorn -b 0.0.0.0:5000 web:app

After: gunicorn -b 0.0.0.0:5000 web:app -k gevent

Seems to solve the problem ) Thanks a lot!