| 1530 | } |
| 1531 | |
| 1532 | void AutomationServer::stop() |
| 1533 | { |
| 1534 | if (!m_server) |
| 1535 | return; |
| 1536 | |
| 1537 | // Safety: never leave the radio keyed when the bridge shuts down. |
| 1538 | if (m_txAllowed) |
| 1539 | forceUnkey("automation bridge stopping"); |
| 1540 | |
| 1541 | // Restore the user's real station name so live MultiFlex peers stop seeing |
| 1542 | // the agent name immediately (don't wait for the disconnect to drop it). |
| 1543 | restoreStation(); |
| 1544 | if (m_txWatchdog) { |
| 1545 | m_txWatchdog->stop(); |
| 1546 | m_txWatchdog->deleteLater(); |
| 1547 | m_txWatchdog = nullptr; |
| 1548 | } |
| 1549 | // Detach the log tap before teardown so no logging thread can touch us. |
| 1550 | if (m_logTapId >= 0) { |
| 1551 | LogManager::instance().removeTap(m_logTapId); |
| 1552 | m_logTapId = -1; |
| 1553 | } |
| 1554 | if (m_logDrain) { |
| 1555 | m_logDrain->stop(); |
| 1556 | m_logDrain->deleteLater(); |
| 1557 | m_logDrain = nullptr; |
| 1558 | } |
| 1559 | m_logSubscribers.clear(); |
| 1560 | for (const std::shared_ptr<ConnectWait>& wait : m_connectWaits) { |
| 1561 | if (!wait) { |
| 1562 | continue; |
| 1563 | } |
| 1564 | if (wait->timer) { |
| 1565 | wait->timer->stop(); |
| 1566 | wait->timer->deleteLater(); |
| 1567 | wait->timer = nullptr; |
| 1568 | } |
| 1569 | QObject::disconnect(wait->connection); |
| 1570 | wait->complete = true; |
| 1571 | } |
| 1572 | m_connectWaits.clear(); |
| 1573 | |
| 1574 | for (auto it = m_buffers.constBegin(); it != m_buffers.constEnd(); ++it) |
| 1575 | it.key()->deleteLater(); |
| 1576 | m_buffers.clear(); |
| 1577 | |
| 1578 | m_server->close(); |
| 1579 | m_server->deleteLater(); |
| 1580 | m_server = nullptr; |
| 1581 | |
| 1582 | // Our own per-pid entry is always ours to remove. |
| 1583 | if (!m_discoveryEntry.isEmpty()) { |
| 1584 | QFile::remove(m_discoveryEntry); |
| 1585 | m_discoveryEntry.clear(); |
| 1586 | } |
| 1587 | // The legacy shared pointer: remove it only if it still points at US, so an |
| 1588 | // exiting sibling can't blind a still-running instance that owns it now. |
| 1589 | if (!m_discoveryFile.isEmpty()) { |
no test coverage detected