Client doesn't receive messages from server when sent from separate thread
See original GitHub issueHello,
I’ve done a lot of digging on the issue of using different threads with Flask-SocketIO. I feel like my problem is incredibly simple, although it’s possible I’m missing something conceptually important.
I’m trying to send a message to the client using a background thread, which reads from an event queue, like this:
@app.route("/all_sims/", methods=["GET"])
def all_sims():
...
t = threading.Thread(target=check_sim_status, args=(sb.event_queue,), daemon=True)
t.start()
# thread target
def check_sim_status(queue):
while True:
message = queue.get()
print("MESSAGE IN SITE: " + str(message))
# with app.app_context():
socketio.emit("progressbar", json.dumps(message))
socketio.sleep(0)
queue.task_done()
if __name__ == "__main__":
socketio.run(app, debug=True)
Socket.io seems to ignore the emit call, no debug line is printed and the program goes on its way. Other calls within decorators communicate with the client site just fine.
Originally I was just using standard python threads for this event queue, but other posts (such as https://github.com/miguelgrinberg/python-socketio/issues/16) talked about monkey patching with eventlet, so I tried that as well. I got the infinite recursion bug (as seen here https://github.com/eventlet/eventlet/issues/371), so I couldn’t proceed.
Another post recommended adding socketio.sleep(0)
after my emit, but the message does not show up on the client, and it additionally throws a greenlet exception:
Traceback (most recent call last):
File "C:\Users\reedt\AppData\Local\Programs\Python\Python36\lib\site-packages\eventlet\queue.py", line 118, in switch
self.greenlet.switch(value)
greenlet.error: cannot switch to a different thread
Is there something obvious I’m doing wrong? I don’t have any performance requirements right now, I just want to send a message from a background thread.
Issue Analytics
- State:
- Created 6 years ago
- Reactions:3
- Comments:8 (3 by maintainers)
I don’t have any terribly blocking I/O on my main thread. My program uses subprocess and thread pools to do expensive work in another program, and wait on the results, but this processing does not touch socket.io.
Now, I’ve stripped out all manually created threads and eventlet entirely from my reporter. It now calls the
socketio.emit
function directly, I’ve verified the method is called correctly, but I still don’t see any messages being sent or coming through. The handshake is done just fine. I’m not sure there’s a simpler use case than this:and internally
I’m sorry I’m posting a lot on this thread, I’m just surprised by the complexity using this library. It really doesn’t seem that nuanced of a problem on the surface.
Well, for starters, eventlet is a single-threaded framework. Anything that interacts in any way with eventlet must be all on the same thread. You can use other threads, I guess, but there must be no interaction between the eventlet thread (usually the main thread) and your other threads, unless you manage that interaction exclusively through eventlet.
The reason for all these conditions is that for eventlet to function only non-blocking functions must be used. A lot of the standard library functions are blocking, so any blocking call that you make will prevent eventlet from running. And this, can be the reason why your emits are not working.