(ckb) Added --close option to quit ckb instead of opening it

(ckb) Added --version option to print current version
(ckb) Fixed "ckb is already running" after the program had crashed
New shared memory format allows storing the PID as well as a more robust command format. This will be put to more use later.
This commit is contained in:
ccMSC
2015-06-26 01:01:52 -06:00
parent c98bffa9d1
commit c607e3cd59
3 changed files with 101 additions and 17 deletions
+4 -2
View File
@@ -63,7 +63,6 @@ if [[ ! -d $BINDIR ]]; then
echo "There is nothing to do."
finish 0
fi
# Offer to install ckb at a standard location
shopt -s nocasematch
read -rp "Install ckb system-wide [Y/n]? " doinstall
@@ -191,8 +190,11 @@ sleep 1
echo ""
read -rp "Start ckb now [Y/n]? " dolaunch
[[ $dolaunch =~ no? ]] && exit 0
sleep 0.5
APP=$PREFIX/ckb
[[ "$OSTYPE" == "darwin"* ]] && APP=$APP.app/Contents/MacOS/ckb
# Ask ckb to close if there's an instance already running
$APP --close >/dev/null 2>&1
sleep 0.5
# Launch
nohup $APP >/dev/null 2>&1 &
exit 0
+76 -10
View File
@@ -3,6 +3,9 @@
#include <QDateTime>
#include <QSharedMemory>
#include <cstring>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
QSharedMemory appShare("ckb");
@@ -12,17 +15,64 @@ QSharedMemory appShare("ckb");
extern "C" void disableAppNap();
#endif
bool isRunning(bool showWindow){
if(!appShare.create(16)){
if(!appShare.attach() || !appShare.lock())
return false;
if(showWindow){
void* data = appShare.data();
snprintf((char*)data, 16, "Open");
// Shared memory sizes
#define SHMEM_SIZE 128 * 1024
#define SHMEM_SIZE_V015 16
// Scan shared memory for an active PID
static bool pidActive(const QStringList& lines){
foreach(const QString& line, lines){
if(line.startsWith("PID ")){
bool ok;
pid_t pid;
// Valid PID found?
if((pid = line.split(" ")[1].toLong(&ok)) > 0 && ok){
// kill -0 does nothing to the application, but checks if it's running
return (kill(pid, 0) == 0 || errno != ESRCH);
}
}
appShare.unlock();
return true;
}
// If the PID wasn't listed in the shmem, assume it is running
return true;
}
// Check if the application is running. Optionally write something to its shared memory.
static bool isRunning(const char* command){
// Try to create shared memory (if successful, application was not already running)
if(!appShare.create(SHMEM_SIZE) || !appShare.lock()){
// Lock existing shared memory
if(!appShare.attach() || !appShare.lock())
return true;
bool running = false;
if(appShare.size() == SHMEM_SIZE_V015){
// Old shmem - no PID listed so assume the process is running, and print the command directly to the buffer
if(command){
void* data = appShare.data();
snprintf((char*)data, SHMEM_SIZE_V015, "%s", command);
}
running = true;
} else {
// New shmem. Scan the contents of the shared memory for a PID
QStringList lines = QString((const char*)appShare.constData()).split("\n");
if(pidActive(lines)){
running = true;
// Append the command
if(command){
lines.append(QString("Option ") + command);
QByteArray newMem = lines.join("\n").left(SHMEM_SIZE).toLatin1();
// Copy the NUL byte as well as the string
memcpy(appShare.data(), newMem.constData(), newMem.length() + 1);
}
}
}
if(running){
appShare.unlock();
return true;
}
}
// Not already running. Initialize the shared memory with our PID
snprintf((char*)appShare.data(), appShare.size(), "PID %ld", (long)getpid());
appShare.unlock();
return false;
}
@@ -40,8 +90,24 @@ int main(int argc, char *argv[]){
qApp->setAttribute(Qt::AA_UseHighDpiPixmaps);
#endif
// If launched with --version, print version info and then quit
if(qApp->arguments().contains("--version")){
printf("ckb %s\n", CKB_VERSION_STR);
return 0;
}
// Kill existing app when launched with --close
if(qApp->arguments().contains("--close")){
if(isRunning("Close"))
printf("Asking existing instance to close.\n");
else
printf("ckb is not running.\n");
return 0;
}
// Launch in background if requested
bool background = qApp->arguments().contains("--background");
if(isRunning(!background)){
if(isRunning(background ? 0 : "Open")){
printf("ckb is already running. Exiting.\n");
return 0;
}
+21 -5
View File
@@ -6,6 +6,7 @@
#include <QShortcut>
#include <QMessageBox>
#include <QMenuBar>
#include <unistd.h>
extern QSharedMemory appShare;
@@ -204,14 +205,29 @@ void MainWindow::closeEvent(QCloseEvent *event){
}
void MainWindow::timerTick(){
// Check if another instance requested this in the foreground
// Check shared memory for changes
if(appShare.lock()){
void* data = appShare.data();
if((QString)QByteArray((const char*)data) == "Open")
showWindow();
// Remove the request
*(char*)data = 0;
QStringList commands = QString((const char*)data).split("\n");
// Restore PID, remove all other data
snprintf((char*)appShare.data(), appShare.size(), "PID %ld", (long)getpid());
appShare.unlock();
// Parse commands
foreach(const QString& line, commands){
// Old ckb option line - bring application to foreground
if(line == "Open")
showWindow();
if(line.startsWith("Option ")){
// New ckb option line
QString option = line.split(" ")[1];
if(option == "Open")
// Bring to foreground
showWindow();
else if(option == "Close")
// Quit application
qApp->quit();
}
}
}
// Check for firmware updates (when appropriate)
if(!CkbSettings::get("Program/DisableAutoFWCheck").toBool())