#include <sys/types.h>
#include <time.h>
#include <unistd.h>
+#include <signal.h>
#include <common/mi-lttng.h>
return ret;
}
+/*
+ * spawn_sessiond
+ *
+ * Spawn a session daemon by forking and execv.
+ */
+static int spawn_sessiond(char *pathname)
+{
+ int ret = 0;
+ 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.
+ */
+ execlp(pathname, "lttng-sessiond", "--sig-parent", "--quiet", NULL);
+ /* execlp only returns if error happened */
+ if (errno == ENOENT) {
+ ERR("No session daemon found. Use --sessiond-path.");
+ } else {
+ PERROR("execlp");
+ }
+ 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);
+ }
+ /*
+ * The signal handler will nullify sessiond_pid on SIGCHLD
+ */
+ if (!sessiond_pid) {
+ exit(EXIT_FAILURE);
+ }
+ goto end;
+ } else {
+ PERROR("fork");
+ ret = -1;
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+/*
+ * launch_sessiond
+ *
+ * Check if the session daemon is available using
+ * the liblttngctl API for the check. If not, try to
+ * spawn a daemon.
+ */
+static int launch_sessiond(void)
+{
+ int ret;
+ char *pathname = NULL;
+
+ ret = lttng_session_daemon_alive();
+ if (ret) {
+ /* Sessiond is alive, not an error */
+ ret = 0;
+ goto end;
+ }
+
+ /* Try command line option path */
+ pathname = opt_sessiond_path;
+
+ /* Try LTTNG_SESSIOND_PATH env variable */
+ if (pathname == NULL) {
+ pathname = getenv(DEFAULT_SESSIOND_PATH_ENV);
+ }
+
+ /* Try with configured path */
+ if (pathname == NULL) {
+ if (CONFIG_SESSIOND_BIN[0] != '\0') {
+ pathname = CONFIG_SESSIOND_BIN;
+ }
+ }
+
+ /* Try the default path */
+ if (pathname == NULL) {
+ pathname = INSTALL_BIN_PATH "/lttng-sessiond";
+ }
+
+ DBG("Session daemon binary path: %s", pathname);
+
+ /* Check existence and permissions */
+ ret = access(pathname, F_OK | X_OK);
+ if (ret < 0) {
+ ERR("No such file or access denied: %s", pathname);
+ goto end;
+ }
+
+ ret = spawn_sessiond(pathname);
+ if (ret < 0) {
+ ERR("Problem occurred when starting %s", pathname);
+ }
+end:
+ return ret;
+}
+
/*
* The 'create <options>' first level command
*
goto end;
}
+ /* Spawn a session daemon if needed */
+ if (!opt_no_sessiond) {
+ ret = launch_sessiond();
+ if (ret) {
+ ret = CMD_ERROR;
+ goto end;
+ }
+ }
+
/* MI initialization */
if (lttng_opt_mi) {
writer = mi_lttng_writer_create(fileno(stdout), lttng_opt_mi);