nfs-utils - 3 of 6 -statd - Ensure child process is running for before the parent exits
Subsystems (2)
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_Pshort 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.