Skip to content

Commit

Permalink
all: Ensure pid file exists when respawning child process
Browse files Browse the repository at this point in the history
If a child process is respawned, the old pidfile may or may not still
exist. If it doesn't exist, we need to recreate it. If it still exists
we need to reset our file offset and truncate the file before
re-wrighting it.
  • Loading branch information
pqarmitage committed Aug 10, 2024
1 parent da0448a commit 7cb09b2
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 14 deletions.
3 changes: 3 additions & 0 deletions keepalived/core/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ const char *snmp_socket; /* Socket to use for SNMP agent */
#endif
static const char *syslog_ident; /* syslog ident if not default */
bool use_pid_dir; /* Put pid files in /run/keepalived or @localstatedir@/run/keepalived */
bool children_started; /* Set once children have been run first time */

unsigned os_major; /* Kernel version */
unsigned os_minor;
Expand Down Expand Up @@ -560,6 +561,8 @@ start_keepalived(__attribute__((unused)) thread_ref_t thread)
pidfile_rm(&bfd_pidfile);
#endif

children_started = true;

#ifndef _ONE_PROCESS_DEBUG_
/* Do we have a reload file to monitor */
if (global_data->reload_time_file)
Expand Down
65 changes: 52 additions & 13 deletions keepalived/core/pidfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,18 +151,6 @@ close_other_pidfiles(void)
#endif
}

/* Create the running daemon pidfile */
bool
pidfile_write(const pidfile_t *pidf)
{
if (pidf->fd == -1)
return false;

dprintf(pidf->fd, "%d\n", getpid());

return true;
}

/* return the daemon running state */
static bool
create_pidfile(pidfile_t *pidf)
Expand Down Expand Up @@ -226,7 +214,7 @@ create_pidfile(pidfile_t *pidf)
break;
}

/* pid file is now openned, locked and 0 length */
/* pid file is now opened, locked and 0 length */
return false;
}

Expand Down Expand Up @@ -258,3 +246,54 @@ keepalived_running(unsigned long mode)
#endif
return false;
}

/* Create the running daemon pidfile */
bool
pidfile_write(pidfile_t *pidf)
{
int ret;

if (pidf->fd == -1)
return false;

if (children_started) {
struct stat statb, fstatb;

/* There could be more error handling, but that will just
* complicate the code for minimal benefit. */
if (stat(pidf->path, &statb)) {
/* pidfile no longer exists */
close(pidf->fd);
create_pidfile(pidf);
} else {
if (fstat(pidf->fd, &fstatb) ||
statb.st_dev != fstatb.st_dev ||
statb.st_ino != fstatb.st_ino) {
/* The pidfile has been deleted and recreated. Open the new one. */
close(pidf->fd);
while ((pidf->fd = open(pidf->path, O_NOFOLLOW | O_WRONLY | O_NONBLOCK)) == -1 && errno == EINTR);

if (pidf->fd == -1)
return false;
}

/* Since we have already written to the pid file,
* we need to reset the file offset and truncate the file. */
off_t offs = lseek(pidf->fd, 0, SEEK_CUR);
if (offs) {
lseek(pidf->fd, 0, SEEK_SET);
if (ftruncate(pidf->fd, 0))
log_message(LOG_INFO, "ftruncate error %d - %m", errno);
}
}
}

ret = dprintf(pidf->fd, "%d\n", getpid());

if (ret < 0)
log_message(LOG_INFO, "pidfile_write returned %d, errno %d - %m", ret, errno);
else
log_message(LOG_INFO, "pidfile_write returned %d", ret);

return true;
}
1 change: 1 addition & 0 deletions keepalived/include/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ extern bool snmp_option; /* Enable SNMP support */
extern const char *snmp_socket; /* Socket to use for SNMP agent */
#endif
extern bool use_pid_dir; /* pid files in /run/keepalived */
extern bool children_started; /* Set once children have been run first time */
extern unsigned os_major; /* Kernel version */
extern unsigned os_minor;
extern unsigned os_release;
Expand Down
2 changes: 1 addition & 1 deletion keepalived/include/pidfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ extern void create_pid_dir(void);
extern void remove_pid_dir(void);
extern char *make_pidfile_name(const char *, const char *, const char *);
extern void pidfile_close(pidfile_t *, bool);
extern bool pidfile_write(const pidfile_t *);
extern bool pidfile_write(pidfile_t *);
extern void pidfile_rm(pidfile_t *);
extern void close_other_pidfiles(void);
extern bool keepalived_running(unsigned long);
Expand Down

0 comments on commit 7cb09b2

Please sign in to comment.