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