From f2b11dbef8bb638ff57baf3225864ed732164fe7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 21 Nov 2004 13:18:56 +0000 Subject: * PID and lock file fixes git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@299 fefdeb5f-60dc-0310-8127-8f9354f1896f --- polyp/pid.c | 97 ++++++++++++++++++++++++++++++++++++++++++------------------ polyp/util.c | 46 +++++++++++++++++++++------- 2 files changed, 104 insertions(+), 39 deletions(-) (limited to 'polyp') diff --git a/polyp/pid.c b/polyp/pid.c index 37a76984..232de216 100644 --- a/polyp/pid.c +++ b/polyp/pid.c @@ -65,9 +65,62 @@ static pid_t read_pid(const char *fn, int fd) { return (pid_t) pid; } +static int open_pid_file(const char *fn, int mode) { + int fd = -1; + int lock = -1; + + for (;;) { + struct stat st; + + pa_make_secure_parent_dir(fn); + + if ((fd = open(fn, mode, S_IRUSR|S_IWUSR)) < 0) { + if (mode != O_RDONLY || errno != ENOENT) + pa_log(__FILE__": WARNING: failed to open PID file '%s': %s\n", fn, strerror(errno)); + goto fail; + } + + /* Try to lock the file. If that fails, go without */ + if (pa_lock_fd(fd, 1) < 0) + goto fail; + + if (fstat(fd, &st) < 0) { + pa_log(__FILE__": Failed to fstat() PID file '%s': %s\n", fn, strerror(errno)); + goto fail; + } + + /* Does the file still exist in the file system? When ye, w're done, otherwise restart */ + if (st.st_nlink >= 1) + break; + + if (pa_lock_fd(fd, 0) < 0) + goto fail; + + if (close(fd) < 0) { + pa_log(__FILE__": Failed to close file '%s': %s\n", fn, strerror(errno)); + goto fail; + } + + fd = -1; + } + + return fd; + +fail: + + if (fd < 0) { + if (lock >= 0) + pa_lock_fd(fd, 0); + + close(fd); + } + + return -1; +} + /* Create a new PID file for the current process. */ int pa_pid_file_create(void) { - int fd = -1, lock = -1; + int fd = -1; int ret = -1; char fn[PATH_MAX]; char t[20]; @@ -75,13 +128,9 @@ int pa_pid_file_create(void) { size_t l; pa_runtime_path("pid", fn, sizeof(fn)); - if ((fd = open(fn, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0) { - pa_log(__FILE__": WARNING: failed to open PID file '%s': %s\n", fn, strerror(errno)); - goto fail; - } - /* Try to lock the file. If that fails, go without */ - lock = pa_lock_fd(fd, 1); + if ((fd = open_pid_file(fn, O_CREAT|O_RDWR)) < 0) + goto fail; if ((pid = read_pid(fn, fd)) == (pid_t) -1) pa_log(__FILE__": corrupt PID file, overwriting.\n"); @@ -112,9 +161,7 @@ int pa_pid_file_create(void) { fail: if (fd >= 0) { - if (lock >= 0) - pa_lock_fd(fd, 0); - + pa_lock_fd(fd, 0); close(fd); } @@ -123,19 +170,18 @@ fail: /* Remove the PID file, if it is ours */ int pa_pid_file_remove(void) { - int fd = -1, lock = -1; + int fd = -1; char fn[PATH_MAX]; int ret = -1; pid_t pid; pa_runtime_path("pid", fn, sizeof(fn)); - if ((fd = open(fn, O_RDWR)) < 0) { + + if ((fd = open_pid_file(fn, O_RDWR)) < 0) { pa_log(__FILE__": WARNING: failed to open PID file '%s': %s\n", fn, strerror(errno)); goto fail; } - lock = pa_lock_fd(fd, 1); - if ((pid = read_pid(fn, fd)) == (pid_t) -1) goto fail; @@ -159,9 +205,7 @@ int pa_pid_file_remove(void) { fail: if (fd >= 0) { - if (lock >= 0) - pa_lock_fd(fd, 0); - + pa_lock_fd(fd, 0); close(fd); } @@ -180,31 +224,28 @@ int pa_pid_file_check_running(pid_t *pid) { * otherwise. If successful *pid contains the PID of the daemon * process. */ int pa_pid_file_kill(int sig, pid_t *pid) { - int fd = -1, lock = -1; + int fd = -1; char fn[PATH_MAX]; int ret = -1; pid_t _pid; if (!pid) pid = &_pid; - + pa_runtime_path("pid", fn, sizeof(fn)); - if ((fd = open(fn, O_RDONLY)) < 0) + + if ((fd = open_pid_file(fn, O_RDONLY)) < 0) goto fail; - - lock = pa_lock_fd(fd, 1); - + if ((*pid = read_pid(fn, fd)) == (pid_t) -1) goto fail; - + ret = kill(*pid, sig); fail: - + if (fd >= 0) { - if (lock >= 0) - pa_lock_fd(fd, 0); - + pa_lock_fd(fd, 0); close(fd); } diff --git a/polyp/util.c b/polyp/util.c index b01b80a1..87beafb3 100644 --- a/polyp/util.c +++ b/polyp/util.c @@ -646,26 +646,50 @@ char* pa_strip_nl(char *s) { /* Create a temporary lock file and lock it. */ int pa_lock_lockfile(const char *fn) { - int fd; + int fd = -1; assert(fn); - if ((fd = open(fn, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0) { - pa_log(__FILE__": failed to create lock file '%s': %s\n", fn, strerror(errno)); - goto fail; - } + for (;;) { + struct stat st; + + if ((fd = open(fn, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0) { + pa_log(__FILE__": failed to create lock file '%s': %s\n", fn, strerror(errno)); + goto fail; + } + + if (pa_lock_fd(fd, 1) < 0) { + pa_log(__FILE__": failed to lock file '%s'.\n", fn); + goto fail; + } + + if (fstat(fd, &st) < 0) { + pa_log(__FILE__": failed to fstat() file '%s'.\n", fn); + goto fail; + } - if (pa_lock_fd(fd, 1) < 0) - pa_log(__FILE__": failed to lock file '%s'.\n", fn); - goto fail; + /* Check wheter the file has been removed meanwhile. When yes, restart this loop, otherwise, we're done */ + if (st.st_nlink >= 1) + break; + + if (pa_lock_fd(fd, 0) < 0) { + pa_log(__FILE__": failed to unlock file '%s'.\n", fn); + goto fail; + } + + if (close(fd) < 0) { + pa_log(__FILE__": failed to close file '%s'.\n", fn); + goto fail; + } + fd = -1; + } + return fd; fail: - if (fd >= 0) { - unlink(fn); + if (fd >= 0) close(fd); - } return -1; } -- cgit