Hello, I am using Smack 4.4.6 and I found that if I wrote too many messages at once, my connection would suddenly lock. I did some digging and found this issue. I went ahead and disabled StreamManagement so that I wouldn’t depend on acks, and this helped the connection last a bit longer, but I was still hitting deadlock eventually. Note that I tested sending bursts of 1000 messages per second for several seconds, which is quite a lot, and which is in fact the scale I am working towards supporting in my application.
It appears that this deadlock comes from the XMPPTCPConnection PacketWriter. When it is .init()'d, it creates a thread that runs .writePackets(), which continually calls .nextStreamElement(), which calls queue.take(). At the same time, my thread/the user thread is ultimately calling PacketWriter.sendStreamElement(), which calls queue.put(). Here “queue” is an ArrayBlockingQueueWithShutdown.
The problem arises when this queue fills up (it is only 500 elements). In this case, queue.put() will first call lock.lockInterruptibly() and then putInternal(). It will then notFull.await(). Then, the spinning writePackets() thread will call queue.take(), which first also calls lock.lockInterruptibly(). Now, neither thread will advance, because they are both waiting on the other.
This situation arises when I am putting data into the queue faster than it can be read. There’s a few solutions that could help mitigate this:
- Have an unbounded queue, and leave it up to the developer to deal with this
- Allow the developer to get metrics on this queue so that we can ensure we aren’t going to fill it
- Probably best, ensure the dequeueing thread is not blocked by the enqueueing thread in this scenario.
Please let me know if any of this is unclear or you would like more information about it, thank you!