The session daemon checks that no other session daemons are
running only after daemonizing. This means that launching the
deamon in background or daemon modes will appear to succeed even
if the launch failed due to an already present daemon.
The check is performed using both the client socket and the lock
file. This fix also addresses another problem that would cause
the pid file to be overwritten and deleted even if the session daemon
failed to launch.
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
- /*
- * Cleanup lock file by deleting it and finaly closing it which will
- * release the file system lock.
- */
- if (lockfile_fd >= 0) {
- ret = remove(config.lock_file_path.value);
- if (ret < 0) {
- PERROR("remove lock file");
- }
- ret = close(lockfile_fd);
- if (ret < 0) {
- PERROR("close lock file");
- }
- }
-
/*
* We do NOT rmdir rundir because there are other processes
* using it, for instance lttng-relayd, which can start in
/*
* We do NOT rmdir rundir because there are other processes
* using it, for instance lttng-relayd, which can start in
+/*
+ * Create lockfile using the rundir and return its fd.
+ */
+static int create_lockfile(void)
+{
+ return utils_create_lock_file(config.lock_file_path.value);
+}
+
/*
* Check if the global socket is available, and if a daemon is answering at the
* other side. If yes, error is returned.
/*
* Check if the global socket is available, and if a daemon is answering at the
* other side. If yes, error is returned.
+ *
+ * Also attempts to create and hold the lock file.
*/
static int check_existing_daemon(void)
{
*/
static int check_existing_daemon(void)
{
/* Is there anybody out there ? */
if (lttng_session_daemon_alive()) {
/* Is there anybody out there ? */
if (lttng_session_daemon_alive()) {
+ ret = -EEXIST;
+ goto end;
+ lockfile_fd = create_lockfile();
+ if (lockfile_fd < 0) {
+ ret = -EEXIST;
+ goto end;
+ }
+end:
+ return ret;
+}
+
+static void sessiond_cleanup_lock_file(void)
+{
+ int ret;
+
+ /*
+ * Cleanup lock file by deleting it and finaly closing it which will
+ * release the file system lock.
+ */
+ if (lockfile_fd >= 0) {
+ ret = remove(config.lock_file_path.value);
+ if (ret < 0) {
+ PERROR("remove lock file");
+ }
+ ret = close(lockfile_fd);
+ if (ret < 0) {
+ PERROR("close lock file");
+ }
+ }
return utils_create_pid_file(getpid(), config.pid_file_path.value);
}
return utils_create_pid_file(getpid(), config.pid_file_path.value);
}
-/*
- * Create lockfile using the rundir and return its fd.
- */
-static int create_lockfile(void)
-{
- return utils_create_lock_file(config.lock_file_path.value);
-}
-
/*
* Write agent TCP port using the rundir.
*/
/*
* Write agent TCP port using the rundir.
*/
sessiond_config_log(&config);
sessiond_config_log(&config);
+ if (create_lttng_rundir()) {
+ retval = -1;
+ goto exit_options;
+ }
+
+ /* Abort launch if a session daemon is already running. */
+ if (check_existing_daemon()) {
+ ERR("A session daemon is already running.");
+ retval = -1;
+ goto exit_options;
+ }
+
/* Daemonize */
if (config.daemonize || config.background) {
int i;
/* Daemonize */
if (config.daemonize || config.background) {
int i;
/*
* We are in the child. Make sure all other file descriptors are
* closed, in case we are called with more opened file
/*
* We are in the child. Make sure all other file descriptors are
* closed, in case we are called with more opened file
- * descriptors than the standard ones.
+ * descriptors than the standard ones and the lock file.
*/
for (i = 3; i < sysconf(_SC_OPEN_MAX); i++) {
*/
for (i = 3; i < sysconf(_SC_OPEN_MAX); i++) {
+ if (i == lockfile_fd) {
+ continue;
+ }
/* Check if daemon is UID = 0 */
is_root = !getuid();
/* Check if daemon is UID = 0 */
is_root = !getuid();
-
- if (create_lttng_rundir()) {
- retval = -1;
- goto exit_init_data;
- }
-
if (is_root) {
/* Create global run dir with root access */
if (is_root) {
/* Create global run dir with root access */
- lockfile_fd = create_lockfile();
- if (lockfile_fd < 0) {
- retval = -1;
- goto exit_init_data;
- }
-
/* Set consumer initial state */
kernel_consumerd_state = CONSUMER_STOPPED;
ust_consumerd_state = CONSUMER_STOPPED;
/* Set consumer initial state */
kernel_consumerd_state = CONSUMER_STOPPED;
ust_consumerd_state = CONSUMER_STOPPED;
- /*
- * See if daemon already exist.
- */
- if (check_existing_daemon()) {
- ERR("Already running daemon.\n");
- /*
- * We do not goto exit because we must not cleanup()
- * because a daemon is already running.
- */
- retval = -1;
- goto exit_init_data;
- }
-
/*
* Init UST app hash table. Alloc hash table before this point since
* cleanup() can get called after that point.
/*
* Init UST app hash table. Alloc hash table before this point since
* cleanup() can get called after that point.
exit_create_run_as_worker_cleanup:
exit_options:
exit_create_run_as_worker_cleanup:
exit_options:
+ sessiond_cleanup_lock_file();
sessiond_cleanup_options();
exit_set_signal_handler:
sessiond_cleanup_options();
exit_set_signal_handler: