2e9afc
commit 0582f6b3d6fab2128ee43a06250571922ee7c1e3
2e9afc
Author: Andreas Schwab <schwab@suse.de>
2e9afc
Date:   Sun Dec 23 09:45:07 2012 +0100
2e9afc
2e9afc
    nscd: don't fork twice
2e9afc
2e9afc
commit 532a60357ef4c5852cc1bf836cfd9d6f093ef204
2e9afc
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
2e9afc
Date:   Mon Mar 3 22:51:39 2014 +0530
2e9afc
2e9afc
    nscd: Improved support for tracking startup failure in nscd service (BZ #16639)
2e9afc
    
2e9afc
    Currently, the nscd parent process parses commandline options and
2e9afc
    configuration, forks on startup and immediately exits with a success.
2e9afc
    If the child process encounters some error after this, it goes
2e9afc
    undetected and any services started up after it may have to repeatedly
2e9afc
    check to make sure that the nscd service did actually start up and is
2e9afc
    serving requests.
2e9afc
    
2e9afc
    To make this process more reliable, I have added a pipe between the
2e9afc
    parent and child process, through which the child process sends a
2e9afc
    notification to the parent informing it of its status.  The parent
2e9afc
    waits for this status and once it receives it, exits with the
2e9afc
    corresponding exit code.  So if the child service sends a success
2e9afc
    status (0), the parent exits with a success status.  Similarly for
2e9afc
    error conditions, the child sends the non-zero status code, which the
2e9afc
    parent passes on as the exit code.
2e9afc
    
2e9afc
    This, along with setting the nscd service type to forking in its
2e9afc
    systemd configuration file, allows systemd to be certain that the nscd
2e9afc
    service is ready and is accepting connections.
2e9afc
2e9afc
12745e
diff --git glibc-2.17-c758a686/nscd/connections.c glibc-2.17-c758a686/nscd/connections.c
2e9afc
index f463f45..180ae77 100644
12745e
--- glibc-2.17-c758a686/nscd/connections.c
12745e
+++ glibc-2.17-c758a686/nscd/connections.c
2e9afc
@@ -649,8 +649,8 @@ cannot create read-only descriptor for \"%s\"; no mmap"),
2e9afc
 		  close (fd);
2e9afc
 	      }
2e9afc
 	    else if (errno == EACCES)
2e9afc
-	      error (EXIT_FAILURE, 0, _("cannot access '%s'"),
2e9afc
-		     dbs[cnt].db_filename);
2e9afc
+	      do_exit (EXIT_FAILURE, 0, _("cannot access '%s'"),
2e9afc
+		       dbs[cnt].db_filename);
2e9afc
 	  }
2e9afc
 
2e9afc
 	if (dbs[cnt].head == NULL)
2e9afc
@@ -699,8 +699,7 @@ cannot create read-only descriptor for \"%s\"; no mmap"),
2e9afc
 		  {
2e9afc
 		    dbg_log (_("database for %s corrupted or simultaneously used; remove %s manually if necessary and restart"),
2e9afc
 			     dbnames[cnt], dbs[cnt].db_filename);
2e9afc
-		    // XXX Correct way to terminate?
2e9afc
-		    exit (1);
2e9afc
+		    do_exit (1, 0, NULL);
2e9afc
 		  }
2e9afc
 
2e9afc
 		if  (dbs[cnt].persistent)
2e9afc
@@ -867,7 +866,7 @@ cannot set socket to close on exec: %s; disabling paranoia mode"),
2e9afc
   if (sock < 0)
2e9afc
     {
2e9afc
       dbg_log (_("cannot open socket: %s"), strerror (errno));
2e9afc
-      exit (errno == EACCES ? 4 : 1);
2e9afc
+      do_exit (errno == EACCES ? 4 : 1, 0, NULL);
2e9afc
     }
2e9afc
   /* Bind a name to the socket.  */
2e9afc
   struct sockaddr_un sock_addr;
