Comments (4)
Thanks for the good words.
Did you check if you can use server.setOnClientMessageCallback ?
iirc I had created that to avoid a memory leak.
from ixwebsocket.
ps: I think I had tried to use setOnClientMessageCallback in that proxy code, but it was not working ...
from ixwebsocket.
I chose the old API is for the following reason: I required a weak_ptr to the WebSocket instead of a reference so that I could asynchronously send periodic messages to the client outside the callback, in another thread. Previously, when storing a copy of the reference, the WebSocket would (of course) suddenly disappear due to a Close event and there was no good way to mutex lock this between the threads*. The weak_ptr to the WebSocket solved my problem, as this is checkable.
Next is the problem of capturing the connection state generated by the factory by the 'upstream' and 'downstream' WebSockets. I have double-checked and capturing the state, where the state contains a WebSocket for the upstream, generates a memory leak - the state is never destructed. Again I solved this by first making a weak_ptr to the connection state and capturing this in both callback lambda functions. The state is now destructable as there are no longer any cycles.
Unfortunately I was now presented with frequent crashes due to the std::system_error 'Resource deadlock avoided'. Digging into this further, I traced the problem. As the connection state was now nicely destructed (contrary to your proxy server) the WebSocket member contained in the state was now also destructed and ~WebSocket() joins its worker thread with the caller, through stop(). In the stop() code I found this pattern:
if (_thread.joinable()) _thread.join();
It took me at least ten times reading the std::thread docs on joinable() to realise that this pattern does not prevent you from joining yourself. joinable() is true if the thread has run and nothing more. It does not check if you are calling from the same thread that you are joining. You might have misread the docs just like I did. The check performed by the function is:
get_id() != std::thread::id()
This reads as if thread IDs are being compared, but the current ID (self) is being compared to the default-constructed id of a non-running thread. In other words, the check is really whether the thread is running, or has run.
The problem is having a shared_ptr to the connection state, the final thread decrementing the usage count to zero is the one calling the destructor. I found out that sometimes it was the upstream websocket that was the last one to do so, which triggered the Resource deadlock avoided, because it would join itself.
My current work-around is to introduce a new garbage collector thread that also has a reference to the connection state in a std::list. It is this thread that periodically checks whether there is only one reference left to the state, in which case it chooses to destruct the connection by erasing it from the list. This always works because it is a different thread.
I would like to hear from you to learn if there is a more elegant solution.
*) My attempt to have the Close event wait for a sendBinary() in progress in another thread was complicated when I found out that a failing sendBinary() can also call Close directly from the same callstack/thread, which makes the locking very ugly, to avoid yet more deadlocks.
from ixwebsocket.
Here's one more complex example I had in this repo at some point ; https://github.com/machinezone/IXWebSocket/tree/v11.0.0/ixsnake/ixsnake
It was possibly suffering from the same problem you had, but I had it working with thread sanitizer, but it was still possibly leaking.
I know it took me a while to get something relatively stable, with this garbage collection thread, so I believe that you extra garbage collecting thread is a good idea. If you'd like to make a PR to add it to this repo I would consider it.
The caveat is that managing an std::list isn't ideal for some operations, but this server has already constraints so I think it's acceptable.
The code that makes things more complicated is the automatic reconnection thing, but it's a very useful feature.
from ixwebsocket.
Related Issues (20)
- the client did not receive the close event HOT 3
- Cannot link against IXWebsocket HOT 1
- HTTPServer questions? HOT 2
- Question about weak_ptr in API HOT 1
- Source code release v11.4.4 contains an error in IXSocketMbedTLS.cpp line 52 HOT 3
- Can I use IXHttpClient to upload files to server? HOT 1
- each http request cause socket reconnection HOT 1
- [BUG] Does not receive a close or error message. and the mapping configured in the host file does not take effect
- Universal Windows application TLS certificate issue HOT 2
- UWP App undefined method PathMatchSpecA HOT 2
- Client connection closed immediately on re-connection after ping timeout HOT 1
- Disable ZLIB when install as vcpkg package? HOT 1
- Build error. (mbedtls) HOT 2
- [Feature Request] Add support for OpenSSL SSLKEYLOGFILE HOT 9
- Unable to connect to ws endpoint behind standard AWS load balancer (ALB) HOT 8
- CMake packaging doesn't support example usage HOT 2
- Possible unintentional copying inside Websocket#connect function
- Possible unintentional copying inside Websocket#connect function HOT 1
- [enhancement] add ability to remove default headers HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ixwebsocket.