Skip to content

Commit b117282

Browse files
Verify primary PID is still alive before assuming it is running (#217)
When a primary instance is force-killed (SIGKILL), the shared memory block persists on Unix systems with `primary=true` and the stale PID. Currently this causes all subsequent launches to detect a non-existent primary and immediately exit as secondary instances. This PR adds an `isProcessRunning()` check after the shared memory checksum verification. If the recorded `primaryPid` no longer corresponds to a running process: - **Unix**: uses `kill(pid, 0)` + `errno != ESRCH` - **Windows**: uses `OpenProcess()` + `GetExitCodeProcess()` The new instance then takes over as primary instead of exiting. Tested on macOS (force-kill scenario) and confirmed the stale PID warning is now followed by successful takeover. Co-authored-by: Itay Grudev <itay+git2020@grudev.com>
1 parent d08e923 commit b117282

1 file changed

Lines changed: 34 additions & 0 deletions

File tree

singleapplication.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,36 @@
2626
#include <QtCore/QByteArray>
2727
#include <QtCore/QSharedMemory>
2828

29+
#ifdef Q_OS_UNIX
30+
#include <signal.h>
31+
#include <errno.h>
32+
#endif
33+
#ifdef Q_OS_WIN
34+
#include <windows.h>
35+
#endif
36+
2937
#include "singleapplication.h"
3038
#include "singleapplication_p.h"
3139

40+
static bool isProcessRunning( qint64 pid )
41+
{
42+
if ( pid <= 0 )
43+
return false;
44+
45+
#ifdef Q_OS_UNIX
46+
return kill( static_cast<pid_t>( pid ), 0 ) == 0 || errno != ESRCH;
47+
#endif
48+
#ifdef Q_OS_WIN
49+
HANDLE hProcess = OpenProcess( PROCESS_QUERY_LIMITED_INFORMATION, FALSE, static_cast<DWORD>( pid ) );
50+
if ( hProcess == NULL )
51+
return false;
52+
DWORD exitCode;
53+
bool running = GetExitCodeProcess( hProcess, &exitCode ) && exitCode == STILL_ACTIVE;
54+
CloseHandle( hProcess );
55+
return running;
56+
#endif
57+
}
58+
3259
/**
3360
* @brief Constructor. Checks and fires up LocalServer or closes the program
3461
* if another instance already exists
@@ -138,6 +165,13 @@ SingleApplication::SingleApplication( int &argc, char *argv[], bool allowSeconda
138165
}
139166
}
140167

168+
// If the recorded primary PID is no longer running (e.g. force-killed),
169+
// take over as the primary instance
170+
if( inst->primary && !isProcessRunning( inst->primaryPid ) ){
171+
qWarning() << "SingleApplication: Primary instance (PID" << inst->primaryPid << ") is no longer running. Taking over.";
172+
d->initializeMemoryBlock();
173+
}
174+
141175
if( inst->primary == false ){
142176
d->startPrimary();
143177
if( ! d->memory->unlock() ){

0 commit comments

Comments
 (0)