From 6a6af7fec8f0f93218b790618a3e095844b77b9b Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 21 Feb 2009 22:10:52 +0100 Subject: fixed severe bug about removing the pidfile in the wrong place (not propagating the state of the pidfile object from parent to daemon!) --- src/daemon/daemon.c | 21 ++++++++++++--------- src/daemon/pidfile.c | 30 +++++++++++++++++++----------- 2 files changed, 31 insertions(+), 20 deletions(-) (limited to 'src/daemon') diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c index a6fe63a..abcf47c 100644 --- a/src/daemon/daemon.c +++ b/src/daemon/daemon.c @@ -370,7 +370,7 @@ wolf_error_t wolf_daemon_start( wolf_daemon_p d ) { */ WOLF_LOG( WOLF_LOG_DEBUG, "Parent after first fork: child is %d", pid ); d->state = TERMINATE_EXIT_CODE; - return WOLF_ERR_PROGRAMMING; /* intensional error code here, so we get into wolf_daemon_exit! */ + return( d->error = WOLF_ERR_PROGRAMMING ); /* intensional error code here, so we get into wolf_daemon_exit! */ } /* second pipe communicates from the daemon back to its parent @@ -428,7 +428,7 @@ wolf_error_t wolf_daemon_start( wolf_daemon_p d ) { (void)install_signal_handlers_parent( ); WOLF_LOG( WOLF_LOG_DEBUG, "Parent after second fork: child (and daemon) is %d", pid ); d->state = TERMINATE_PARENT; - return WOLF_ERR_PROGRAMMING; /* intensional error code here, so we get into wolf_daemon_exit! */ + return( d->error = WOLF_ERR_PROGRAMMING ); /* intensional error code here, so we get into wolf_daemon_exit! */ } /* Now install signal handlers */ @@ -579,7 +579,6 @@ wolf_error_t wolf_daemon_start( wolf_daemon_p d ) { NORETURN void wolf_daemon_exit( wolf_daemon_p d ) { int exit_code; - int pid_file_fd; WOLF_LOG( WOLF_LOG_DEBUG, "daemon_exit called int state %d (error %d)", d->state, d->error ); @@ -612,18 +611,18 @@ NORETURN void wolf_daemon_exit( wolf_daemon_p d ) { /* wait for termination signal */ WOLF_LOG( WOLF_LOG_DEBUG, "Waiting on parent pipe for termination signal" ); - atomar_read( daemon_parent_pipe[0], &pid_file_fd, sizeof( int ) ); - WOLF_LOG( WOLF_LOG_DEBUG, "Parent got termination (pidfile fd: %d).. cleaning up now (PID: %lu)", - pid_file_fd, getpid( ) ); + atomar_read( daemon_parent_pipe[0], &d->pidfile.locked, sizeof( bool ) ); + atomar_read( daemon_parent_pipe[0], &d->pidfile.running, sizeof( bool ) ); + atomar_read( daemon_parent_pipe[0], &d->pidfile.fd, sizeof( int ) ); + WOLF_LOG( WOLF_LOG_DEBUG, "Parent got termination (pidfile lock: %d, run: %d, fd: %d).. cleaning up now (PID: %lu)", + d->pidfile.locked, d->pidfile.running, d->pidfile.fd, getpid( ) ); /* we need root permissions for that! */ - d->pidfile.fd = pid_file_fd; (void)pidfile_remove( &d->pidfile ); wolf_daemon_signals_terminate( ); - WOLF_LOG( WOLF_LOG_DEBUG, "Terminating parent of daemon pid file fd %d (PID %lu)", - pid_file_fd, getpid( ) ); + WOLF_LOG( WOLF_LOG_DEBUG, "Terminating parent of daemon (PID %lu)", getpid( ) ); /* exit code is irrelevant here.. */ exit( EXIT_SUCCESS ); @@ -635,6 +634,8 @@ NORETURN void wolf_daemon_exit( wolf_daemon_p d ) { /* This is the daemon terminating, signal the * parent that we are terminating */ + atomar_write( daemon_parent_pipe[1], &d->pidfile.locked, sizeof( bool ) ); + atomar_write( daemon_parent_pipe[1], &d->pidfile.running, sizeof( bool ) ); atomar_write( daemon_parent_pipe[1], &d->pidfile.fd, sizeof( int ) ); wolf_daemon_signals_terminate( ); @@ -659,6 +660,8 @@ NORETURN void wolf_daemon_exit( wolf_daemon_p d ) { atomar_write( exit_code_pipe[1], &exit_code, sizeof( int ) ); /* also terminate the parent of the daemon */ + atomar_write( daemon_parent_pipe[1], &d->pidfile.locked, sizeof( bool ) ); + atomar_write( daemon_parent_pipe[1], &d->pidfile.running, sizeof( bool ) ); atomar_write( daemon_parent_pipe[1], &d->pidfile.fd, sizeof( int ) ); wolf_daemon_signals_terminate( ); diff --git a/src/daemon/pidfile.c b/src/daemon/pidfile.c index aa4e3b0..839e2cf 100644 --- a/src/daemon/pidfile.c +++ b/src/daemon/pidfile.c @@ -57,11 +57,11 @@ bool is_daemon_running( struct pidfile_t *pidfile, pid_t *pid, wolf_error_t *err WOLF_LOG( WOLF_LOG_DEBUG, "No pidfile '%s' found, daemon is not running", pidfile->filename ); (void)close( pidfile->fd ); *error = WOLF_OK; - return pidfile->running; + return( pidfile->running = false ); } else { WOLF_LOG( WOLF_LOG_EMERG, "Unable to open pidfile '%s' for reading: %s", pidfile->filename, strerror( errno ) ); *error = WOLF_ERR_INTERNAL; - return pidfile->running; + return( pidfile->running = false ); } } @@ -78,11 +78,13 @@ bool is_daemon_running( struct pidfile_t *pidfile, pid_t *pid, wolf_error_t *err WOLF_LOG( WOLF_LOG_EMERG, "Unable to lock pidfile '%s': %s", pidfile->filename, strerror( errno ) ); (void)close( pidfile->fd ); *error = WOLF_ERR_INTERNAL; - pidfile->running = false; - return pidfile->running; + return( pidfile->running = false ); } } else { - pidfile->locked = false; + /* we can lock the file but it could be a relict, so we are not sure + * yet if the daemon is already running or not + */ + pidfile->locked = true; } /* try to read the pid from the file */ @@ -91,7 +93,7 @@ bool is_daemon_running( struct pidfile_t *pidfile, pid_t *pid, wolf_error_t *err WOLF_LOG( WOLF_LOG_EMERG, "Unable to read pid from pidfile '%s': %s", pidfile->filename, strerror( errno ) ); (void)close( pidfile->fd ); *error = WOLF_ERR_INTERNAL; - return pidfile->running; + return( pidfile->running = false ); } /* parse the file and see if we have a valid pid on the first line */ @@ -107,7 +109,7 @@ bool is_daemon_running( struct pidfile_t *pidfile, pid_t *pid, wolf_error_t *err WOLF_LOG( WOLF_LOG_EMERG, "pidfile '%s' contains invalid data, can't read PID from it!", pidfile->filename ); (void)close( pidfile->fd ); *error = WOLF_ERR_INTERNAL; - return pidfile->running; + return( pidfile->running = false ); } WOLF_LOG( WOLF_LOG_DEBUG, "Found PID '%lu' in pidfile", *pid ); @@ -121,12 +123,12 @@ bool is_daemon_running( struct pidfile_t *pidfile, pid_t *pid, wolf_error_t *err WOLF_LOG( WOLF_LOG_EMERG, "Found PID '%lu' in pidfile '%s', but no such process is running. Check and manually delete the pidfile!", *pid, pidfile->filename ); (void)close( pidfile->fd ); *error = WOLF_ERR_INTERNAL; - return pidfile->running; + return( pidfile->running = false ); } else { - WOLF_LOG( WOLF_LOG_EMERG, "Can't check if processor with PID '%lu' is alive: %s", *pid, strerror( errno ) ); + WOLF_LOG( WOLF_LOG_EMERG, "Can't check if proces with PID '%lu' is alive: %s", *pid, strerror( errno ) ); (void)close( pidfile->fd ); *error = WOLF_ERR_INTERNAL; - return pidfile->running; + return( pidfile->running = false ); } } WOLF_LOG( WOLF_LOG_DEBUG, "A process with PID '%lu' is already running", *pid ); @@ -136,7 +138,7 @@ bool is_daemon_running( struct pidfile_t *pidfile, pid_t *pid, wolf_error_t *err */ (void)close( pidfile->fd ); *error = WOLF_OK; - return pidfile->running; + return( pidfile->running = true ); } wolf_error_t pidfile_create( struct pidfile_t *pidfile ) { @@ -233,6 +235,12 @@ wolf_error_t pidfile_remove( struct pidfile_t *pidfile ) { WOLF_LOG( WOLF_LOG_DEBUG, "Removing pidfile '%s' (fd: %d, locked: %d, running: %d)", pidfile->filename, pidfile->fd, pidfile->locked, pidfile->running ); + /* if we know that another process is running, then we also know that we are + * not allowed to remove the pidfile + */ + if( pidfile->running ) { + return WOLF_OK; + } /* unconditionally remove the pidfile */ if( unlink( pidfile->filename ) < 0 ) { -- cgit v1.2.3-54-g00ecf