2e9afc
@@ -876,7 +875,7 @@ cannot set socket to close on exec: %s; disabling paranoia mode"),
2e9afc
   if (bind (sock, (struct sockaddr *) &sock_addr, sizeof (sock_addr)) < 0)
2e9afc
     {
2e9afc
       dbg_log ("%s: %s", _PATH_NSCDSOCKET, strerror (errno));
2e9afc
-      exit (errno == EACCES ? 4 : 1);
2e9afc
+      do_exit (errno == EACCES ? 4 : 1, 0, NULL);
2e9afc
     }
2e9afc
 
2e9afc
 #ifndef __ASSUME_SOCK_CLOEXEC
2e9afc
@@ -888,7 +887,7 @@ cannot set socket to close on exec: %s; disabling paranoia mode"),
2e9afc
 	{
2e9afc
 	  dbg_log (_("cannot change socket to nonblocking mode: %s"),
2e9afc
 		   strerror (errno));
2e9afc
-	  exit (1);
2e9afc
+	  do_exit (1, 0, NULL);
2e9afc
 	}
2e9afc
 
2e9afc
       /* The descriptor needs to be closed on exec.  */
2e9afc
@@ -896,7 +895,7 @@ cannot set socket to close on exec: %s; disabling paranoia mode"),
2e9afc
 	{
2e9afc
 	  dbg_log (_("cannot set socket to close on exec: %s"),
2e9afc
 		   strerror (errno));
2e9afc
-	  exit (1);
2e9afc
+	  do_exit (1, 0, NULL);
2e9afc
 	}
2e9afc
     }
2e9afc
 #endif
2e9afc
@@ -909,7 +908,7 @@ cannot set socket to close on exec: %s; disabling paranoia mode"),
2e9afc
     {
2e9afc
       dbg_log (_("cannot enable socket to accept connections: %s"),
2e9afc
 	       strerror (errno));
2e9afc
-      exit (1);
2e9afc
+      do_exit (1, 0, NULL);
2e9afc
     }
2e9afc
 
2e9afc
 #ifdef HAVE_NETLINK
2e9afc
@@ -953,7 +952,7 @@ cannot set socket to close on exec: %s; disabling paranoia mode"),
2e9afc
 		      dbg_log (_("\
2e9afc
 cannot change socket to nonblocking mode: %s"),
2e9afc
 			       strerror (errno));
2e9afc
-		      exit (1);
2e9afc
+		      do_exit (1, 0, NULL);
2e9afc
 		    }
2e9afc
 
2e9afc
 		  /* The descriptor needs to be closed on exec.  */
2e9afc
@@ -962,7 +961,7 @@ cannot change socket to nonblocking mode: %s"),
2e9afc
 		    {
2e9afc
 		      dbg_log (_("cannot set socket to close on exec: %s"),
2e9afc
 			       strerror (errno));
2e9afc
-		      exit (1);
2e9afc
+		      do_exit (1, 0, NULL);
2e9afc
 		    }
2e9afc
 		}
2e9afc
 # endif
2e9afc
@@ -2392,7 +2391,7 @@ start_threads (void)
2e9afc
       if (pthread_cond_init (&dbs[i].prune_cond, &condattr) != 0)
2e9afc
 	{
2e9afc
 	  dbg_log (_("could not initialize conditional variable"));
2e9afc
-	  exit (1);
2e9afc
+	  do_exit (1, 0, NULL);
2e9afc
 	}
2e9afc
 
2e9afc
       pthread_t th;
2e9afc
@@ -2400,7 +2399,7 @@ start_threads (void)
2e9afc
 	  && pthread_create (&th, &attr, nscd_run_prune, (void *) i) != 0)
2e9afc
 	{
2e9afc
 	  dbg_log (_("could not start clean-up thread; terminating"));
2e9afc
-	  exit (1);
2e9afc
+	  do_exit (1, 0, NULL);
2e9afc
 	}
2e9afc
     }
2e9afc
 
