forked from quickshell/quickshell
core/command: add --daemonize
This commit is contained in:
parent
9d21a01153
commit
01f6331cb7
1 changed files with 77 additions and 4 deletions
|
@ -1,5 +1,7 @@
|
||||||
#include "main.hpp"
|
#include "main.hpp"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <cerrno>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
@ -8,6 +10,7 @@
|
||||||
#include <CLI/App.hpp>
|
#include <CLI/App.hpp>
|
||||||
#include <CLI/CLI.hpp> // NOLINT: Need to include this for impls of some CLI11 classes
|
#include <CLI/CLI.hpp> // NOLINT: Need to include this for impls of some CLI11 classes
|
||||||
#include <CLI/Validators.hpp>
|
#include <CLI/Validators.hpp>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <qapplication.h>
|
#include <qapplication.h>
|
||||||
#include <qcontainerfwd.h>
|
#include <qcontainerfwd.h>
|
||||||
#include <qcoreapplication.h>
|
#include <qcoreapplication.h>
|
||||||
|
@ -55,6 +58,34 @@ using qs::ipc::IpcClient;
|
||||||
void checkCrashRelaunch(char** argv, QCoreApplication* coreApplication);
|
void checkCrashRelaunch(char** argv, QCoreApplication* coreApplication);
|
||||||
int runCommand(int argc, char** argv, QCoreApplication* coreApplication);
|
int runCommand(int argc, char** argv, QCoreApplication* coreApplication);
|
||||||
|
|
||||||
|
int DAEMON_PIPE = -1; // NOLINT
|
||||||
|
void exitDaemon(int code) {
|
||||||
|
if (DAEMON_PIPE == -1) return;
|
||||||
|
|
||||||
|
if (write(DAEMON_PIPE, &code, sizeof(int)) == -1) {
|
||||||
|
qCritical().nospace() << "Failed to write daemon exit command with error code " << errno << ": "
|
||||||
|
<< qt_error_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
close(DAEMON_PIPE);
|
||||||
|
|
||||||
|
close(STDIN_FILENO);
|
||||||
|
close(STDOUT_FILENO);
|
||||||
|
close(STDERR_FILENO);
|
||||||
|
|
||||||
|
if (open("/dev/null", O_RDONLY) != STDIN_FILENO) { // NOLINT
|
||||||
|
qFatal() << "Failed to open /dev/null on stdin";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (open("/dev/null", O_WRONLY) != STDOUT_FILENO) { // NOLINT
|
||||||
|
qFatal() << "Failed to open /dev/null on stdout";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (open("/dev/null", O_WRONLY) != STDERR_FILENO) { // NOLINT
|
||||||
|
qFatal() << "Failed to open /dev/null on stderr";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
QCoreApplication::setApplicationName("quickshell");
|
QCoreApplication::setApplicationName("quickshell");
|
||||||
|
|
||||||
|
@ -66,7 +97,10 @@ int main(int argc, char** argv) {
|
||||||
auto* coreApplication = new QCoreApplication(qArgC, argv);
|
auto* coreApplication = new QCoreApplication(qArgC, argv);
|
||||||
|
|
||||||
checkCrashRelaunch(argv, coreApplication);
|
checkCrashRelaunch(argv, coreApplication);
|
||||||
return runCommand(argc, argv, coreApplication);
|
auto code = runCommand(argc, argv, coreApplication);
|
||||||
|
|
||||||
|
exitDaemon(code);
|
||||||
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
class QStringOption {
|
class QStringOption {
|
||||||
|
@ -133,6 +167,7 @@ struct CommandState {
|
||||||
bool printVersion = false;
|
bool printVersion = false;
|
||||||
bool killAll = false;
|
bool killAll = false;
|
||||||
bool noDuplicate = false;
|
bool noDuplicate = false;
|
||||||
|
bool daemonize = false;
|
||||||
} misc;
|
} misc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -241,8 +276,11 @@ int runCommand(int argc, char** argv, QCoreApplication* coreApplication) {
|
||||||
cli.add_flag("-V,--version", state.misc.printVersion)
|
cli.add_flag("-V,--version", state.misc.printVersion)
|
||||||
->description("Print quickshell's version and exit.");
|
->description("Print quickshell's version and exit.");
|
||||||
|
|
||||||
cli.add_flag("--no-duplicate", state.misc.noDuplicate)
|
cli.add_flag("-n,--no-duplicate", state.misc.noDuplicate)
|
||||||
->description("Exit immediately if another instance of the given config is running.");
|
->description("Exit immediately if another instance of the given config is running.");
|
||||||
|
|
||||||
|
cli.add_flag("-d,--daemonize", state.misc.daemonize)
|
||||||
|
->description("Detach from the controlling terminal.");
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -295,6 +333,39 @@ int runCommand(int argc, char** argv, QCoreApplication* coreApplication) {
|
||||||
|
|
||||||
CLI11_PARSE(cli, argc, argv);
|
CLI11_PARSE(cli, argc, argv);
|
||||||
|
|
||||||
|
// Has to happen before extra threads are spawned.
|
||||||
|
if (state.misc.daemonize) {
|
||||||
|
auto closepipes = std::array<int, 2>();
|
||||||
|
if (pipe(closepipes.data()) == -1) {
|
||||||
|
qFatal().nospace() << "Failed to create messaging pipes for daemon with error " << errno
|
||||||
|
<< ": " << qt_error_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
DAEMON_PIPE = closepipes[1];
|
||||||
|
|
||||||
|
pid_t pid = fork(); // NOLINT (include)
|
||||||
|
|
||||||
|
if (pid == -1) {
|
||||||
|
qFatal().nospace() << "Failed to fork daemon with error " << errno << ": "
|
||||||
|
<< qt_error_string();
|
||||||
|
} else if (pid == 0) {
|
||||||
|
close(closepipes[0]);
|
||||||
|
|
||||||
|
if (setsid() == -1) {
|
||||||
|
qFatal().nospace() << "Failed to setsid with error " << errno << ": " << qt_error_string();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
close(closepipes[1]);
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
|
if (read(closepipes[0], &ret, sizeof(int)) == -1) {
|
||||||
|
qFatal() << "Failed to wait for daemon launch (it may have crashed)";
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto level = state.log.verbosity == 0 ? QtWarningMsg
|
auto level = state.log.verbosity == 0 ? QtWarningMsg
|
||||||
: state.log.verbosity == 1 ? QtInfoMsg
|
: state.log.verbosity == 1 ? QtInfoMsg
|
||||||
|
@ -489,7 +560,7 @@ int readLogFile(CommandState& cmd) {
|
||||||
|
|
||||||
int listInstances(CommandState& cmd) {
|
int listInstances(CommandState& cmd) {
|
||||||
auto* basePath = QsPaths::instance()->baseRunDir();
|
auto* basePath = QsPaths::instance()->baseRunDir();
|
||||||
if (!basePath) exit(-1); // NOLINT
|
if (!basePath) return -1; // NOLINT
|
||||||
|
|
||||||
QString path;
|
QString path;
|
||||||
QString configFilePath;
|
QString configFilePath;
|
||||||
|
@ -648,7 +719,7 @@ int launchFromCommand(CommandState& cmd, QCoreApplication* coreApplication) {
|
||||||
{
|
{
|
||||||
InstanceLockInfo info;
|
InstanceLockInfo info;
|
||||||
if (cmd.misc.noDuplicate && selectInstance(cmd, &info) == 0) {
|
if (cmd.misc.noDuplicate && selectInstance(cmd, &info) == 0) {
|
||||||
qCDebug(logBare) << "An instance of this configuration is already running.";
|
qCInfo(logBare) << "An instance of this configuration is already running.";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -834,6 +905,8 @@ int launch(const LaunchArgs& args, char** argv, QCoreApplication* coreApplicatio
|
||||||
auto root = RootWrapper(args.configPath, shellId);
|
auto root = RootWrapper(args.configPath, shellId);
|
||||||
QGuiApplication::setQuitOnLastWindowClosed(false);
|
QGuiApplication::setQuitOnLastWindowClosed(false);
|
||||||
|
|
||||||
|
exitDaemon(0);
|
||||||
|
|
||||||
auto code = QGuiApplication::exec();
|
auto code = QGuiApplication::exec();
|
||||||
delete app;
|
delete app;
|
||||||
return code;
|
return code;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue