The function will attempt to read a pid from @path, and store it in @pid. The @pid will only be set, however, if @path is locked by virFileLock() at byte 0 and the pid in @path is running. Signed-off-by: Vasiliy Ulyanov <vulyanov@xxxxxxx> --- src/libvirt_private.syms | 1 + src/util/virpidfile.c | 34 ++++++++++++++++++++++++++++++++++ src/util/virpidfile.h | 2 ++ 3 files changed, 37 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 9bc3d9530b..447ba9d82b 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -3070,6 +3070,7 @@ virPidFileRead; virPidFileReadIfAlive; virPidFileReadPath; virPidFileReadPathIfAlive; +virPidFileReadPathIfLocked; virPidFileRelease; virPidFileReleasePath; virPidFileWrite; diff --git a/src/util/virpidfile.c b/src/util/virpidfile.c index 7069f8343d..b8bb455e5e 100644 --- a/src/util/virpidfile.c +++ b/src/util/virpidfile.c @@ -302,6 +302,40 @@ int virPidFileReadIfAlive(const char *dir, return 0; } +/** + * virPidFileReadPathIfLocked: + * @path: path to pidfile + * @pid: variable to return pid in + * + * This will attempt to read a pid from @path, and store it + * in @pid. The @pid will only be set, however, if the + * pid in @path is running, and @path is locked by virFileLock() + * at byte 0. This adds protection against returning a stale pid. + * + * Returns -1 upon error, or zero on successful + * reading of the pidfile. If @path is not locked + * or if the PID was not still alive, zero will + * be returned, but @pid will be set to -1. + */ +int virPidFileReadPathIfLocked(const char *path, pid_t *pid) +{ + VIR_AUTOCLOSE fd = -1; + + if ((fd = open(path, O_RDWR)) < 0) + return -1; + + if (virFileLock(fd, false, 0, 1, false) >= 0) { + /* The file isn't locked. PID is stale. */ + *pid = -1; + return 0; + } + + if (virPidFileReadPathIfAlive(path, pid, NULL) < 0) + return -1; + + return 0; +} + int virPidFileDeletePath(const char *pidfile) { diff --git a/src/util/virpidfile.h b/src/util/virpidfile.h index fd8013c41e..e84542f298 100644 --- a/src/util/virpidfile.h +++ b/src/util/virpidfile.h @@ -48,6 +48,8 @@ int virPidFileReadIfAlive(const char *dir, const char *name, pid_t *pid, const char *binpath) G_GNUC_WARN_UNUSED_RESULT; +int virPidFileReadPathIfLocked(const char *path, + pid_t *pid) G_GNUC_WARN_UNUSED_RESULT; int virPidFileDeletePath(const char *path); int virPidFileDelete(const char *dir, -- 2.34.1