fix crash on close
This commit is contained in:
parent
6cd970d0d9
commit
ef2e5c7ddb
@ -149,7 +149,6 @@ namespace ix
|
|||||||
// This value needs to be forced when shutting down, it is restored later
|
// This value needs to be forced when shutting down, it is restored later
|
||||||
_automaticReconnection = false;
|
_automaticReconnection = false;
|
||||||
|
|
||||||
// sync close
|
|
||||||
close();
|
close();
|
||||||
|
|
||||||
if (_thread.joinable())
|
if (_thread.joinable())
|
||||||
@ -218,72 +217,63 @@ namespace ix
|
|||||||
return getReadyState() == WebSocket_ReadyState_Closing;
|
return getReadyState() == WebSocket_ReadyState_Closing;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebSocket::isConnectedOrClosing() const
|
|
||||||
{
|
|
||||||
return isConnected() || isClosing();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WebSocket::close()
|
void WebSocket::close()
|
||||||
{
|
{
|
||||||
_ws.close();
|
_ws.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSocket::reconnectPerpetuallyIfDisconnected()
|
void WebSocket::checkConnection(bool initial)
|
||||||
{
|
{
|
||||||
uint32_t retries = 0;
|
|
||||||
WebSocketErrorInfo connectErr;
|
|
||||||
ix::WebSocketInitResult status;
|
|
||||||
using millis = std::chrono::duration<double, std::milli>;
|
using millis = std::chrono::duration<double, std::milli>;
|
||||||
|
|
||||||
|
uint32_t retries = 0;
|
||||||
millis duration;
|
millis duration;
|
||||||
|
ix::WebSocketInitResult status;
|
||||||
|
|
||||||
// Try to connect only once when we don't have automaticReconnection setup
|
// we will try to connect perpertually
|
||||||
if (!isConnectedOrClosing() && !_stop && !_automaticReconnection)
|
|
||||||
{
|
|
||||||
status = connect(_handshakeTimeoutSecs);
|
|
||||||
|
|
||||||
if (!status.success)
|
|
||||||
{
|
|
||||||
duration = millis(calculateRetryWaitMilliseconds(retries++));
|
|
||||||
|
|
||||||
connectErr.retries = retries;
|
|
||||||
connectErr.wait_time = duration.count();
|
|
||||||
connectErr.reason = status.errorStr;
|
|
||||||
connectErr.http_status = status.http_status;
|
|
||||||
_onMessageCallback(WebSocket_MessageType_Error, "", 0,
|
|
||||||
connectErr, WebSocketOpenInfo(),
|
|
||||||
WebSocketCloseInfo());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Otherwise try to reconnect perpertually
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (isConnectedOrClosing() || _stop || !_automaticReconnection)
|
if (isConnected() || isClosing() || _stop)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!initial && !_automaticReconnection)
|
||||||
|
{
|
||||||
|
// don't attempt to reconnect
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
initial = false;
|
||||||
|
|
||||||
|
// Only sleep if we are retrying
|
||||||
|
if (duration.count() > 0)
|
||||||
|
{
|
||||||
|
// to do: make conditional sleeping
|
||||||
|
std::this_thread::sleep_for(duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to connect (sync connect)
|
||||||
status = connect(_handshakeTimeoutSecs);
|
status = connect(_handshakeTimeoutSecs);
|
||||||
|
|
||||||
if (!status.success)
|
if (!status.success)
|
||||||
|
{
|
||||||
|
WebSocketErrorInfo connectErr;
|
||||||
|
|
||||||
|
if (_automaticReconnection)
|
||||||
{
|
{
|
||||||
duration = millis(calculateRetryWaitMilliseconds(retries++));
|
duration = millis(calculateRetryWaitMilliseconds(retries++));
|
||||||
|
|
||||||
connectErr.retries = retries;
|
|
||||||
connectErr.wait_time = duration.count();
|
connectErr.wait_time = duration.count();
|
||||||
|
connectErr.retries = retries;
|
||||||
|
}
|
||||||
|
|
||||||
connectErr.reason = status.errorStr;
|
connectErr.reason = status.errorStr;
|
||||||
connectErr.http_status = status.http_status;
|
connectErr.http_status = status.http_status;
|
||||||
|
|
||||||
_onMessageCallback(WebSocket_MessageType_Error, "", 0,
|
_onMessageCallback(WebSocket_MessageType_Error, "", 0,
|
||||||
connectErr, WebSocketOpenInfo(),
|
connectErr, WebSocketOpenInfo(),
|
||||||
WebSocketCloseInfo());
|
WebSocketCloseInfo());
|
||||||
|
|
||||||
// Only sleep if we aren't in the middle of stopping
|
|
||||||
if (!_stop)
|
|
||||||
{
|
|
||||||
std::this_thread::sleep_for(duration);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -292,10 +282,20 @@ namespace ix
|
|||||||
{
|
{
|
||||||
setThreadName(getUrl());
|
setThreadName(getUrl());
|
||||||
|
|
||||||
while (getReadyState() != WebSocket_ReadyState_Closed)
|
bool initial = true;
|
||||||
|
|
||||||
|
while (true)
|
||||||
{
|
{
|
||||||
// 1. Make sure we are always connected
|
// 1. Make sure we are always connected
|
||||||
reconnectPerpetuallyIfDisconnected();
|
checkConnection(initial);
|
||||||
|
|
||||||
|
initial = false;
|
||||||
|
|
||||||
|
// if here we are closed then checkConnection was not able to connect
|
||||||
|
if (getReadyState() == WebSocket_ReadyState_Closed)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// 2. Poll to see if there's any new data available
|
// 2. Poll to see if there's any new data available
|
||||||
WebSocketTransport::PollPostTreatment pollPostTreatment = _ws.poll();
|
WebSocketTransport::PollPostTreatment pollPostTreatment = _ws.poll();
|
||||||
@ -311,6 +311,7 @@ namespace ix
|
|||||||
WebSocketMessageType webSocketMessageType;
|
WebSocketMessageType webSocketMessageType;
|
||||||
switch (messageKind)
|
switch (messageKind)
|
||||||
{
|
{
|
||||||
|
default:
|
||||||
case WebSocketTransport::MSG:
|
case WebSocketTransport::MSG:
|
||||||
{
|
{
|
||||||
webSocketMessageType = WebSocket_MessageType_Message;
|
webSocketMessageType = WebSocket_MessageType_Message;
|
||||||
@ -341,9 +342,6 @@ namespace ix
|
|||||||
|
|
||||||
WebSocket::invokeTrafficTrackerCallback(msg.size(), true);
|
WebSocket::invokeTrafficTrackerCallback(msg.size(), true);
|
||||||
});
|
});
|
||||||
|
|
||||||
// If we aren't trying to reconnect automatically, exit if we aren't connected
|
|
||||||
if (!isConnectedOrClosing() && !_automaticReconnection) return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,6 +99,7 @@ namespace ix
|
|||||||
|
|
||||||
// Run asynchronously, by calling start and stop.
|
// Run asynchronously, by calling start and stop.
|
||||||
void start();
|
void start();
|
||||||
|
// stop is synchronous
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
// Run in blocking mode, by connecting first manually, and then calling run.
|
// Run in blocking mode, by connecting first manually, and then calling run.
|
||||||
@ -135,8 +136,7 @@ namespace ix
|
|||||||
|
|
||||||
bool isConnected() const;
|
bool isConnected() const;
|
||||||
bool isClosing() const;
|
bool isClosing() const;
|
||||||
bool isConnectedOrClosing() const;
|
void checkConnection(bool initial);
|
||||||
void reconnectPerpetuallyIfDisconnected();
|
|
||||||
std::string readyStateToString(ReadyState readyState);
|
std::string readyStateToString(ReadyState readyState);
|
||||||
static void invokeTrafficTrackerCallback(size_t size, bool incoming);
|
static void invokeTrafficTrackerCallback(size_t size, bool incoming);
|
||||||
|
|
||||||
|
@ -12,10 +12,10 @@ namespace ix
|
|||||||
{
|
{
|
||||||
struct WebSocketErrorInfo
|
struct WebSocketErrorInfo
|
||||||
{
|
{
|
||||||
uint32_t retries;
|
uint32_t retries = 0;
|
||||||
double wait_time;
|
double wait_time = 0;
|
||||||
int http_status;
|
int http_status = 0;
|
||||||
std::string reason;
|
std::string reason;
|
||||||
bool decompressionError;
|
bool decompressionError = false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user