77Q_LOGGING_CATEGORY (fcitx5Helper, " fcitx5.helper" )
88
99#include < QCoreApplication>
10+ #include < QDir>
11+ #include < QLockFile>
12+ #include < QScopedPointer>
13+ #include < unistd.h>
1014
1115#include < signal.h>
1216
17+ static QScopedPointer<QLockFile> g_lockFile;
18+
19+ // Extract from DGuiApplicationHelper::setSingleInstance (UserScope only)
20+ static bool setSingleInstance () {
21+ QString socket_key = " _fcitx5_single_instance_" ;
22+ socket_key += QString (" %1_" ).arg (getuid ());
23+ socket_key += QString (" fcitx5-helper" );
24+
25+ QString lockfile = socket_key;
26+ if (!lockfile.startsWith (QLatin1Char (' /' ))) {
27+ lockfile = QDir::cleanPath (QDir::tempPath ());
28+ lockfile += QLatin1Char (' /' ) + socket_key;
29+ qCDebug (fcitx5Helper) << " lockfile:" << lockfile;
30+ }
31+ lockfile += QStringLiteral (" .lock" );
32+
33+ qint64 pid = -1 ;
34+ QString hostname, appname;
35+ if (!g_lockFile.isNull () && g_lockFile->isLocked () && g_lockFile->getLockInfo (&pid, &hostname, &appname) && pid == getpid ()) {
36+ qCWarning (fcitx5Helper) << " call setSingleInstance again within the same process" ;
37+ g_lockFile->unlock ();
38+ g_lockFile.reset ();
39+ qCDebug (fcitx5Helper) << " unlock lock file" ;
40+ }
41+
42+ // Create new lock file
43+ g_lockFile.reset (new QLockFile (lockfile));
44+
45+ // Try to lock
46+ if (!g_lockFile->tryLock ()) {
47+ qCInfo (fcitx5Helper) << " fcitx5-helper instance already exists for current user, exiting" ;
48+ return false ;
49+ }
50+
51+ qCDebug (fcitx5Helper) << " Created lock file:" << lockfile;
52+ return true ;
53+ }
54+
1355static void signal_callback_handler (int signum, siginfo_t *siginfo, void *context) {
1456 Q_UNUSED (context)
1557 qCDebug (fcitx5Helper) << " Received signal:" << signum << " from pid:" << (long )siginfo->si_pid ;
1658 if (signum == SIGTERM && (long )siginfo->si_pid == 1 ) {
1759 qCInfo (fcitx5Helper) << " Terminating fcitx5 processes due to SIGTERM from init" ;
60+ // Clean up lock file
61+ if (!g_lockFile.isNull () && g_lockFile->isLocked ()) {
62+ qCInfo (fcitx5Helper) << " unlock lock file" ;
63+ g_lockFile->unlock ();
64+ }
1865 QString output, error;
1966 ProcessMonitor::exeCommand (" pidof fcitx5 | xargs kill -9" , QStringList (), output, error);
2067 qCDebug (fcitx5Helper) << " Command output:" << output << " Error:" << error;
@@ -23,7 +70,7 @@ static void signal_callback_handler(int signum, siginfo_t *siginfo, void *contex
2370}
2471
2572static void setupSignalHandler () {
26- // 进城被init杀死 ,视为关机
73+ // 进程被init杀死 ,视为关机
2774 struct sigaction act;
2875 memset (&act, 0 , sizeof (act));
2976 act.sa_sigaction = &signal_callback_handler;
@@ -34,11 +81,24 @@ static void setupSignalHandler() {
3481int main (int argc, char *argv[])
3582{
3683 qCInfo (fcitx5Helper) << " Starting fcitx5 helper process" ;
84+ // Check single instance for current user
85+ if (!setSingleInstance ()) {
86+ qCInfo (fcitx5Helper) << " fcitx5-helper already running" ;
87+ return 0 ;
88+ }
3789 QCoreApplication app (argc, argv);
3890
91+ // Register cleanup function to unlock on exit
92+ QObject::connect (&app, &QCoreApplication::aboutToQuit, []() {
93+ if (!g_lockFile.isNull () && g_lockFile->isLocked ()) {
94+ qCInfo (fcitx5Helper) << " unlock lock file" ;
95+ g_lockFile->unlock ();
96+ }
97+ });
98+
3999 qCDebug (fcitx5Helper) << " Setting up signal handlers" ;
40100 setupSignalHandler ();
41-
101+
42102 qCDebug (fcitx5Helper) << " Initializing process monitor" ;
43103 ProcessMonitor monitor;
44104 monitor.startMonitoring ();
0 commit comments