diff --git a/pglablib/ASyncDBConnection.cpp b/pglablib/ASyncDBConnection.cpp index dfe05c9..c85fcc6 100644 --- a/pglablib/ASyncDBConnection.cpp +++ b/pglablib/ASyncDBConnection.cpp @@ -81,7 +81,7 @@ private: void doStateCallback(ASyncDBConnection::StateData state); /// Wait's for a command to come in and send's it to the server - void waitForAndSendCommand(); + bool waitForAndSendCommand(); void doNewCommand(); void waitForResult(); @@ -236,7 +236,9 @@ void ASyncDBConnectionThread::communicate() if (m_state == ASyncDBConnection::State::Connected) { - waitForAndSendCommand(); + if (!waitForAndSendCommand()) { + return; + } } else if (m_state == ASyncDBConnection::State::QuerySend || m_state == ASyncDBConnection::State::CancelSend) { // Wait for result, even after a cancel we should wait, for all results @@ -255,14 +257,21 @@ void ASyncDBConnectionThread::stop() void ASyncDBConnectionThread::doStateCallback(ASyncDBConnection::StateData state) { + qDebug() << "State change " + state.Message; m_state = state.State; Q_EMIT asyncConnObject->onStateChanged(state); } -void ASyncDBConnectionThread::waitForAndSendCommand() +bool ASyncDBConnectionThread::waitForAndSendCommand() { + SOCKET sock = static_cast(m_connection.socket()); + Win32Event socket_event(Win32Event::Reset::Manual, Win32Event::Initial::Clear); + long fd = FD_READ | FD_CLOSE; + WSAEventSelect(sock, socket_event.handle(), fd); + WaitHandleList whl; auto wait_result_new_command = whl.add(m_commandQueue.m_newEvent); + auto wait_result_socket = whl.add(socket_event); whl.add(m_stopEvent); DWORD res = MsgWaitForMultipleObjectsEx( @@ -275,8 +284,17 @@ void ASyncDBConnectionThread::waitForAndSendCommand() if (res == wait_result_new_command) { doNewCommand(); } + else if (res == wait_result_socket) { + WSANETWORKEVENTS net_events; + WSAEnumNetworkEvents(sock, socket_event.handle(), &net_events); + if (net_events.lNetworkEvents & FD_CLOSE) { + doStateCallback({ ASyncDBConnection::State::NotConnected, "Connection lost" }); + return false; + } + } // Note if it was stop we can just return and function // above will stop looping because terminateRequested has been set too by stop + return true; } void ASyncDBConnectionThread::doNewCommand() @@ -358,6 +376,11 @@ void ASyncDBConnectionThread::waitForResult() finished = true; } } + else if (net_events.lNetworkEvents & FD_CLOSE) { + doStateCallback({ ASyncDBConnection::State::NotConnected, "Close while waiting for result" }); + finished = true; + stop(); + } } if (res == wait_result_stop) { // Send cancel, close connection and terminate thread