Skip to content

Commit 8c7691a

Browse files
committed
Improve pidfile management
We used to create an empty pidfile, and write the pid only after starting the interface. Having pidfile without a pid does not make sense, as other processes cannot use the pid to terminate the process. For example if starting the interface is blocking for long time due to a bug, we are left with unhelpful pid file. To keep the main flow more clear, add a helper to create and remove the pid file. The helpers check all errors and log better log messages using ERRORF instead of ERRORN, including the pidfile path. Previously if we got a short write to the pidfile, we log bogus error since errno is set only when write return negative return value. Rename pid_fd to pidfile_fd to avoid confusion with Linux's pidfd https://man7.org/linux/man-pages/man2/pidfd_open.2.html. Signed-off-by: Nir Soffer <nirsof@gmail.com>
1 parent 2b032b6 commit 8c7691a

File tree

1 file changed

+42
-18
lines changed

1 file changed

+42
-18
lines changed

main.c

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,40 @@ static int socket_bindlisten(const char *socket_path,
364364
return -1;
365365
}
366366

367+
static void remove_pidfile(const char *pidfile)
368+
{
369+
if (unlink(pidfile) != 0) {
370+
ERRORF("Failed to remove pidfile: \"%s\": %s", pidfile, strerror(errno));
371+
}
372+
}
373+
374+
static int create_pidfile(const char *pidfile)
375+
{
376+
int flags = O_WRONLY | O_CREAT | O_EXLOCK | O_TRUNC | O_NONBLOCK;
377+
int fd = open(pidfile, flags, 0644);
378+
if (fd == -1) {
379+
ERRORF("Failed to open pidfile: \"%s\": %s", pidfile, strerror(errno));
380+
return -1;
381+
}
382+
383+
char pid[20];
384+
snprintf(pid, sizeof(pid), "%u", getpid());
385+
ssize_t n = write(fd, pid, strlen(pid));
386+
if (n != (ssize_t)strlen(pid)) {
387+
if (n < 0) {
388+
ERRORF("Failed to write pidfile: \"%s\": %s", pidfile, strerror(errno));
389+
} else {
390+
// Should never happen, but if it does errno is not set.
391+
ERRORF("Short write to pidfile: \"%s\"", pidfile);
392+
}
393+
remove_pidfile(pidfile);
394+
close(fd);
395+
return -1;
396+
}
397+
398+
return fd;
399+
}
400+
367401
static void on_accept(struct state *state, int accept_fd, interface_ref iface);
368402

369403
int main(int argc, char *argv[]) {
@@ -395,15 +429,14 @@ int main(int argc, char *argv[]) {
395429
// We will receive EPIPE on the socket.
396430
signal(SIGPIPE, SIG_IGN);
397431

398-
int pid_fd = -1;
432+
int pidfile_fd = -1;
399433
if (cliopt->pidfile != NULL) {
400-
pid_fd = open(cliopt->pidfile,
401-
O_WRONLY | O_CREAT | O_EXLOCK | O_TRUNC | O_NONBLOCK, 0644);
402-
if (pid_fd == -1) {
403-
ERRORN("pidfile_open");
404-
goto done;
434+
pidfile_fd = create_pidfile(cliopt->pidfile);
435+
if (pidfile_fd == -1) {
436+
goto done; // error already logged.
405437
}
406438
}
439+
407440
DEBUGF("Opening socket \"%s\" (for UNIX group \"%s\")", cliopt->socket_path,
408441
cliopt->socket_group);
409442
listen_fd = socket_bindlisten(cliopt->socket_path, cliopt->socket_group);
@@ -428,15 +461,6 @@ int main(int argc, char *argv[]) {
428461
goto done;
429462
}
430463

431-
if (pid_fd != -1) {
432-
char pid[20];
433-
snprintf(pid, sizeof(pid), "%u", getpid());
434-
if (write(pid_fd, pid, strlen(pid)) != (ssize_t)strlen(pid)) {
435-
ERRORN("write");
436-
goto done;
437-
}
438-
}
439-
440464
while (1) {
441465
int accept_fd = accept(listen_fd, NULL, NULL);
442466
if (accept_fd < 0) {
@@ -457,9 +481,9 @@ int main(int argc, char *argv[]) {
457481
if (listen_fd != -1) {
458482
close(listen_fd);
459483
}
460-
if (pid_fd != -1) {
461-
unlink(cliopt->pidfile);
462-
close(pid_fd);
484+
if (pidfile_fd != -1) {
485+
remove_pidfile(cliopt->pidfile);
486+
close(pidfile_fd);
463487
}
464488
if (state.vms_queue != NULL)
465489
dispatch_release(state.vms_queue);

0 commit comments

Comments
 (0)