diff --git a/capture/src/capture.cpp b/capture/src/capture.cpp index 41338599..4b81014f 100644 --- a/capture/src/capture.cpp +++ b/capture/src/capture.cpp @@ -147,6 +147,11 @@ int main( int argc, char** argv ) printf( "\nThe client you are trying to connect to uses incompatible protocol version.\nMake sure you are using the same Tracy version on both client and server.\n" ); return 1; } + if( handshake == tracy::HandshakeNotAvailable ) + { + printf( "\nThe client you are trying to connect to is no longer able to sent profiling data,\nbecause another server was already connected to it.\nYou can do the following:\n\n 1. Restart the client application.\n 2. Rebuild the client application with on-demand mode enabled.\n" ); + return 2; + } } while( !worker.HasData() ) std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) ); printf( "\nQueue delay: %s\nTimer resolution: %s\n", TimeToString( worker.GetDelay() ), TimeToString( worker.GetResolution() ) ); diff --git a/client/TracyProfiler.cpp b/client/TracyProfiler.cpp index ecdc49a5..f8f0ce78 100644 --- a/client/TracyProfiler.cpp +++ b/client/TracyProfiler.cpp @@ -1021,6 +1021,64 @@ void Profiler::Worker() m_sock->~Socket(); tracy_free( m_sock ); + + // Client is no longer available here + for(;;) + { + if( ShouldExit() ) + { + m_shutdownFinished.store( true, std::memory_order_relaxed ); + return; + } + + while( s_queue.try_dequeue_bulk( token, m_itemBuf, BulkSize ) > 0 ) {} + bool lockHeld = true; + while( !m_serialLock.try_lock() ) + { + if( m_shutdownManual.load( std::memory_order_relaxed ) ) + { + lockHeld = false; + break; + } + } + m_serialQueue.swap( m_serialDequeue ); + if( lockHeld ) + { + m_serialLock.unlock(); + } + m_serialDequeue.clear(); + + m_sock = listen.Accept(); + if( m_sock ) + { + timeval tv; + tv.tv_sec = 1; + tv.tv_usec = 0; + + char shibboleth[HandshakeShibbolethSize]; + auto res = m_sock->ReadRaw( shibboleth, HandshakeShibbolethSize, &tv ); + if( !res || memcmp( shibboleth, HandshakeShibboleth, HandshakeShibbolethSize ) != 0 ) + { + m_sock->~Socket(); + tracy_free( m_sock ); + continue; + } + + uint32_t protocolVersion; + res = m_sock->ReadRaw( &protocolVersion, sizeof( protocolVersion ), &tv ); + if( !res ) + { + m_sock->~Socket(); + tracy_free( m_sock ); + continue; + } + + HandshakeStatus status = HandshakeNotAvailable; + m_sock->Send( &status, sizeof( status ) ); + m_sock->~Socket(); + tracy_free( m_sock ); + } + } } for(;;) diff --git a/common/TracyProtocol.hpp b/common/TracyProtocol.hpp index eae9fd8f..7012d3d4 100644 --- a/common/TracyProtocol.hpp +++ b/common/TracyProtocol.hpp @@ -37,6 +37,7 @@ enum HandshakeStatus : uint8_t HandshakePending, HandshakeWelcome, HandshakeProtocolMismatch, + HandshakeNotAvailable }; enum { WelcomeMessageProgramNameSize = 64 }; diff --git a/server/TracyView.cpp b/server/TracyView.cpp index c803f912..81c8733b 100644 --- a/server/TracyView.cpp +++ b/server/TracyView.cpp @@ -460,6 +460,10 @@ bool View::Draw() { ImGui::OpenPopup( "Protocol mismatch" ); } + else if( status == HandshakeNotAvailable ) + { + ImGui::OpenPopup( "Client not ready" ); + } if( ImGui::BeginPopupModal( "Protocol mismatch", nullptr, ImGuiWindowFlags_AlwaysAutoResize ) ) { @@ -477,6 +481,22 @@ bool View::Draw() ImGui::EndPopup(); } + if( ImGui::BeginPopupModal( "Client not ready", nullptr, ImGuiWindowFlags_AlwaysAutoResize ) ) + { +#ifdef TRACY_EXTENDED_FONT + TextCentered( ICON_FA_LIGHTBULB ); +#endif + ImGui::Text( "The client you are trying to connect to is no longer able to sent profiling data,\nbecause another server was already connected to it.\nYou can do the following:\n\n 1. Restart the client application.\n 2. Rebuild the client application with on-demand mode enabled." ); + ImGui::Separator(); + if( ImGui::Button( "I understand" ) ) + { + ImGui::CloseCurrentPopup(); + ImGui::EndPopup(); + return false; + } + ImGui::EndPopup(); + } + return s_instance->DrawImpl(); } diff --git a/server/TracyWorker.cpp b/server/TracyWorker.cpp index f6581cec..cb61ed58 100644 --- a/server/TracyWorker.cpp +++ b/server/TracyWorker.cpp @@ -1299,6 +1299,7 @@ void Worker::Exec() case HandshakeWelcome: break; case HandshakeProtocolMismatch: + case HandshakeNotAvailable: default: goto close; }