Title: Deadlock SocketIoSocket.leaveAllRooms vs SocketIoMemoryAdapter.remove · Issue #8 · socketio/socket.io-server-java · GitHub
Open Graph Title: Deadlock SocketIoSocket.leaveAllRooms vs SocketIoMemoryAdapter.remove · Issue #8 · socketio/socket.io-server-java
X Title: Deadlock SocketIoSocket.leaveAllRooms vs SocketIoMemoryAdapter.remove · Issue #8 · socketio/socket.io-server-java
Description: I have a chat system with the back end built on socket.io-server-java. When a client disconnects, the system broadcasts a message to the room that the client was in. This is working very nicely, thank you, except that when multiple clien...
Open Graph Description: I have a chat system with the back end built on socket.io-server-java. When a client disconnects, the system broadcasts a message to the room that the client was in. This is working very nicely, th...
X Description: I have a chat system with the back end built on socket.io-server-java. When a client disconnects, the system broadcasts a message to the room that the client was in. This is working very nicely, th...
Opengraph URL: https://github.com/socketio/socket.io-server-java/issues/8
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Deadlock SocketIoSocket.leaveAllRooms vs SocketIoMemoryAdapter.remove","articleBody":"I have a chat system with the back end built on socket.io-server-java. When a client disconnects, the system broadcasts a message to the room that the client was in.\r\n\r\nThis is working very nicely, thank you, except that when multiple clients leave at almost exactly the same time I hit a deadlock. The stack trace below demonstrates this.\r\n\r\nThe first thread is processing closing a connection. It holds the lock to the SocketIoSocket being closed (0x00000007b37007a8) and as part of running SocketIoSocket leaveAllRooms it is waiting on acquiring the lock to the SocketIoMemoryAdapter (0x00000007b3901978) to run its remove method.\r\n\r\nThe second thread is processing closing a connection - I assume from a different client. As part of that, on \"disconnect\" I have a listener registered that broadcasts a message to a room. This thread holds the lock to the SocketIoMemoryAdapter (0x00000007b3901978) because it is in the SocketIoMemoryAdapter broadcast method. Somehow that broadcast is throwing an IOException - I suspect trying to broadcast to the socket that the first thread is in the middle of closing. As part of processing that exception, it is attempting to close the problematic socket, which includes running SocketIoSocket method leaveAllRooms, and in doing so its trying to acquire the lock on that SocketIoSocket (0x00000007b37007a8). Hence the deadlock.\r\n\r\nIs this a known limitation, or is it something you could look at fixing please? Is there any workaround?\r\n\r\nI'm running version 4.0.1 in a a web app deployed as an EAR file in WildFly 26.1.1.\r\n\r\n```\r\n\"default task-572\" #2020 prio=5 os_prio=0 cpu=15.63ms elapsed=6490.38s allocated=14200B defined_classes=0 tid=0x00000203fa9c7000 nid=0x4608 waiting for monitor entry [0x00000036229fe000]\r\n java.lang.Thread.State: BLOCKED (on object monitor)\r\n\tat io.socket.socketio.server.SocketIoMemoryAdapter.remove(SocketIoMemoryAdapter.java:92)\r\n\t- waiting to lock \u003c0x00000007b3901978\u003e (a io.socket.socketio.server.SocketIoMemoryAdapter)\r\n\tat io.socket.socketio.server.SocketIoSocket.leaveAllRooms(SocketIoSocket.java:268)\r\n\t- locked \u003c0x00000007b37007a8\u003e (a io.socket.socketio.server.SocketIoSocket)\r\n\tat io.socket.socketio.server.SocketIoSocket.onClose(SocketIoSocket.java:364)\r\n\tat io.socket.socketio.server.SocketIoSocket.onDisconnect(SocketIoSocket.java:357)\r\n\tat io.socket.socketio.server.SocketIoSocket.onPacket(SocketIoSocket.java:336)\r\n\tat io.socket.socketio.server.SocketIoClient.lambda$setup$1(SocketIoClient.java:163)\r\n\tat io.socket.socketio.server.SocketIoClient$$Lambda$3548/0x0000000803770440.call(Unknown Source)\r\n\tat io.socket.socketio.server.parser.IOParser$Decoder.add(IOParser.java:99)\r\n\tat io.socket.socketio.server.SocketIoClient.lambda$setup$2(SocketIoClient.java:171)\r\n\tat io.socket.socketio.server.SocketIoClient$$Lambda$3549/0x0000000803770840.call(Unknown Source)\r\n\tat io.socket.engineio.server.Emitter.emit(Emitter.java:123)\r\n\tat io.socket.engineio.server.EngineIoSocket.emit(EngineIoSocket.java:187)\r\n\tat io.socket.engineio.server.EngineIoSocket.onPacket(EngineIoSocket.java:400)\r\n\tat io.socket.engineio.server.EngineIoSocket.lambda$setTransport$10(EngineIoSocket.java:303)\r\n\tat io.socket.engineio.server.EngineIoSocket$$Lambda$3542/0x0000000803732440.call(Unknown Source)\r\n\tat io.socket.engineio.server.Emitter.emit(Emitter.java:123)\r\n\tat io.socket.engineio.server.Transport.onPacket(Transport.java:102)\r\n\tat io.socket.engineio.server.Transport.onData(Transport.java:111)\r\n\tat io.socket.engineio.server.transport.WebSocket.lambda$new$0(WebSocket.java:26)\r\n\tat io.socket.engineio.server.transport.WebSocket$$Lambda$3556/0x0000000803772440.call(Unknown Source)\r\n\tat io.socket.engineio.server.Emitter.emit(Emitter.java:123)\r\n[...my @OnMessage method in my @ServerEndpoint class]\r\n```\r\n\r\n```\r\n\"default task-558\" #2006 prio=5 os_prio=0 cpu=15.63ms elapsed=6490.39s allocated=60368B defined_classes=0 tid=0x00000203f3b80000 nid=0x52a4 waiting for monitor entry [0x00000036219fc000]\r\n java.lang.Thread.State: BLOCKED (on object monitor)\r\n\tat io.socket.socketio.server.SocketIoSocket.leaveAllRooms(SocketIoSocket.java:267)\r\n\t- waiting to lock \u003c0x00000007b37007a8\u003e (a io.socket.socketio.server.SocketIoSocket)\r\n\tat io.socket.socketio.server.SocketIoSocket.onClose(SocketIoSocket.java:364)\r\n\tat io.socket.socketio.server.SocketIoClient.onClose(SocketIoClient.java:206)\r\n\tat io.socket.socketio.server.SocketIoClient.lambda$setup$4(SocketIoClient.java:180)\r\n\tat io.socket.socketio.server.SocketIoClient$$Lambda$3551/0x0000000803771040.call(Unknown Source)\r\n\tat io.socket.engineio.server.Emitter.emit(Emitter.java:123)\r\n\tat io.socket.engineio.server.EngineIoSocket.emit(EngineIoSocket.java:187)\r\n\tat io.socket.engineio.server.EngineIoSocket.onClose(EngineIoSocket.java:369)\r\n\tat io.socket.engineio.server.EngineIoSocket.onError(EngineIoSocket.java:374)\r\n\tat io.socket.engineio.server.EngineIoSocket.lambda$setTransport$8(EngineIoSocket.java:298)\r\n\tat io.socket.engineio.server.EngineIoSocket$$Lambda$3540/0x0000000803732c40.call(Unknown Source)\r\n\tat io.socket.engineio.server.Emitter$OnceListener.call(Emitter.java:37)\r\n\tat io.socket.engineio.server.Emitter.emit(Emitter.java:123)\r\n\tat io.socket.engineio.server.Transport.onError(Transport.java:92)\r\n\tat io.socket.engineio.server.transport.WebSocket.lambda$send$3(WebSocket.java:54)\r\n\tat io.socket.engineio.server.transport.WebSocket$$Lambda$3564/0x0000000803774440.call(Unknown Source)\r\n\tat io.socket.engineio.server.parser.ParserV4.encodePacket(ParserV4.java:36)\r\n\tat io.socket.engineio.server.transport.WebSocket.send(WebSocket.java:58)\r\n\tat io.socket.engineio.server.EngineIoSocket.flush(EngineIoSocket.java:422)\r\n\t- locked \u003c0x00000007b3700bf8\u003e (a java.lang.Object)\r\n\tat io.socket.engineio.server.EngineIoSocket.sendPacket(EngineIoSocket.java:412)\r\n\t- locked \u003c0x00000007b3700bf8\u003e (a java.lang.Object)\r\n\tat io.socket.engineio.server.EngineIoSocket.send(EngineIoSocket.java:114)\r\n\tat io.socket.socketio.server.SocketIoClient.lambda$sendPacket$0(SocketIoClient.java:74)\r\n\tat io.socket.socketio.server.SocketIoClient$$Lambda$3554/0x0000000803771c40.call(Unknown Source)\r\n\tat io.socket.socketio.server.parser.IOParser$Encoder.encode(IOParser.java:37)\r\n\tat io.socket.socketio.server.SocketIoClient.sendPacket(SocketIoClient.java:68)\r\n\tat io.socket.socketio.server.SocketIoSocket.sendPacket(SocketIoSocket.java:382)\r\n\tat io.socket.socketio.server.SocketIoMemoryAdapter.broadcast(SocketIoMemoryAdapter.java:52)\r\n\t- locked \u003c0x00000007b3901978\u003e (a io.socket.socketio.server.SocketIoMemoryAdapter)\r\n\tat io.socket.socketio.server.SocketIoAdapter.broadcast(SocketIoAdapter.java:59)\r\n\tat io.socket.socketio.server.SocketIoNamespaceImpl.broadcast(SocketIoNamespaceImpl.java:32)\r\n\tat io.socket.socketio.server.SocketIoNamespace.broadcast(SocketIoNamespace.java:60)\r\n[...my code that responds to a client disconnecting and broadcasts a message to the room...]\r\n\tat io.socket.engineio.server.Emitter.emit(Emitter.java:123)\r\n\tat io.socket.socketio.server.SocketIoSocket.onClose(SocketIoSocket.java:370)\r\n\tat io.socket.socketio.server.SocketIoSocket.onDisconnect(SocketIoSocket.java:357)\r\n\tat io.socket.socketio.server.SocketIoSocket.onPacket(SocketIoSocket.java:336)\r\n\tat io.socket.socketio.server.SocketIoClient.lambda$setup$1(SocketIoClient.java:163)\r\n\tat io.socket.socketio.server.SocketIoClient$$Lambda$3548/0x0000000803770440.call(Unknown Source)\r\n\tat io.socket.socketio.server.parser.IOParser$Decoder.add(IOParser.java:99)\r\n\tat io.socket.socketio.server.SocketIoClient.lambda$setup$2(SocketIoClient.java:171)\r\n\tat io.socket.socketio.server.SocketIoClient$$Lambda$3549/0x0000000803770840.call(Unknown Source)\r\n\tat io.socket.engineio.server.Emitter.emit(Emitter.java:123)\r\n\tat io.socket.engineio.server.EngineIoSocket.emit(EngineIoSocket.java:187)\r\n\tat io.socket.engineio.server.EngineIoSocket.onPacket(EngineIoSocket.java:400)\r\n\tat io.socket.engineio.server.EngineIoSocket.lambda$setTransport$10(EngineIoSocket.java:303)\r\n\tat io.socket.engineio.server.EngineIoSocket$$Lambda$3542/0x0000000803732440.call(Unknown Source)\r\n\tat io.socket.engineio.server.Emitter.emit(Emitter.java:123)\r\n\tat io.socket.engineio.server.Transport.onPacket(Transport.java:102)\r\n\tat io.socket.engineio.server.Transport.onData(Transport.java:111)\r\n\tat io.socket.engineio.server.transport.WebSocket.lambda$new$0(WebSocket.java:26)\r\n\tat io.socket.engineio.server.transport.WebSocket$$Lambda$3556/0x0000000803772440.call(Unknown Source)\r\n\tat io.socket.engineio.server.Emitter.emit(Emitter.java:123)\r\n[...my @OnMessage method in my @ServerEndpoint class]\r\n```\r\n","author":{"url":"https://github.com/paulthomson78","@type":"Person","name":"paulthomson78"},"datePublished":"2022-11-15T14:52:05.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":1},"url":"https://github.com/8/socket.io-server-java/issues/8"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:bb133fc5-12fc-c204-db48-daeb8a9f9c2b |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | E0B4:33DAD9:8EA7F9:C7FC23:6A4E7AAF |
| html-safe-nonce | ee8206e58172e05dbb7ca2cf426724e9ee5775c0ef89eaafa9f5ead288112852 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJFMEI0OjMzREFEOTo4RUE3Rjk6QzdGQzIzOjZBNEU3QUFGIiwidmlzaXRvcl9pZCI6IjE4Njg3MDkyMjM5NTQ1NDUzMjciLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | 68917528156bb82400a5f5fdb7b135220cf7dd07b4d4a0a08c19457ea43f1ad1 |
| hovercard-subject-tag | issue:1449913679 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/socketio/socket.io-server-java/8/issue_layout |
| twitter:image | https://opengraph.githubassets.com/ce9bf9ce1f812c9992c1bad7f32b42bfd5dc0c87b342ccd243e88e7fd6d1d5eb/socketio/socket.io-server-java/issues/8 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/ce9bf9ce1f812c9992c1bad7f32b42bfd5dc0c87b342ccd243e88e7fd6d1d5eb/socketio/socket.io-server-java/issues/8 |
| og:image:alt | I have a chat system with the back end built on socket.io-server-java. When a client disconnects, the system broadcasts a message to the room that the client was in. This is working very nicely, th... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | paulthomson78 |
| hostname | github.com |
| expected-hostname | github.com |
| None | 41b6ab3ba6d20a71766ac245b5a4a94c6fc672a9cd4da7d44c1b33ab8bf6a21c |
| turbo-cache-control | no-preview |
| go-import | github.com/socketio/socket.io-server-java git https://github.com/socketio/socket.io-server-java.git |
| octolytics-dimension-user_id | 10566080 |
| octolytics-dimension-user_login | socketio |
| octolytics-dimension-repository_id | 365938076 |
| octolytics-dimension-repository_nwo | socketio/socket.io-server-java |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | true |
| octolytics-dimension-repository_parent_id | 144740389 |
| octolytics-dimension-repository_parent_nwo | trinopoty/socket.io-server-java |
| octolytics-dimension-repository_network_root_id | 144740389 |
| octolytics-dimension-repository_network_root_nwo | trinopoty/socket.io-server-java |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | e6a744804e8e70f97b4d5a18a94dcc63db22f97a |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width