2e9afc
@@ -2414,13 +2413,17 @@ start_threads (void)
2e9afc
 	  if (i == 0)
2e9afc
 	    {
2e9afc
 	      dbg_log (_("could not start any worker thread; terminating"));
2e9afc
-	      exit (1);
2e9afc
+	      do_exit (1, 0, NULL);
2e9afc
 	    }
2e9afc
 
2e9afc
 	  break;
2e9afc
 	}
2e9afc
     }
2e9afc
 
2e9afc
+  /* Now it is safe to let the parent know that we're doing fine and it can
2e9afc
+     exit.  */
2e9afc
+  notify_parent (0);
2e9afc
+
2e9afc
   /* Determine how much room for descriptors we should initially
2e9afc
      allocate.  This might need to change later if we cap the number
2e9afc
      with MAXCONN.  */
2e9afc
@@ -2465,8 +2468,8 @@ begin_drop_privileges (void)
2e9afc
   if (pwd == NULL)
2e9afc
     {
2e9afc
       dbg_log (_("Failed to run nscd as user '%s'"), server_user);
2e9afc
-      error (EXIT_FAILURE, 0, _("Failed to run nscd as user '%s'"),
2e9afc
-	     server_user);
2e9afc
+      do_exit (EXIT_FAILURE, 0,
2e9afc
+	       _("Failed to run nscd as user '%s'"), server_user);
2e9afc
     }
2e9afc
 
2e9afc
   server_uid = pwd->pw_uid;
2e9afc
@@ -2483,7 +2486,8 @@ begin_drop_privileges (void)
2e9afc
     {
2e9afc
       /* This really must never happen.  */
2e9afc
       dbg_log (_("Failed to run nscd as user '%s'"), server_user);
2e9afc
-      error (EXIT_FAILURE, errno, _("initial getgrouplist failed"));
2e9afc
+      do_exit (EXIT_FAILURE, errno,
2e9afc
+	       _("initial getgrouplist failed"));
2e9afc
     }
2e9afc
 
2e9afc
   server_groups = (gid_t *) xmalloc (server_ngroups * sizeof (gid_t));
2e9afc
@@ -2492,7 +2496,7 @@ begin_drop_privileges (void)
2e9afc
       == -1)
2e9afc
     {
2e9afc
       dbg_log (_("Failed to run nscd as user '%s'"), server_user);
2e9afc
-      error (EXIT_FAILURE, errno, _("getgrouplist failed"));
2e9afc
+      do_exit (EXIT_FAILURE, errno, _("getgrouplist failed"));
2e9afc
     }
2e9afc
 }
2e9afc
 
2e9afc
@@ -2510,7 +2514,7 @@ finish_drop_privileges (void)
2e9afc
   if (setgroups (server_ngroups, server_groups) == -1)
2e9afc
     {
2e9afc
       dbg_log (_("Failed to run nscd as user '%s'"), server_user);
2e9afc
-      error (EXIT_FAILURE, errno, _("setgroups failed"));
2e9afc
+      do_exit (EXIT_FAILURE, errno, _("setgroups failed"));
2e9afc
     }
2e9afc
 
2e9afc
   int res;
2e9afc
@@ -2521,8 +2525,7 @@ finish_drop_privileges (void)
2e9afc
   if (res == -1)
2e9afc
     {
2e9afc
       dbg_log (_("Failed to run nscd as user '%s'"), server_user);
2e9afc
-      perror ("setgid");
2e9afc
-      exit (4);
2e9afc
+      do_exit (4, errno, "setgid");
2e9afc
     }
2e9afc
 
2e9afc
   if (paranoia)
2e9afc
@@ -2532,8 +2535,7 @@ finish_drop_privileges (void)
2e9afc
   if (res == -1)
2e9afc
     {
2e9afc
       dbg_log (_("Failed to run nscd as user '%s'"), server_user);
2e9afc
-      perror ("setuid");
2e9afc
-      exit (4);
2e9afc
+      do_exit (4, errno, "setuid");
2e9afc
     }
2e9afc
 
