labwc/src/common/spawn.c

61 lines
1.1 KiB
C
Raw Normal View History

#define _POSIX_C_SOURCE 200809L
#include <assert.h>
2020-06-19 22:00:22 +01:00
#include <glib.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include "common/log.h"
#include "common/spawn.h"
2020-06-19 22:00:22 +01:00
void
spawn_async_no_shell(char const *command)
2020-06-19 22:00:22 +01:00
{
GError *err = NULL;
gchar **argv = NULL;
assert(command);
/* Use glib's shell-parse to mimic Openbox's behaviour */
2020-06-19 22:00:22 +01:00
g_shell_parse_argv((gchar *)command, NULL, &argv, &err);
if (err) {
g_message("%s", err->message);
g_error_free(err);
return;
}
/*
* Avoid zombie processes by using a double-fork, whereby the
* grandchild becomes orphaned & the responsibility of the OS.
*/
pid_t child = 0, grandchild = 0;
child = fork();
switch (child) {
case -1:
warn("unable to fork()");
goto out;
case 0:
setsid();
sigset_t set;
sigemptyset(&set);
sigprocmask(SIG_SETMASK, &set, NULL);
grandchild = fork();
if (grandchild == 0) {
execvp(argv[0], argv);
2021-02-15 17:57:20 +00:00
_exit(0);
} else if (grandchild < 0) {
warn("unable to fork()");
}
2021-02-15 17:57:20 +00:00
_exit(0);
default:
break;
2020-06-19 22:00:22 +01:00
}
waitpid(child, NULL, 0);
out:
2020-06-19 22:00:22 +01:00
g_strfreev(argv);
}