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