2e9afc
 #if defined HAVE_LIBAUDIT && defined HAVE_LIBCAP
12745e
diff --git glibc-2.17-c758a686/nscd/nscd.c glibc-2.17-c758a686/nscd/nscd.c
2e9afc
index 63d9d83..5680378 100644
12745e
--- glibc-2.17-c758a686/nscd/nscd.c
12745e
+++ glibc-2.17-c758a686/nscd/nscd.c
2e9afc
@@ -39,6 +39,8 @@
2e9afc
 #include <sys/stat.h>
2e9afc
 #include <sys/uio.h>
2e9afc
 #include <sys/un.h>
2e9afc
+#include <sys/wait.h>
2e9afc
+#include <stdarg.h>
2e9afc
 
2e9afc
 #include "dbg_log.h"
2e9afc
 #include "nscd.h"
2e9afc
@@ -101,6 +103,7 @@ gid_t old_gid;
2e9afc
 
2e9afc
 static int check_pid (const char *file);
2e9afc
 static int write_pid (const char *file);
2e9afc
+static int monitor_child (int fd);
2e9afc
 
2e9afc
 /* Name and version of program.  */
2e9afc
 static void print_version (FILE *stream, struct argp_state *state);
2e9afc
@@ -142,6 +145,7 @@ static struct argp argp =
2e9afc
 
2e9afc
 /* True if only statistics are requested.  */
2e9afc
 static bool get_stats;
2e9afc
+static int parent_fd = -1;
2e9afc
 
2e9afc
 int
2e9afc
 main (int argc, char **argv)
2e9afc
@@ -196,11 +200,27 @@ main (int argc, char **argv)
2e9afc
       /* Behave like a daemon.  */
2e9afc
       if (run_mode == RUN_DAEMONIZE)
2e9afc
 	{
2e9afc
+	  int fd[2];
2e9afc
+
2e9afc
+	  if (pipe (fd) != 0)
2e9afc
+	    error (EXIT_FAILURE, errno,
2e9afc
+		   _("cannot create a pipe to talk to the child"));
2e9afc
+
2e9afc
 	  pid = fork ();
2e9afc
 	  if (pid == -1)
2e9afc
 	    error (EXIT_FAILURE, errno, _("cannot fork"));
2e9afc
 	  if (pid != 0)
2e9afc
-	    exit (0);
2e9afc
+	    {
2e9afc
+	      /* The parent only reads from the child.  */
2e9afc
+	      close (fd[1]);
2e9afc
+	      exit (monitor_child (fd[0]));
2e9afc
+	    }
2e9afc
+	  else
2e9afc
+	    {
2e9afc
+	      /* The child only writes to the parent.  */
2e9afc
+	      close (fd[0]);
2e9afc
+	      parent_fd = fd[1];
2e9afc
+	    }
2e9afc
 	}
2e9afc
 
2e9afc
       int nullfd = open (_PATH_DEVNULL, O_RDWR);
2e9afc
@@ -242,7 +262,8 @@ main (int argc, char **argv)
2e9afc
 	      char *endp;
2e9afc
 	      long int fdn = strtol (dirent->d_name, &endp, 10);
2e9afc
 
2e9afc
-	      if (*endp == '\0' && fdn != dfdn && fdn >= min_close_fd)
2e9afc
+	      if (*endp == '\0' && fdn != dfdn && fdn >= min_close_fd
2e9afc
+		  && fdn != parent_fd)
2e9afc
 		close ((int) fdn);
2e9afc
 	    }
2e9afc
 
2e9afc
@@ -250,22 +271,14 @@ main (int argc, char **argv)
2e9afc
 	}
2e9afc
       else
2e9afc
 	for (i = min_close_fd; i < getdtablesize (); i++)
2e9afc
-	  close (i);
2e9afc
+	  if (i != parent_fd)
2e9afc
+	    close (i);
2e9afc
 
2e9afc
-      if (run_mode == RUN_DAEMONIZE)
2e9afc
-	{
2e9afc
-	  pid = fork ();
2e9afc
-	  if (pid == -1)
2e9afc
-	    error (EXIT_FAILURE, errno, _("cannot fork"));
2e9afc
-	  if (pid != 0)
2e9afc
-	    exit (0);
2e9afc
-	}
2e9afc
-
2e9afc
       setsid ();
2e9afc
 
2e9afc
       if (chdir ("/") != 0)
2e9afc
-	error (EXIT_FAILURE, errno,
2e9afc
-	       _("cannot change current working directory to \"/\""));
2e9afc
+	do_exit (EXIT_FAILURE, errno,
2e9afc
+		 _("cannot change current working directory to \"/\""));
2e9afc
 
2e9afc
       openlog ("nscd", LOG_CONS | LOG_ODELAY, LOG_DAEMON);
2e9afc
 
2e9afc
@@ -592,3 +614,79 @@ write_pid (const char *file)
2e9afc
 
2e9afc
   return result;
2e9afc
 }
2e9afc
+
2e9afc
+static int
2e9afc
+monitor_child (int fd)
2e9afc
+{
2e9afc
+  int child_ret = 0;
2e9afc
+  int ret = read (fd, &child_ret, sizeof (child_ret));
2e9afc
+
2e9afc
+  /* The child terminated with an error, either via exit or some other abnormal
2e9afc
+     method, like a segfault.  */
2e9afc
+  if (ret <= 0 || child_ret != 0)
2e9afc
+    {
2e9afc
+      int err = wait (&child_ret);
2e9afc
+
2e9afc
+      if (err < 0)
2e9afc
+	{
2e9afc
+	  fprintf (stderr, _("wait failed"));
2e9afc
+	  return 1;
2e9afc
+	}
2e9afc
+
2e9afc
+      fprintf (stderr, _("child exited with status %d"),
2e9afc
+	       WEXITSTATUS (child_ret));
2e9afc
+      if (WIFSIGNALED (child_ret))
2e9afc
+	fprintf (stderr, _(", terminated by signal %d.\n"),
2e9afc
+		 WTERMSIG (child_ret));
2e9afc
+      else
2e9afc
+	fprintf (stderr, ".\n");
2e9afc
+    }
2e9afc
+
2e9afc
+  /* We have the child status, so exit with that code.  */
2e9afc
+  close (fd);
2e9afc
+
2e9afc
+  return child_ret;
2e9afc
+}
2e9afc
+
2e9afc
+void
2e9afc
+do_exit (int child_ret, int errnum, const char *format, ...)
2e9afc
+{
2e9afc
+  if (parent_fd != -1)
2e9afc
+    {
2e9afc
+      int ret = write (parent_fd, &child_ret, sizeof (child_ret));
2e9afc
+      assert (ret == sizeof (child_ret));
2e9afc
+      close (parent_fd);
2e9afc
+    }
2e9afc
+
2e9afc
+  if (format != NULL)
2e9afc
+    {
2e9afc
+      /* Emulate error() since we don't have a va_list variant for it.  */
2e9afc
+      va_list argp;
2e9afc
+
2e9afc
+      fflush (stdout);
2e9afc
+
2e9afc
+      fprintf (stderr, "%s: ", program_invocation_name);
2e9afc
+
2e9afc
+      va_start (argp, format);
2e9afc
+      vfprintf (stderr, format, argp);
2e9afc
+      va_end (argp);
2e9afc
+
2e9afc
+      fprintf (stderr, ": %s\n", strerror (errnum));
2e9afc
+      fflush (stderr);
2e9afc
+    }
2e9afc
+
2e9afc
+  /* Finally, exit.  */
2e9afc
+  exit (child_ret);
2e9afc
+}
2e9afc
+
2e9afc
+void
2e9afc
+notify_parent (int child_ret)
2e9afc
+{
2e9afc
+  if (parent_fd == -1)
2e9afc
+    return;
2e9afc
+
2e9afc
+  int ret = write (parent_fd, &child_ret, sizeof (child_ret));
2e9afc
+  assert (ret == sizeof (child_ret));
2e9afc
+  close (parent_fd);
2e9afc
+  parent_fd = -1;
2e9afc
+}
12745e
diff --git glibc-2.17-c758a686/nscd/nscd.h glibc-2.17-c758a686/nscd/nscd.h
2e9afc
index 972f462..529b3f5 100644
12745e
--- glibc-2.17-c758a686/nscd/nscd.h
12745e
+++ glibc-2.17-c758a686/nscd/nscd.h
2e9afc
@@ -205,6 +205,8 @@ extern gid_t old_gid;
2e9afc
 /* nscd.c */
2e9afc
 extern void termination_handler (int signum) __attribute__ ((__noreturn__));
2e9afc
 extern int nscd_open_socket (void);
2e9afc
+void notify_parent (int child_ret);
2e9afc
+void do_exit (int child_ret, int errnum, const char *format, ...);
2e9afc
 
2e9afc
 /* connections.c */
2e9afc
 extern void nscd_init (void);
12745e
diff --git glibc-2.17-c758a686/nscd/selinux.c glibc-2.17-c758a686/nscd/selinux.c
2e9afc
index e477254..46b0ea9 100644
12745e
--- glibc-2.17-c758a686/nscd/selinux.c
12745e
+++ glibc-2.17-c758a686/nscd/selinux.c
2e9afc
@@ -179,7 +179,7 @@ preserve_capabilities (void)
2e9afc
   if (prctl (PR_SET_KEEPCAPS, 1) == -1)
2e9afc
     {
2e9afc
       dbg_log (_("Failed to set keep-capabilities"));
2e9afc
-      error (EXIT_FAILURE, errno, _("prctl(KEEPCAPS) failed"));
2e9afc
+      do_exit (EXIT_FAILURE, errno, _("prctl(KEEPCAPS) failed"));
2e9afc
       /* NOTREACHED */
2e9afc
     }
2e9afc
 
2e9afc
@@ -194,7 +194,7 @@ preserve_capabilities (void)
2e9afc
 	cap_free (tmp_caps);
2e9afc
 
2e9afc
       dbg_log (_("Failed to initialize drop of capabilities"));
2e9afc
-      error (EXIT_FAILURE, 0, _("cap_init failed"));
2e9afc
+      do_exit (EXIT_FAILURE, 0, _("cap_init failed"));
2e9afc
     }
2e9afc
 
2e9afc
   /* There is no reason why these should not work.  */
2e9afc
@@ -216,7 +216,7 @@ preserve_capabilities (void)
2e9afc
     {
2e9afc
       cap_free (new_caps);
2e9afc
       dbg_log (_("Failed to drop capabilities"));
2e9afc
-      error (EXIT_FAILURE, 0, _("cap_set_proc failed"));
2e9afc
+      do_exit (EXIT_FAILURE, 0, _("cap_set_proc failed"));
2e9afc
     }
2e9afc
 
2e9afc
   return new_caps;
2e9afc
@@ -233,7 +233,7 @@ install_real_capabilities (cap_t new_caps)
2e9afc
     {
2e9afc
       cap_free (new_caps);
2e9afc
       dbg_log (_("Failed to drop capabilities"));
2e9afc
-      error (EXIT_FAILURE, 0, _("cap_set_proc failed"));
2e9afc
+      do_exit (EXIT_FAILURE, 0, _("cap_set_proc failed"));
2e9afc
       /* NOTREACHED */
2e9afc
     }
2e9afc
 
2e9afc
@@ -242,7 +242,7 @@ install_real_capabilities (cap_t new_caps)
2e9afc
   if (prctl (PR_SET_KEEPCAPS, 0) == -1)
2e9afc
     {
2e9afc
       dbg_log (_("Failed to unset keep-capabilities"));
2e9afc
-      error (EXIT_FAILURE, errno, _("prctl(KEEPCAPS) failed"));
2e9afc
+      do_exit (EXIT_FAILURE, errno, _("prctl(KEEPCAPS) failed"));
2e9afc
       /* NOTREACHED */
2e9afc
     }
2e9afc
 }
2e9afc
@@ -258,7 +258,7 @@ nscd_selinux_enabled (int *selinux_enabled)
2e9afc
   if (*selinux_enabled < 0)
2e9afc
     {
2e9afc
       dbg_log (_("Failed to determine if kernel supports SELinux"));
2e9afc
-      exit (EXIT_FAILURE);
2e9afc
+      do_exit (EXIT_FAILURE, 0, NULL);
2e9afc
     }
2e9afc
 }
2e9afc
 
2e9afc
@@ -272,7 +272,7 @@ avc_create_thread (void (*run) (void))
2e9afc
   rc =
2e9afc
     pthread_create (&avc_notify_thread, NULL, (void *(*) (void *)) run, NULL);
2e9afc
   if (rc != 0)
2e9afc
-    error (EXIT_FAILURE, rc, _("Failed to start AVC thread"));
2e9afc
+    do_exit (EXIT_FAILURE, rc, _("Failed to start AVC thread"));
2e9afc
 
2e9afc
   return &avc_notify_thread;
2e9afc
 }
2e9afc
@@ -294,7 +294,7 @@ avc_alloc_lock (void)
2e9afc
 
2e9afc
   avc_mutex = malloc (sizeof (pthread_mutex_t));
2e9afc
   if (avc_mutex == NULL)
2e9afc
-    error (EXIT_FAILURE, errno, _("Failed to create AVC lock"));
2e9afc
+    do_exit (EXIT_FAILURE, errno, _("Failed to create AVC lock"));
2e9afc
   pthread_mutex_init (avc_mutex, NULL);
2e9afc
 
2e9afc
   return avc_mutex;
2e9afc
@@ -334,7 +334,7 @@ nscd_avc_init (void)
2e9afc
   avc_entry_ref_init (&aeref);
2e9afc
 
2e9afc
   if (avc_init ("avc", NULL, &log_cb, &thread_cb, &lock_cb) < 0)
2e9afc
-    error (EXIT_FAILURE, errno, _("Failed to start AVC"));
2e9afc
+    do_exit (EXIT_FAILURE, errno, _("Failed to start AVC"));
2e9afc
   else
2e9afc
     dbg_log (_("Access Vector Cache (AVC) started"));
2e9afc
 #ifdef HAVE_LIBAUDIT
12745e
--- glibc-2.17-c758a686/releng/nscd.service	2012-11-06 03:03:19.000000000 +0530
12745e
+++ glibc-2.17-c758a686/releng/nscd.service	2014-02-28 16:59:51.096630222 +0530
2e9afc
@@ -1,10 +1,13 @@
2e9afc
+# systemd service file for nscd
2e9afc
+
2e9afc
 [Unit]
2e9afc
 Description=Name Service Cache Daemon
2e9afc
 After=syslog.target
2e9afc
 
2e9afc
 [Service]
2e9afc
+Type=forking
2e9afc
 EnvironmentFile=-/etc/sysconfig/nscd
2e9afc
-ExecStart=/usr/sbin/nscd --foreground $NSCD_OPTIONS
2e9afc
+ExecStart=/usr/sbin/nscd $NSCD_OPTIONS
2e9afc
 ExecStop=/usr/sbin/nscd --shutdown
2e9afc
 ExecReload=/usr/sbin/nscd -i passwd
2e9afc
 ExecReload=/usr/sbin/nscd -i group
2e9afc
@@ -12,6 +14,7 @@
2e9afc
 ExecReload=/usr/sbin/nscd -i services
2e9afc
 ExecReload=/usr/sbin/nscd -i netgroup
2e9afc
 Restart=always
2e9afc
+PIDFile=/run/nscd/nscd.pid
2e9afc
 
2e9afc
 [Install]
2e9afc
 WantedBy=multi-user.target