Skip to contentSkip to conversation

nfs-utils - 3 of 6 -statd - Ensure child process is running for before the parent exits

PATCH New Steve Dickson 1 participant 1 message Jun 18, 2003

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 nfs-utils - 3 of 6 -statd - Ensure child process is running for before the parent exits

To make sure the correct start-up status is returned to the rc script during boot, the parent statd process must know if the child process (i.e. "real" daemon) was able to successfully start. Otherwise, the child can die and the parent will returns success which would cause networks lock to hang (unexplainable)....

SteveD.

utils/statd/statd.c renamed from utils/statd/statd.c.org +51 -7
@@ -46,6 +46,7 @@ char *  SM_STAT_PATH = DEFAULT_SM_STAT_P
 
 short int restart = 0;
 int	run_mode = 0;		/* foreground logging mode */
+int pfds[2] = {-1, -1};            /* pipe fds */
 
 /* LH - I had these local to main, but it seemed silly to have 
  * two copies of each - one in main(), one static in log.c... 
@@ -79,14 +80,20 @@ extern void simulator (int, char **);
  */
 static const char *piddir="/var/run/rpc.statd";
 static const char *pidfile="/var/run/rpc.statd/rpc.statd.pid";
+static const char *mypidfile = NULL;
 static void
 delete_pidfile(void)
 {
-	if (unlink(pidfile) < 0) {
-		log(L_WARNING,"Unlinking %s failed: errno %d (%s)\n", pidfile,
-			errno, strerror(errno));
+	/*
+	 * Only delete the pidfile if this is
+	 * the process that created it
+	 */ 
+	if (mypidfile) {
+		if (unlink(mypidfile) < 0) {
+			log(L_WARNING,"Unlinking %s failed: errno %d (%s)\n", mypidfile,
+				errno, strerror(errno));
+		}
 	}
-
 	return;
 }
 static void
@@ -115,9 +122,20 @@ create_pidfile(void)
 		log(L_WARNING,"Closing %s failed: errno %d (%s)\n", pidfile,
 			errno, strerror(errno));
 	}
+	mypidfile = pidfile;
 
 	return;
 }
+/*
+ * Called when the child exits
+ */
+static void
+child_exit(void)
+{
+	delete_pidfile();
+	if (pfds[1] > -1)
+		close(pfds[1]);
+}
 
 /*
  * Privilege dropper
@@ -254,6 +272,7 @@ int main (int argc, char **argv)
 	int pid;
 	int arg;
 	int port = 0, out_port = 0;
+	int status=-1;
 
 	/* Default: daemon mode, no other options */
 	run_mode = 0;
@@ -373,11 +392,24 @@ int main (int argc, char **argv)
 	if (!(run_mode & MODE_NODAEMON)) {
 		int filedes, fdmax, tempfd;
 
+		if (pipe(pfds) < 0) {
+			fprintf(stderr, "Unable to create a pipe(2):"
+				" errno %d (%s)\n", errno, strerror(errno));
+			exit(-1);
+		}
 		if ((pid = fork ()) < 0) {
 			perror ("Could not fork");
-			exit (1);
+			exit(-1);
 		} else if (pid != 0) {
 			/* Parent. */
+			/*
+			 * Wait for status from the child 
+			 */
+			close(pfds[1]);
+			if (read(pfds[0], &status, sizeof(status)) < 1)
+				exit(-1); /* the child died */
+			if (status != 0)
+				exit(-1); /* the child failed */
 			exit (0);
 		}
 		/* Child.	*/
@@ -390,13 +422,16 @@ int main (int argc, char **argv)
 		close(2); dup2(tempfd, 2);
 		fdmax = sysconf (_SC_OPEN_MAX);
 		for (filedes = 3; filedes < fdmax; filedes++) {
-			close (filedes);
+			if (filedes != pfds[1]) 
+				close (filedes);
 		}
+		atexit(child_exit);
 	}
 
 	log_init (name_p, version_p);
 	create_pidfile();
-	atexit(delete_pidfile);
+	if (run_mode & MODE_NODAEMON)
+		atexit(delete_pidfile);
 
 	/* Child. */
 	signal (SIGHUP, killer);
@@ -432,6 +467,15 @@ int main (int argc, char **argv)
 	if (access(".", R_OK|W_OK|X_OK) != 0)
 		die("Cannot access current directory after dropping privs: access()\n");
 
+	/* Tell the parent everthing is ok... */
+	status=0;
+	if (write(pfds[1], &status, sizeof(status)) < 0) {
+		log(L_WARNING,"Writting to pipe[1] failed: errno %d (%s)\n",
+		errno, strerror(errno));
+	}
+	close(pfds[1]);
+	pfds[1] = -1;
+
 	for (;;) {
 		if (!(run_mode & MODE_NOTIFY_ONLY)) {
 			/* Do not do pmap_unset() when running in notify mode.