summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/monitor/monitor.c41
-rw-r--r--src/util/server.c35
-rw-r--r--src/util/util.h1
3 files changed, 73 insertions, 4 deletions
diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
index ea600ba3a..8f1be95af 100644
--- a/src/monitor/monitor.c
+++ b/src/monitor/monitor.c
@@ -142,6 +142,8 @@ struct mt_ctx {
struct sss_domain_info *domains;
TALLOC_CTX *service_ctx; /* Memory context for services */
char **services;
+ int num_services;
+ int started_services;
struct mt_svc *svc_list;
struct sbus_connection *sbus_srv;
struct config_file_ctx *file_ctx;
@@ -151,6 +153,8 @@ struct mt_ctx {
bool services_started;
struct netlink_ctx *nlctx;
struct sss_sigchild_ctx *sigchld_ctx;
+ bool is_daemon;
+ pid_t parent_pid;
};
static int start_service(struct mt_svc *mt_svc);
@@ -422,6 +426,34 @@ static int mark_service_as_started(struct mt_svc *svc)
}
}
+ if (svc->type == MT_SVC_SERVICE) {
+ ctx->started_services++;
+ }
+
+ if (ctx->started_services == ctx->num_services) {
+ /* Initialization is complete, terminate parent process if in daemon
+ * mode. Make sure we send the signal to the right process */
+ if (ctx->is_daemon) {
+ if (ctx->parent_pid <= 1 || ctx->parent_pid != getppid()) {
+ /* the parent process was already terminated */
+ DEBUG(SSSDBG_MINOR_FAILURE, ("Invalid parent pid: %d\n",
+ ctx->parent_pid));
+ goto done;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, ("SSSD is initialized, "
+ "terminating parent process\n"));
+
+ errno = 0;
+ ret = kill(ctx->parent_pid, SIGTERM);
+ if (ret != 0) {
+ ret = errno;
+ DEBUG(SSSDBG_FATAL_FAILURE, ("Unable to terminate parent "
+ "process [%d]: %s\n", ret, strerror(ret)));
+ }
+ }
+ }
+
done:
return ret;
}
@@ -783,6 +815,7 @@ int get_monitor_config(struct mt_ctx *ctx)
int ret;
int timeout_seconds;
char *badsrv = NULL;
+ int i;
ret = confdb_get_int(ctx->cdb, ctx,
CONFDB_MONITOR_CONF_ENTRY,
@@ -813,6 +846,12 @@ int get_monitor_config(struct mt_ctx *ctx)
return EINVAL;
}
+ ctx->started_services = 0;
+ ctx->num_services = 0;
+ for (i = 0; ctx->services[i] != NULL; i++) {
+ ctx->num_services++;
+ }
+
ctx->domain_ctx = talloc_new(ctx);
if(!ctx->domain_ctx) {
return ENOMEM;
@@ -2460,6 +2499,8 @@ int main(int argc, const char *argv[])
ret = server_setup("sssd", flags, CONFDB_MONITOR_CONF_ENTRY, &main_ctx);
if (ret != EOK) return 2;
+ monitor->is_daemon = !opt_interactive;
+ monitor->parent_pid = main_ctx->parent_pid;
monitor->ev = main_ctx->event_ctx;
talloc_steal(main_ctx, monitor);
diff --git a/src/util/server.c b/src/util/server.c
index 1e8b148d7..41c0d97a5 100644
--- a/src/util/server.c
+++ b/src/util/server.c
@@ -25,6 +25,7 @@
#define _GNU_SOURCE
#include <sys/types.h>
+#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
@@ -67,18 +68,43 @@ static void close_low_fds(void)
#endif
}
+static void deamon_parent_sigterm(int sig)
+{
+ _exit(0);
+}
+
/**
Become a daemon, discarding the controlling terminal.
**/
void become_daemon(bool Fork)
{
- int ret;
+ pid_t pid;
+ int status;
+ int ret;
if (Fork) {
- if (fork()) {
- _exit(0);
- }
+ pid = fork();
+ if (pid != 0) {
+ /* Terminate parent process on demand so we can hold systemd
+ * or initd from starting next service until sssd in initialized.
+ * We use signals directly here because we don't have a tevent
+ * context yet. */
+ CatchSignal(SIGTERM, deamon_parent_sigterm);
+
+ /* or exit when sssd monitor is terminated */
+ waitpid(pid, &status, 0);
+
+ /* return error if we didn't exited normally */
+ ret = 1;
+
+ if (WIFEXITED(status)) {
+ /* but return our exit code otherwise */
+ ret = WEXITSTATUS(status);
+ }
+
+ _exit(ret);
+ }
}
/* detach from the terminal */
@@ -430,6 +456,7 @@ int server_setup(const char *name, int flags,
return ENOMEM;
}
+ ctx->parent_pid = getppid();
ctx->event_ctx = event_ctx;
conf_db = talloc_asprintf(ctx, "%s/%s", DB_PATH, CONFDB_FILE);
diff --git a/src/util/util.h b/src/util/util.h
index 43017aa0d..1bc469282 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -276,6 +276,7 @@ void sss_log(int priority, const char *format, ...);
struct main_context {
struct tevent_context *event_ctx;
struct confdb_ctx *confdb_ctx;
+ pid_t parent_pid;
};
int die_if_parent_died(void);