-
Notifications
You must be signed in to change notification settings - Fork 41
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
Message frames might be interleaved when sending from multiple greenlets #84
Comments
@awestendorf, I'll be happy to hear your opinion about this.
Thanks! |
This should only be a problem when you're using the same channel across greenlets/eventlets/threads though right? |
True. It's a common use case, no? |
It is, I just wanted to make sure I understood the problem correctly. The simplest case would be to create a channel, or pull one from a pool, for each publish on each thread. Although there's a limit to the number of channel ids, they're relatively light on both sides of the connection. There's
In either case where we handle a lock, I think we shouldn't assume that the user has monkey-patched the thread library, and so there will have to be some abstractions that allow |
Actually, with regard to option I'm leaning in the direction of a helper such as |
Perhaps a way around all those complications and to fix the bug is to change |
That sounds simpler. |
Short update: the refactoring is more significant that I expected. We currently bypassed the issue with application-level semaphores, hope to get back to this soon. |
When publishing a large message,
BasicClass.publish
creates multiple frames and sends them one by one.When using async transports such as
gevent
, or the currently unsupportedeventlet
, there is no guarantee that we won't switch to another greenlet between frames.When multiple greenlets use the same connection to publish large messages, frames might get interleaved. Today, this doesn't occur with
gevent
by chance - but future changes ingevent
s greenlet switching mechanism might break this.I've come across this problem with an
eventlet
Transport (which I will later contribute tohaigha
), in which the problem occurs. It's easy to reproduce - I spawn multiple publishers which continuously publish large messages, and very soon after I get disconnected from RabbitMQ with this message (or a similar one):Connection closed: 505 : UNEXPECTED_FRAME - expected content body, got non content body frame instead
Tracing the operations done shows the exact problem - multiple greenlets are waiting on the single
EventletTransport._write_lock
(similarly toGeventTransport._write_lock
), andsend_frame
calls are interleaved.A possible solution would be to acquire and release a semaphore for each message, not each frame... but the locking mechanism, today, is part of
BasicClass
and notTransport
thus can't be library specific.The text was updated successfully, but these errors were encountered: