SHA256
1
0
forked from pool/tcsh
tcsh/tcsh-6.22.02-local-dotlock.dif

204 lines
4.5 KiB
Plaintext
Raw Permalink Normal View History

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 <unistd.h>
+#include <fcntl.h>
+
#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
@@ -1230,9 +1230,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. */
@@ -1311,11 +1313,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);