#include <time.h>
#include <unistd.h>
#include <signal.h>
+#include <sys/wait.h>
#include <common/mi-lttng.h>
pid_t pid;
MSG("Spawning a session daemon");
- recv_child_signal = 0;
pid = fork();
if (pid == 0) {
/*
- * Spawn session daemon and tell
- * it to signal us when ready.
+ * Spawn session daemon in daemon mode.
*/
- execlp(pathname, "lttng-sessiond", "--sig-parent", "--quiet", NULL);
+ execlp(pathname, "lttng-sessiond",
+ "--daemonize", NULL);
/* execlp only returns if error happened */
if (errno == ENOENT) {
ERR("No session daemon found. Use --sessiond-path.");
kill(getppid(), SIGTERM); /* wake parent */
exit(EXIT_FAILURE);
} else if (pid > 0) {
- sessiond_pid = pid;
- /*
- * Wait for lttng-sessiond to start. We need to use a flag to check if
- * the signal has been sent to us, because the child can be scheduled
- * before the parent, and thus send the signal before this check. In
- * the signal handler, we set the recv_child_signal flag, so anytime we
- * check it after the fork is fine. Note that sleep() is interrupted
- * before the 1 second delay as soon as the signal is received, so it
- * will not cause visible delay for the user.
- */
- while (!recv_child_signal) {
- sleep(1);
- }
+ int status;
+
/*
- * The signal handler will nullify sessiond_pid on SIGCHLD
+ * In daemon mode (--daemonize), sessiond only exits when
+ * it's ready to accept commands.
*/
- if (!sessiond_pid) {
- exit(EXIT_FAILURE);
+ for (;;) {
+ waitpid(pid, &status, 0);
+
+ if (WIFSIGNALED(status)) {
+ ERR("Session daemon was killed by signal %d",
+ WTERMSIG(status));
+ ret = -1;
+ goto end;
+ } else if (WIFEXITED(status)) {
+ DBG("Session daemon terminated normally (exit status: %d)",
+ WEXITSTATUS(status));
+
+ if (WEXITSTATUS(status) != 0) {
+ ERR("Session daemon terminated with an error (exit status: %d)",
+ WEXITSTATUS(status));
+ ret = -1;
+ goto end;
+ }
+ break;
+ }
}
+
goto end;
} else {
PERROR("fork");
static char *progname;
int opt_no_sessiond;
char *opt_sessiond_path;
-pid_t sessiond_pid;
-volatile int recv_child_signal;
char *opt_relayd_path;
*/
static void sighandler(int sig)
{
- int status;
-
switch (sig) {
case SIGTERM:
DBG("SIGTERM caught");
clean_exit(EXIT_FAILURE);
break;
- case SIGCHLD:
- DBG("SIGCHLD caught");
- waitpid(sessiond_pid, &status, 0);
- recv_child_signal = 1;
- /* Indicate that the session daemon died */
- sessiond_pid = 0;
- ERR("Session daemon died (exit status %d)", WEXITSTATUS(status));
- break;
- case SIGUSR1:
- /* Notify is done */
- recv_child_signal = 1;
- DBG("SIGUSR1 caught");
- break;
default:
DBG("Unknown signal %d caught", sig);
break;
sa.sa_handler = sighandler;
sa.sa_mask = sigset;
sa.sa_flags = 0;
- if ((ret = sigaction(SIGUSR1, &sa, NULL)) < 0) {
- PERROR("sigaction");
- goto end;
- }
if ((ret = sigaction(SIGTERM, &sa, NULL)) < 0) {
PERROR("sigaction");
goto end;
}
- if ((ret = sigaction(SIGCHLD, &sa, NULL)) < 0) {
- PERROR("sigaction");
- goto end;
- }
-
end:
return ret;
}