diff --git a/src/cbang/ws/Websocket.cpp b/src/cbang/ws/Websocket.cpp index a6d21f3d3..ac24be855 100644 --- a/src/cbang/ws/Websocket.cpp +++ b/src/cbang/ws/Websocket.cpp @@ -71,9 +71,11 @@ void Websocket::connect(HTTP::Client &client, const URI &uri) { start(); } else { + // Release refs first so a reconnect from onClose() is not clobbered + outConn.release(); + connection.release(); onClose(WS_STATUS_NONE, SSTR("Connection failed: error=" << error << " code=" << code)); - connection.release(); } }; @@ -88,7 +90,11 @@ void Websocket::connect(HTTP::Client &client, const URI &uri) { req->outSet("Upgrade", "websocket"); req->outSet("Connection", "upgrade"); - connection = client.send(req); + // Hold a strong reference to the outgoing connection; other refs are weak + outConn = client.send(req); + connection = outConn; + // Cache ID like upgrade() does, since the weak ref may not outlive us + id = outConn->getID(); } @@ -439,10 +445,10 @@ void Websocket::shutdown() { SmartPointer self = this; SmartPointer conn = connection; - if (conn.isSet()) { - connection.release(); - conn->close(); - } + // Clear members first; conn->close() callbacks may re-enter this class + outConn.release(); + connection.release(); + if (conn.isSet()) conn->close(); if (active) { active = false; diff --git a/src/cbang/ws/Websocket.h b/src/cbang/ws/Websocket.h index 8288034ac..c0d951dcb 100644 --- a/src/cbang/ws/Websocket.h +++ b/src/cbang/ws/Websocket.h @@ -50,6 +50,7 @@ namespace cb { namespace WS { class Websocket : virtual public RefCounted, public Enum { SmartPointer::Weak connection; + SmartPointer outConn; uint64_t id = ~0; bool active = false;