diff --git a/src/py_dvt_ate/app/dashboard/app.py b/src/py_dvt_ate/app/dashboard/app.py index 7bfd933..02090f6 100644 --- a/src/py_dvt_ate/app/dashboard/app.py +++ b/src/py_dvt_ate/app/dashboard/app.py @@ -128,12 +128,31 @@ def get_or_create_server() -> SimulationServer: """ global _simulation_server, _server_thread - # Return existing server if it's running AND responsive - if _simulation_server is not None and _simulation_server.is_running: - # Verify the server is actually responding (not a stale flag) - if _is_server_responsive(): + # FIRST: Check if ports are already in use (regardless of singleton state) + # This catches orphan servers from previous processes (e.g., Docker restarts) + ports_in_use = _is_server_responsive() + + if ports_in_use: + # Ports are in use - either our singleton or an orphan process + if _simulation_server is not None and _simulation_server.is_running: + # We have a reference - reuse it return _simulation_server - # Server flag says running but it's not responsive - clean up + else: + # Orphan server from previous process - wait for it to die + st.warning("Waiting for previous server to shut down...") + for _ in range(10): # Wait up to 5 seconds + time.sleep(0.5) + if not _is_server_responsive(): + break + else: + st.error( + "Port still in use. Please wait a moment and refresh, " + "or restart the container." + ) + st.stop() + + # Clean up stale singleton reference if ports are free but singleton exists + if _simulation_server is not None and not ports_in_use: _simulation_server = None _server_thread = None