fix crash on close
This commit is contained in:
		@@ -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>;
 | 
				
			||||||
        millis duration;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Try to connect only once when we don't have automaticReconnection setup
 | 
					        uint32_t retries = 0;
 | 
				
			||||||
        if (!isConnectedOrClosing() && !_stop && !_automaticReconnection)
 | 
					        millis duration;
 | 
				
			||||||
 | 
					        ix::WebSocketInitResult status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // we will try to connect perpertually
 | 
				
			||||||
 | 
					        while (true)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            if (isConnected() || isClosing() || _stop)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                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)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                duration = millis(calculateRetryWaitMilliseconds(retries++));
 | 
					                WebSocketErrorInfo connectErr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                connectErr.retries = retries;
 | 
					                if (_automaticReconnection)
 | 
				
			||||||
                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)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                if (isConnectedOrClosing() || _stop || !_automaticReconnection)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    break;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                status = connect(_handshakeTimeoutSecs);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if (!status.success)
 | 
					 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    duration = millis(calculateRetryWaitMilliseconds(retries++));
 | 
					                    duration = millis(calculateRetryWaitMilliseconds(retries++));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    connectErr.retries = retries;
 | 
					 | 
				
			||||||
                    connectErr.wait_time = duration.count();
 | 
					                    connectErr.wait_time = duration.count();
 | 
				
			||||||
                    connectErr.reason = status.errorStr;
 | 
					                    connectErr.retries = retries;
 | 
				
			||||||
                    connectErr.http_status = status.http_status;
 | 
					 | 
				
			||||||
                    _onMessageCallback(WebSocket_MessageType_Error, "", 0,
 | 
					 | 
				
			||||||
                                       connectErr, WebSocketOpenInfo(),
 | 
					 | 
				
			||||||
                                       WebSocketCloseInfo());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    // Only sleep if we aren't in the middle of stopping
 | 
					 | 
				
			||||||
                    if (!_stop)
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        std::this_thread::sleep_for(duration);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                connectErr.reason      = status.errorStr;
 | 
				
			||||||
 | 
					                connectErr.http_status = status.http_status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                _onMessageCallback(WebSocket_MessageType_Error, "", 0,
 | 
				
			||||||
 | 
					                                    connectErr, WebSocketOpenInfo(),
 | 
				
			||||||
 | 
					                                    WebSocketCloseInfo());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -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;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user