>From 393570b45816b690cb16fd1286d0705142ef2d62 Mon Sep 17 00:00:00 2001
From: Simo Sorce <simo@redhat.com>
Date: Fri, 3 Jan 2014 12:10:36 -0500
Subject: [PATCH 2/2] Block parent process until child is initialized.

This way the init system will not proceed starting dependencies until gssproxy
is actually ready to serve requests.
In particular this is used to make sure the nfsd proc file has been touched
before the nfsd server is started.

Resolves: https://fedorahosted.org/gss-proxy/ticket/114

Signed-off-by: Simo Sorce <simo@redhat.com>
---
 proxy/src/gp_init.c  | 42 +++++++++++++++++++++++++++++++++++++++---
 proxy/src/gp_proxy.h |  3 ++-
 proxy/src/gssproxy.c | 11 +++++++++--
 3 files changed, 50 insertions(+), 6 deletions(-)

diff --git a/proxy/src/gp_init.c b/proxy/src/gp_init.c
index 830ae16a30d90ffa9f536a33d7e6c9519ebc5547..6207a7878aa75963dbdc2a7ac2ca25f7ddb136ab 100644
--- a/proxy/src/gp_init.c
+++ b/proxy/src/gp_init.c
@@ -37,12 +37,22 @@
 #include <grp.h>
 #include "gp_proxy.h"
 
-void init_server(bool daemonize)
+void init_server(bool daemonize, int *wait_fd)
 {
     pid_t pid, sid;
     int ret;
 
+    *wait_fd = -1;
+
     if (daemonize) {
+        int pipefd[2];
+        char buf[1];
+
+        /* create parent-child pipe */
+        ret = pipe(pipefd);
+        if (ret == -1) {
+            exit(EXIT_FAILURE);
+        }
 
         pid = fork();
         if (pid == -1) {
@@ -50,10 +60,22 @@ void init_server(bool daemonize)
             exit(EXIT_FAILURE);
         }
         if (pid != 0) {
-            /* ok kill the parent */
-            exit(EXIT_SUCCESS);
+            /* wait for child to signal it is ready */
+            close(pipefd[1]);
+            ret = gp_safe_read(pipefd[0], buf, 1);
+            if (ret == 1) {
+                /* child signaled all ok */
+                exit(EXIT_SUCCESS);
+            } else {
+                /* lost child, something went wrong */
+                exit(EXIT_FAILURE);
+            }
         }
 
+        /* child */
+        close(pipefd[0]);
+        *wait_fd = pipefd[1];
+
         sid = setsid();
         if (sid == -1) {
             /* setsid error ? abort */
@@ -78,6 +100,20 @@ void init_server(bool daemonize)
     gp_logging_init();
 }
 
+void init_done(int wait_fd)
+{
+    char buf = 0;
+    int ret;
+
+    if (wait_fd != -1) {
+        ret = gp_safe_write(wait_fd, &buf, 1);
+        if (ret != 1) {
+            exit(EXIT_FAILURE);
+        }
+        close(wait_fd);
+    }
+}
+
 void fini_server(void)
 {
     closelog();
diff --git a/proxy/src/gp_proxy.h b/proxy/src/gp_proxy.h
index 733fec515b59ba8df4e2ec3faf54fd6f9db69164..79bebb8872e62cc7857146a0d0fae6e969e725a3 100644
--- a/proxy/src/gp_proxy.h
+++ b/proxy/src/gp_proxy.h
@@ -106,7 +106,8 @@ struct gp_creds_handle *gp_service_get_creds_handle(struct gp_service *svc);
 void free_config(struct gp_config **config);
 
 /* from gp_init.c */
-void init_server(bool daemonize);
+void init_server(bool daemonize, int *wait_fd);
+void init_done(int wait_fd);
 void fini_server(void);
 verto_ctx *init_event_loop(void);
 void init_proc_nfsd(struct gp_config *cfg);
diff --git a/proxy/src/gssproxy.c b/proxy/src/gssproxy.c
index 1bf0a0bc84c7c06642bd8d8e83567d9b6216238f..80430d69a58d56fb593e08ce118274dc733e6a3d 100644
--- a/proxy/src/gssproxy.c
+++ b/proxy/src/gssproxy.c
@@ -42,6 +42,7 @@ int main(int argc, const char *argv[])
     int vflags;
     struct gssproxy_ctx *gpctx;
     struct gp_sock_ctx *sock_ctx;
+    int wait_fd;
     int ret;
     int i;
 
@@ -97,7 +98,7 @@ int main(int argc, const char *argv[])
         exit(EXIT_FAILURE);
     }
 
-    init_server(gpctx->config->daemonize);
+    init_server(gpctx->config->daemonize, &wait_fd);
 
     write_pid();
 
@@ -139,9 +140,15 @@ int main(int argc, const char *argv[])
         }
     }
 
-    /* special call to tell the Linux kernel gss-proxy is available */
+    /* We need to tell nfsd that GSS-Proxy is available before it starts,
+     * as nfsd needs to know GSS-Proxy is in use before the first time it
+     * needs to call accept_sec_context. */
     init_proc_nfsd(gpctx->config);
 
+    /* Now it is safe to tell the init system that we're done starting up,
+     * so it can continue with dependencies and start nfsd */
+    init_done(wait_fd);
+
     ret = drop_privs(gpctx->config);
     if (ret) {
         exit(EXIT_FAILURE);
-- 
1.8.4.2

