The branch main has been updated by mjg:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=287451fd019299b138bab2ee99cdf0f3be495439

commit 287451fd019299b138bab2ee99cdf0f3be495439
Author:     Mateusz Guzik <[email protected]>
AuthorDate: 2022-03-11 11:01:50 +0000
Commit:     Mateusz Guzik <[email protected]>
CommitDate: 2022-04-09 15:59:43 +0000

    pidfile: add pidfile_signal
    
    Differential Revision:  https://reviews.freebsd.org/D34681
---
 lib/libutil/libutil.h |  1 +
 lib/libutil/pidfile.c | 76 +++++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 62 insertions(+), 15 deletions(-)

diff --git a/lib/libutil/libutil.h b/lib/libutil/libutil.h
index 17c44de0fce7..1ca22ce40e95 100644
--- a/lib/libutil/libutil.h
+++ b/lib/libutil/libutil.h
@@ -122,6 +122,7 @@ int openpty(int *_amaster, int *_aslave, char *_name,
            struct termios *_termp, struct winsize *_winp);
 int    pidfile_close(struct pidfh *_pfh);
 int    pidfile_fileno(const struct pidfh *_pfh);
+int    pidfile_signal(const char *pathp, int sig, pid_t *pidptr);
 struct pidfh *
        pidfile_open(const char *_path, mode_t _mode, pid_t *_pidptr);
 int    pidfile_remove(struct pidfh *_pfh);
diff --git a/lib/libutil/pidfile.c b/lib/libutil/pidfile.c
index eaa9379267db..33274849f06f 100644
--- a/lib/libutil/pidfile.c
+++ b/lib/libutil/pidfile.c
@@ -30,6 +30,7 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
+#include <sys/types.h>
 #include <sys/capsicum.h>
 #include <sys/file.h>
 #include <sys/stat.h>
@@ -39,6 +40,7 @@ __FBSDID("$FreeBSD$");
 #include <fcntl.h>
 #include <libgen.h>
 #include <libutil.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -74,7 +76,7 @@ pidfile_verify(const struct pidfh *pfh)
 }
 
 static int
-pidfile_read(int dirfd, const char *filename, pid_t *pidptr)
+pidfile_read_impl(int dirfd, const char *filename, pid_t *pidptr)
 {
        char buf[16], *endptr;
        int error, fd, i;
@@ -99,14 +101,33 @@ pidfile_read(int dirfd, const char *filename, pid_t 
*pidptr)
        return (0);
 }
 
+static int
+pidfile_read(int dirfd, const char *filename, pid_t *pidptr)
+{
+       struct timespec rqtp;
+       int count;
+
+       count = 20;
+       rqtp.tv_sec = 0;
+       rqtp.tv_nsec = 5000000;
+       for (;;) {
+               errno = pidfile_read_impl(dirfd, filename, pidptr);
+               if (errno != EAGAIN || --count == 0)
+                       break;
+               nanosleep(&rqtp, 0);
+       }
+       if (errno == EAGAIN)
+               *pidptr = -1;
+       return (errno);
+}
+
 struct pidfh *
 pidfile_open(const char *pathp, mode_t mode, pid_t *pidptr)
 {
        char path[MAXPATHLEN];
        struct pidfh *pfh;
        struct stat sb;
-       int error, fd, dirfd, dirlen, filenamelen, count;
-       struct timespec rqtp;
+       int error, fd, dirfd, dirlen, filenamelen;
        cap_rights_t caprights;
 
        pfh = malloc(sizeof(*pfh));
@@ -159,18 +180,8 @@ pidfile_open(const char *pathp, mode_t mode, pid_t *pidptr)
                        if (pidptr == NULL) {
                                errno = EEXIST;
                        } else {
-                               count = 20;
-                               rqtp.tv_sec = 0;
-                               rqtp.tv_nsec = 5000000;
-                               for (;;) {
-                                       errno = pidfile_read(dirfd,
-                                           pfh->pf_filename, pidptr);
-                                       if (errno != EAGAIN || --count == 0)
-                                               break;
-                                       nanosleep(&rqtp, 0);
-                               }
-                               if (errno == EAGAIN)
-                                       *pidptr = -1;
+                               errno = pidfile_read(dirfd,
+                                   pfh->pf_filename, pidptr);
                                if (errno == 0 || errno == EAGAIN)
                                        errno = EEXIST;
                        }
@@ -330,3 +341,38 @@ pidfile_fileno(const struct pidfh *pfh)
        }
        return (pfh->pf_fd);
 }
+
+int
+pidfile_signal(const char *pathp, int sig, pid_t *pidptr)
+{
+       pid_t pid;
+       int fd;
+
+       fd = flopenat(AT_FDCWD, pathp,
+           O_RDONLY | O_CLOEXEC | O_NONBLOCK);
+       if (fd >= 0) {
+               /*
+                * The file exists but is not locked,
+                * so the daemon is dead. Nothing to do.
+                */
+               close(fd);
+               errno = ENOENT;
+               return (errno);
+       }
+       if (errno != EWOULDBLOCK) {
+               return (errno);
+       }
+       errno = pidfile_read(AT_FDCWD, pathp, &pid);
+       if (errno != 0)
+               return (errno);
+       /*
+        * Refuse to send broadcast or group signals, this has
+        * happened due to the bugs in pidfile(3).
+        */
+       if (pid <= 0)
+               return (EDOM);
+       kill(pid, sig);
+       if (pidptr != NULL)
+               *pidptr = pid;
+       return (errno);
+}

Reply via email to