Avoid left over dot lock file after reboot --- dotlock.c | 124 ++++++++++++++------------------------------------------------ dotlock.h | 2 - sh.hist.c | 11 +++-- 3 files changed, 36 insertions(+), 101 deletions(-) --- dotlock.c +++ dotlock.c 2020-02-19 12:07:22.228255145 +0000 @@ -29,7 +29,9 @@ #ifndef O_SYNC #define O_SYNC 0 #endif - +#include +#include + #include "dotlock.h" static int create_exclusive(const char *); @@ -46,77 +48,26 @@ static int create_exclusive(const char * static int create_exclusive(const char *fname) { - char path[MAXPATHLEN], hostname[MAXHOSTNAMELEN + 1]; - const char *ptr; - struct timeval tv; - pid_t pid; - size_t ntries, cookie; - int fd, serrno; - struct stat st; - - (void)gettimeofday(&tv, NULL); - (void)gethostname(hostname, sizeof(hostname)); - hostname[sizeof(hostname) - 1] = '\0'; - pid = getpid(); - - cookie = pid ^ tv.tv_usec; - - /* - * We generate a semi-unique filename, from hostname.(pid ^ usec) - */ - if ((ptr = strrchr(fname, '/')) == NULL) - ptr = fname; - else - ptr++; - - (void)snprintf(path, sizeof(path), "%.*s.%s.%lx", - (int)(ptr - fname), fname, hostname, (u_long)cookie); - - /* - * We try to create the unique filename. - */ - for (ntries = 0; ntries < 5; ntries++) { - fd = open(path, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_SYNC, 0); - if (fd != -1) { - (void)close(fd); + struct flock fl = { F_WRLCK, SEEK_SET, 0, 0, getpid()}; + int fd, retval; + + fd = open(fname, O_WRONLY|O_CREAT|O_SYNC, S_IWUSR); + if (fd < 0) + return -1; + do { + int ret; + retval = fcntl(fd, F_SETLKW, &fl); + if (retval < 0) { + if (errno == EINTR) + continue; + close(fd); + fd = -1; break; } - else if (errno == EEXIST) - continue; - else - return -1; - } - - /* - * We link the path to the name - */ - if (link(path, fname) == -1) - goto bad; - - /* - * Note that we stat our own exclusively created name, not the - * destination, since the destination can be affected by others. - */ - if (stat(path, &st) == -1) - goto bad; - - (void)unlink(path); - - /* - * If the number of links was two (one for the unique file and one - * for the lock), we've won the race - */ - if (st.st_nlink != 2) { - errno = EEXIST; - return -1; - } - return 0; + } while (retval < 0); -bad: - serrno = errno; - (void)unlink(path); - errno = serrno; - return -1; + (void)unlink(fname); + return fd; } /* @@ -143,37 +94,18 @@ dot_lock(const char *fname, int pollinte (void)snprintf(path, sizeof(path), "%s.lock", fname); retval = -1; - for (;;) { - handle_pending_signals(); - (void)sigprocmask(SIG_BLOCK, &nset, &oset); - if (create_exclusive(path) != -1) { - (void)sigprocmask(SIG_SETMASK, &oset, NULL); - retval = 0; - break; - } - else - (void)sigprocmask(SIG_SETMASK, &oset, NULL); - - if (errno != EEXIST) - break; - - if (pollinterval) { - if (pollinterval == -1) { - errno = EEXIST; - break; - } - (void)usleep((unsigned int)pollinterval * 1000); - } - } + handle_pending_signals(); + (void)sigprocmask(SIG_BLOCK, &nset, &oset); + retval = create_exclusive(path); + (void)sigprocmask(SIG_SETMASK, &oset, NULL); handle_pending_signals(); return retval; } void -dot_unlock(const char *fname) +dot_unlock(const int fd) { - char path[MAXPATHLEN]; - - (void)snprintf(path, sizeof(path), "%s.lock", fname); - (void)unlink(path); + struct flock fl = { F_UNLCK, SEEK_SET, 0, 0, getpid()}; + fcntl(fd, F_SETLK, &fl); + close(fd); } --- dotlock.h +++ dotlock.h 2020-02-19 09:40:16.034422159 +0000 @@ -30,6 +30,6 @@ * pollinterval -- Interval (miliseconds) to check for lock, -1 return */ int dot_lock(const char *fname, int pollinterval); -void dot_unlock(const char *fname); +void dot_unlock(const int fd); #endif /* #ifndef _DOTLOCK_H_ */ --- sh.hist.c +++ sh.hist.c 2020-02-19 09:48:57.640589111 +0000 @@ -1219,9 +1219,11 @@ fmthist(int fmt, ptr_t ptr) } static void -dotlock_cleanup(void* lockpath) +dotlock_cleanup(void* xfdp) { - dot_unlock((char*)lockpath); + int *fdp; + fdp = xfdp; + dot_unlock(*fdp); } /* Save history before exiting the shell. */ @@ -1300,11 +1302,12 @@ rechist(Char *fname, int ref) jmp_buf_t osetexit; if (lock) { #ifndef WINNT_NATIVE + int fdlk; char *lockpath = strsave(short2str(fname)); cleanup_push(lockpath, xfree); /* Poll in 100 miliseconds interval to obtain the lock. */ - if ((dot_lock(lockpath, 100) == 0)) - cleanup_push(lockpath, dotlock_cleanup); + if ((fdlk = dot_lock(lockpath, 100)) != -1) + cleanup_push(&fdlk, dotlock_cleanup); #endif } getexit(osetexit);