diff --git a/src/common/iflytek_ai_assistant.cpp b/src/common/iflytek_ai_assistant.cpp index c9f37ca7..a302a6d0 100644 --- a/src/common/iflytek_ai_assistant.cpp +++ b/src/common/iflytek_ai_assistant.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -391,15 +392,28 @@ QString IflytekAiAssistant::errorString(CallStatus ret) const } } +bool IflytekAiAssistant::appShuttingDown() +{ + // 主线程进入 ~QCoreApplication(closingDown)或应用已析构后,dtk6log/事件派发 + // 处于 teardown 状态,后台线程再走日志或排队回调会崩溃(BUG-378881/378901) + QCoreApplication *app = QCoreApplication::instance(); + return app == nullptr || app->closingDown(); +} + IflytekAiAssistant::CallStatus IflytekAiAssistant::copilotInstalled(const QSharedPointer &copilot) { QDBusReply version = copilot->call("version"); if (version.isValid()) { - qInfo() << "current uos-ai version:" << version.value(); + // 阻塞调用可能跨越整个应用退出过程(默认超时 25s),返回后须复查 + if (!appShuttingDown()) { + qInfo() << "current uos-ai version:" << version.value(); + } return Enable; } - qWarning() << "Query uos-ai installed faild! Maybe need install"; + if (!appShuttingDown()) { + qWarning() << "Query uos-ai installed faild! Maybe need install"; + } return NotInstalled; } @@ -411,12 +425,16 @@ IflytekAiAssistant::CallStatus IflytekAiAssistant::isCopilotEnabled(const QShare { QDBusReply state = copilot->call("isCopilotEnabled"); if (state.isValid()) { - qDebug() << "current uos-ai user exp state:" << state.value(); + if (!appShuttingDown()) { + qDebug() << "current uos-ai user exp state:" << state.value(); + } return state.value() ? Enable : NoUserAgreement; } // NOTE: Adapt old version, if dbus interface not valid, assume the user agreement agreed. - qWarning() << "Query uos-ai user exp state failed!" << state.error().message(); + if (!appShuttingDown()) { + qWarning() << "Query uos-ai user exp state failed!" << state.error().message(); + } return Enable; } @@ -440,6 +458,10 @@ void IflytekAiAssistant::checkAiExists() static std::once_flag kAiFlag; std::call_once(kAiFlag, [this]() { QtConcurrent::run([this]() { + // 任务可能排队到应用退出期才被线程池执行 + if (appShuttingDown()) { + return; + } // If call dbus interface success, the uos-ai backend process started. auto copilot = QSharedPointer::create(kCopilotService, kCopilotPath, kCopilotInterface); CallStatus status = IflytekAiAssistant::copilotInstalled(copilot); @@ -447,6 +469,12 @@ void IflytekAiAssistant::checkAiExists() status = IflytekAiAssistant::isCopilotEnabled(copilot); } + // 阻塞 D-Bus 期间应用可能已进入析构(主线程卡在 ~QCoreApplication + // 的 QThreadPool::waitForDone 等本任务收尾),此时打日志/排队回调即崩溃 + if (appShuttingDown()) { + return; + } + qInfo() << QString("backend uos-ai status: %1(%2)").arg(Enable == status).arg(status); // call on non-gui thread, so queued connection. diff --git a/src/common/iflytek_ai_assistant.h b/src/common/iflytek_ai_assistant.h index c5355b0e..7519ede2 100644 --- a/src/common/iflytek_ai_assistant.h +++ b/src/common/iflytek_ai_assistant.h @@ -67,6 +67,9 @@ class IflytekAiAssistant : public QObject static CallStatus isCopilotEnabled(const QSharedPointer &copilot); static CallStatus launchCopilotChat(const QSharedPointer &copilot); + /// BUG-378881/378901: 应用 teardown 期间为 true,后台探测线程此时不得打日志/排队回调 + static bool appShuttingDown(); + static QString copilotService(); bool m_inited{false}; diff --git a/src/editor/editwrapper.cpp b/src/editor/editwrapper.cpp index f406deb9..e511ab1e 100644 --- a/src/editor/editwrapper.cpp +++ b/src/editor/editwrapper.cpp @@ -195,6 +195,16 @@ EditWrapper::EditWrapper(Window *window, QWidget *parent) EditWrapper::~EditWrapper() { qDebug() << "EditWrapper destructor"; + // 必须在 delete m_pTextEdit 之前清理 m_pWaringNotices,避免 DMessageManager + // 持有 m_pTextEdit 悬空指针导致 use-after-free(bug 378881)。 + // 此前 bug 78042 的崩溃根因是 delete m_pWaringNotices 位于 m_pTextEdit 之后, + // DMessageManager 在处理消息移除时访问已释放的 m_pTextEdit;将删除顺序 + // 调整为先 m_pWaringNotices 后 m_pTextEdit 即可同时避免两个问题。 + if (m_pWaringNotices != nullptr) { + disconnect(m_pWaringNotices); + delete m_pWaringNotices; + m_pWaringNotices = nullptr; + } if (m_pTextEdit != nullptr) { qDebug() << "EditWrapper destructor, m_pTextEdit not nullptr"; disconnect(m_pTextEdit); @@ -207,12 +217,6 @@ EditWrapper::~EditWrapper() delete m_pBottomBar; m_pBottomBar = nullptr; } - //delete 之后,如果出现文件被修改,需要重新加载弹框,之后,点击标签关闭,闪退问题 78042 ut002764 -// if (m_pWaringNotices != nullptr) { -// disconnect(m_pWaringNotices); -// delete m_pWaringNotices; -// m_pWaringNotices = nullptr; -// } qDebug() << "EditWrapper destructor exit"; }