From b7a069a36d6e61977f32b2a24d84899182e38149 Mon Sep 17 00:00:00 2001 From: liuxinhao Date: Thu, 8 Dec 2022 10:42:44 +0800 Subject: [PATCH 4/6] fix(SIGTERM Processing): Use socket to notify SIGTERM signal, and process SIGTERM signal in the main thread to avoid abnormal exit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 使用socket通知SIGTERM信号,在主线程里处理SIGTERM信号,避免非正常退出,修复之前QLightdm::Greeter释放过早导致AuthLightdm调用接口时崩溃问题 --- lib/auth-proxy/auth-lightdm.cpp | 24 ++++++------- lib/auth-proxy/auth-lightdm.h | 5 +-- lightdm-greeter/src/greeter-login-window.cpp | 24 ++++++------- lightdm-greeter/src/greeter-login-window.h | 3 +- lightdm-greeter/src/main.cpp | 37 ++++++++++++++------ 5 files changed, 56 insertions(+), 37 deletions(-) diff --git a/lib/auth-proxy/auth-lightdm.cpp b/lib/auth-proxy/auth-lightdm.cpp index 59e7849..e9193e9 100644 --- a/lib/auth-proxy/auth-lightdm.cpp +++ b/lib/auth-proxy/auth-lightdm.cpp @@ -16,13 +16,13 @@ #include "auth-lightdm.h" #include -AuthLightdm::AuthLightdm(QLightDM::Greeter* greeterAuth, QObject* parent) +AuthLightdm::AuthLightdm(QSharedPointer greeterAuth, QObject* parent) : AuthBase(parent), - m_greeterAuth(greeterAuth) + m_greeterPtrAuth(greeterAuth) { - connect(m_greeterAuth,&QLightDM::Greeter::showPrompt,this,&AuthLightdm::handleGreeterAuthShowPrompt); - connect(m_greeterAuth,&QLightDM::Greeter::showMessage,this,&AuthLightdm::handleGreeterAuthShowMessage); - connect(m_greeterAuth,&QLightDM::Greeter::authenticationComplete, this,&AuthLightdm::handleGreeterAuthComplete); + connect(m_greeterPtrAuth.data(),&QLightDM::Greeter::showPrompt,this,&AuthLightdm::handleGreeterAuthShowPrompt); + connect(m_greeterPtrAuth.data(),&QLightDM::Greeter::showMessage,this,&AuthLightdm::handleGreeterAuthShowMessage); + connect(m_greeterPtrAuth.data(),&QLightDM::Greeter::authenticationComplete, this,&AuthLightdm::handleGreeterAuthComplete); } AuthLightdm::~AuthLightdm() @@ -31,7 +31,7 @@ AuthLightdm::~AuthLightdm() bool AuthLightdm::init() { - bool bRes = m_greeterAuth->connectSync(); + bool bRes = m_greeterPtrAuth->connectSync(); if( !bRes ) { KLOG_ERROR() << "can't connect greeter auth!"; @@ -41,33 +41,33 @@ bool AuthLightdm::init() bool AuthLightdm::authenticate(const QString &userName) { - m_greeterAuth->authenticate(userName); + m_greeterPtrAuth->authenticate(userName); return true; } void AuthLightdm::cancelAuthentication() { - m_greeterAuth->cancelAuthentication(); + m_greeterPtrAuth->cancelAuthentication(); } bool AuthLightdm::isAuthenticated() const { - return m_greeterAuth->isAuthenticated(); + return m_greeterPtrAuth->isAuthenticated(); } bool AuthLightdm::inAuthentication() const { - return m_greeterAuth->inAuthentication(); + return m_greeterPtrAuth->inAuthentication(); } QString AuthLightdm::authenticationUser() const { - return m_greeterAuth->authenticationUser(); + return m_greeterPtrAuth->authenticationUser(); } void AuthLightdm::respond(const QString &response) { - m_greeterAuth->respond(response); + m_greeterPtrAuth->respond(response); } void AuthLightdm::handleGreeterAuthShowPrompt(QString text, QLightDM::Greeter::PromptType type) diff --git a/lib/auth-proxy/auth-lightdm.h b/lib/auth-proxy/auth-lightdm.h index 9451f3c..810c107 100644 --- a/lib/auth-proxy/auth-lightdm.h +++ b/lib/auth-proxy/auth-lightdm.h @@ -17,6 +17,7 @@ #include "auth-base.h" #include +#include /** * 简单的对QLightDM::Greeter进行了一层包装,只是为了给上层认证代理AuthProxy提供统一的接口 @@ -25,7 +26,7 @@ class AuthLightdm : public AuthBase { Q_OBJECT public: - explicit AuthLightdm(QLightDM::Greeter* greeterAuth, QObject* parent = nullptr); + explicit AuthLightdm(QSharedPointer greeterAuth, QObject* parent = nullptr); ~AuthLightdm() override; bool init() override; @@ -44,7 +45,7 @@ private slots: void handleGreeterAuthComplete(); private: - QLightDM::Greeter* m_greeterAuth; + QSharedPointer m_greeterPtrAuth; }; diff --git a/lightdm-greeter/src/greeter-login-window.cpp b/lightdm-greeter/src/greeter-login-window.cpp index 9d46662..99beb43 100644 --- a/lightdm-greeter/src/greeter-login-window.cpp +++ b/lightdm-greeter/src/greeter-login-window.cpp @@ -86,7 +86,7 @@ bool getIsLoggedIn(const QString &userName) GreeterLoginWindow::GreeterLoginWindow(QWidget *parent) : QWidget(parent), ui(new Ui::GreeterLoginWindow), - m_greeter(this), + m_greeterPtr(new QLightDM::Greeter()), m_powerMenu(nullptr), m_sessionMenu(nullptr), m_noListButotnVisiable(true), @@ -239,12 +239,12 @@ void GreeterLoginWindow::initUI() this, &GreeterLoginWindow::slotUserActivated); ///自动登录按钮点击 connect(ui->btn_autologin, &LoginButton::sigClicked, [this]() { - m_authProxy->authenticate(m_greeter.autologinUserHint()); + m_authProxy->authenticate(m_greeterPtr->autologinUserHint()); }); - connect(&m_greeter, &QLightDM::Greeter::autologinTimerExpired, [this]() { + connect(m_greeterPtr.data(), &QLightDM::Greeter::autologinTimerExpired, [this]() { //NOTE:修复机器配置了autologin-timeout,但未配置autologin-user的情况 - if( !m_greeter.autologinUserHint().isEmpty() ) - m_authProxy->authenticate(m_greeter.autologinUserHint()); + if( !m_greeterPtr->autologinUserHint().isEmpty() ) + m_authProxy->authenticate(m_greeterPtr->autologinUserHint()); }); ///重新认证按钮点击 connect(ui->btn_reAuth, &QPushButton::clicked, [this]() { @@ -348,7 +348,7 @@ void GreeterLoginWindow::initMenu() void GreeterLoginWindow::initLightdmGreeter() { - AuthBase *authInterface = new AuthLightdm(&m_greeter); + AuthBase *authInterface = new AuthLightdm(m_greeterPtr); AuthMsgQueue *msgQueue = new AuthMsgQueue(); m_authProxy = new AuthProxy(authInterface, this); @@ -382,7 +382,7 @@ void GreeterLoginWindow::initLightdmGreeter() ///用户0->1 且 配置允许显示用户链表 且 当前登录模式为输入用户登录 且 手动登录还未输入用户名并点击确定 ///显示返回按钮 qInfo() << "rowInserted:" << m_filterModel.rowCount(QModelIndex()); - if ((m_filterModel.rowCount(QModelIndex()) == 1) && m_showUserList && m_loginMode == LOGIN_MODE_MANUAL && !m_greeter.isAuthenticated()) + if ((m_filterModel.rowCount(QModelIndex()) == 1) && m_showUserList && m_loginMode == LOGIN_MODE_MANUAL && !m_greeterPtr->isAuthenticated()) { qInfo() << "setReturn visible true"; ui->btn_notListAndCancel->setVisible(true); @@ -410,12 +410,12 @@ void GreeterLoginWindow::initLightdmGreeter() ui->userlist->loadUserList(); //NOTE:修复#52982问题,若自动登录用户已存在不自动触发延时自动登录 - if ( !m_greeter.autologinUserHint().isEmpty() ) + if ( !m_greeterPtr->autologinUserHint().isEmpty() ) { - bool isLogged = getIsLoggedIn(m_greeter.autologinUserHint()); + bool isLogged = getIsLoggedIn(m_greeterPtr->autologinUserHint()); if( isLogged ) { - m_greeter.cancelAutologin(); + m_greeterPtr->cancelAutologin(); } #if 0 //WARNING:这种方法不能取得root是否已登录信息 @@ -551,7 +551,7 @@ void GreeterLoginWindow::startAuthUser(const QString &username, QString userIcon ui->label_userName->setText(username); ui->loginAvatar->setImage(userIcon); - if (username == m_greeter.autologinUserHint()) + if (username == m_greeterPtr->autologinUserHint()) { KLOG_DEBUG() << "authproxy user" << username << "is auto login user,switch to auto login"; switchToAutoLogin(); @@ -819,7 +819,7 @@ void GreeterLoginWindow::slotAuthenticationComplete(bool success) } } #endif - if (!m_greeter.startSessionSync(m_session)) + if (!m_greeterPtr->startSessionSync(m_session)) { KLOG_WARNING() << "start session failed,session:" << m_session; } diff --git a/lightdm-greeter/src/greeter-login-window.h b/lightdm-greeter/src/greeter-login-window.h index 689025e..caf5d63 100644 --- a/lightdm-greeter/src/greeter-login-window.h +++ b/lightdm-greeter/src/greeter-login-window.h @@ -23,6 +23,7 @@ #include #include #include +#include #include "auth-define.h" #include "auth-msg-queue.h" @@ -124,7 +125,7 @@ private: FilterUserProxyModel m_filterModel; - QLightDM::Greeter m_greeter; + QSharedPointer m_greeterPtr; QLightDM::UsersModel m_userModel; QLightDM::PowerInterface m_powerIface; diff --git a/lightdm-greeter/src/main.cpp b/lightdm-greeter/src/main.cpp index 0320c51..e145b1f 100644 --- a/lightdm-greeter/src/main.cpp +++ b/lightdm-greeter/src/main.cpp @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include "../../lib/common-widgets/virtual-keyboard.h" #include "cursor-helper.h" @@ -28,23 +30,27 @@ #include "scaling-helper.h" #include "sync-lock-status.h" +static int sigtermFd[2]; + #define DEFAULT_STYLE_FILE ":/themes/lightdm-kiran-greeter-normal.qss" void termSignalHandler(int unused) { -#ifdef VIRTUAL_KEYBOARD - VirtualKeyboard::instance()->keyboardProcessExit(); -#endif - qApp->quit(); + char a = 1; + if(write(sigtermFd[0], &a, sizeof(a)) < 1) + { + qWarning("Failed to handle term signal."); + } } void setup_unix_signal_handlers() { struct sigaction term; term.sa_handler = termSignalHandler; - sigemptyset(&term.sa_mask); term.sa_flags = 0; - term.sa_flags |= SA_RESETHAND; + term.sa_flags = SA_RESTART; + + sigemptyset(&term.sa_mask); int iRet = sigaction(SIGTERM, &term, 0); if (iRet != 0) { @@ -61,9 +67,6 @@ int main(int argc, char *argv[]) qWarning() << "klog_qt5_init error:" << iRet; } - ///安装信号处理 - setup_unix_signal_handlers(); - ///设置缩放比 double scaled_factor = 0.0; switch (KiranGreeterPrefs::instance()->scale_mode()) @@ -93,6 +96,15 @@ int main(int argc, char *argv[]) QApplication a(argc, argv); QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); + // 处理SIGTERM信号 + if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sigtermFd)) + { + KLOG_WARNING() << "Couldn't create TERM socketpair"; + } + QSocketNotifier *snTerm = new QSocketNotifier(sigtermFd[1], QSocketNotifier::Read, &a); + QObject::connect(snTerm, SIGNAL(activated(int)), &a, SLOT(quit())); + setup_unix_signal_handlers(); + ///依据登陆器整体缩放比例,设置默认光标大小 if (!CursorHelper::setDefaultCursorSize(scaled_factor)) { @@ -135,5 +147,10 @@ int main(int argc, char *argv[]) GreeterScreenManager screenManager; screenManager.init(); - return a.exec(); + int res = a.exec(); + + close(sigtermFd[0]); + close(sigtermFd[1]); + + return res; } -- 2.33.0