X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/f1c5e5fde4f706bb40af755572c0cad49ca81729..86c5ebc87:/sbr/lock_file.c?ds=sidebyside diff --git a/sbr/lock_file.c b/sbr/lock_file.c index 0e83ac82..9fbcbd78 100644 --- a/sbr/lock_file.c +++ b/sbr/lock_file.c @@ -48,7 +48,7 @@ struct lockinfo { /* * Number of tries to retry locking */ -#define LOCK_RETRIES 5 +#define LOCK_RETRIES 60 /* * Amount of time to wait before @@ -85,20 +85,20 @@ static enum locktype datalocktype, spoollocktype; /* top of list containing all open locks */ static struct lock *l_top = NULL; -static int lkopen(const char *, int, mode_t, enum locktype); +static int lkopen(const char *, int, mode_t, enum locktype, int *); static int str2accbits(const char *); -static int lkopen_fcntl (const char *, int, mode_t); +static int lkopen_fcntl (const char *, int, mode_t, int *); #ifdef HAVE_LOCKF -static int lkopen_lockf (const char *, int, mode_t); +static int lkopen_lockf (const char *, int, mode_t, int *); #endif /* HAVE_LOCKF */ #ifdef HAVE_FLOCK -static int lkopen_flock (const char *, int, mode_t); +static int lkopen_flock (const char *, int, mode_t, int *); #endif /* HAVE_FLOCK */ static enum locktype init_locktype(const char *); -static int lkopen_dot (const char *, int, mode_t); +static int lkopen_dot (const char *, int, mode_t, int *); static void lkclose_dot (int, const char *); static void lockname (const char *, struct lockinfo *, int); static void timerON (char *, int); @@ -115,7 +115,7 @@ static int lockit (struct lockinfo *); */ int -lkopendata(const char *file, int access, mode_t mode) +lkopendata(const char *file, int access, mode_t mode, int *failed_to_lock) { if (! datalockinit) { char *cp = context_find("datalocking"); @@ -130,7 +130,7 @@ lkopendata(const char *file, int access, mode_t mode) datalockinit = 1; } - return lkopen(file, access, mode, datalocktype); + return lkopen(file, access, mode, datalocktype, failed_to_lock); } @@ -138,7 +138,7 @@ lkopendata(const char *file, int access, mode_t mode) * Locking using the spool locking algorithm */ -int lkopenspool(const char *file, int access, mode_t mode) +int lkopenspool(const char *file, int access, mode_t mode, int *failed_to_lock) { if (! spoollockinit) { spoollocktype = init_locktype(spoollocking); @@ -146,7 +146,7 @@ int lkopenspool(const char *file, int access, mode_t mode) spoollockinit = 1; } - return lkopen(file, access, mode, spoollocktype); + return lkopen(file, access, mode, spoollocktype, failed_to_lock); } @@ -155,7 +155,7 @@ int lkopenspool(const char *file, int access, mode_t mode) */ FILE * -lkfopendata(const char *file, const char *mode) +lkfopendata(const char *file, const char *mode, int *failed_to_lock) { FILE *fp; int oflags = str2accbits(mode); @@ -166,7 +166,7 @@ lkfopendata(const char *file, const char *mode) return NULL; } - if ((fd = lkopendata(file, oflags, 0666)) == -1) + if ((fd = lkopendata(file, oflags, 0666, failed_to_lock)) == -1) return NULL; if ((fp = fdopen (fd, mode)) == NULL) { @@ -182,6 +182,7 @@ lkfopenspool(const char *file, const char *mode) { FILE *fp; int oflags = str2accbits(mode); + int failed_to_lock = 0; int fd; if (oflags == -1) { @@ -189,7 +190,7 @@ lkfopenspool(const char *file, const char *mode) return NULL; } - if ((fd = lkopenspool(file, oflags, 0666)) == -1) + if ((fd = lkopenspool(file, oflags, 0666, &failed_to_lock)) == -1) return NULL; if ((fp = fdopen (fd, mode)) == NULL) { @@ -275,20 +276,19 @@ str2accbits(const char *mode) { if (strcmp (mode, "r") == 0) return O_RDONLY; - else if (strcmp (mode, "r+") == 0) + if (strcmp (mode, "r+") == 0) return O_RDWR; - else if (strcmp (mode, "w") == 0) + if (strcmp (mode, "w") == 0) return O_WRONLY | O_CREAT | O_TRUNC; - else if (strcmp (mode, "w+") == 0) + if (strcmp (mode, "w+") == 0) return O_RDWR | O_CREAT | O_TRUNC; - else if (strcmp (mode, "a") == 0) + if (strcmp (mode, "a") == 0) return O_WRONLY | O_CREAT | O_APPEND; - else if (strcmp (mode, "a+") == 0) + if (strcmp (mode, "a+") == 0) return O_RDWR | O_CREAT | O_APPEND; - else { - errno = EINVAL; - return -1; - } + + errno = EINVAL; + return -1; } /* @@ -296,24 +296,25 @@ str2accbits(const char *mode) */ static int -lkopen (const char *file, int access, mode_t mode, enum locktype ltype) +lkopen (const char *file, int access, mode_t mode, enum locktype ltype, + int *failed_to_lock) { switch (ltype) { case FCNTL_LOCKING: - return lkopen_fcntl(file, access, mode); + return lkopen_fcntl(file, access, mode, failed_to_lock); case DOT_LOCKING: - return lkopen_dot(file, access, mode); + return lkopen_dot(file, access, mode, failed_to_lock); #ifdef HAVE_FLOCK case FLOCK_LOCKING: - return lkopen_flock(file, access, mode); + return lkopen_flock(file, access, mode, failed_to_lock); #endif /* HAVE_FLOCK */ #ifdef HAVE_LOCKF case LOCKF_LOCKING: - return lkopen_lockf(file, access, mode); + return lkopen_lockf(file, access, mode, failed_to_lock); #endif /* HAVE_FLOCK */ default: @@ -335,7 +336,7 @@ lkclose_dot (int fd, const char *file) lockname (file, &lkinfo, 0); /* get name of lock file */ #if !defined(HAVE_LIBLOCKFILE) - unlink (lkinfo.curlock); /* remove lock file */ + (void) m_unlink (lkinfo.curlock); /* remove lock file */ #else lockfile_remove(lkinfo.curlock); #endif /* HAVE_LIBLOCKFILE */ @@ -348,7 +349,7 @@ lkclose_dot (int fd, const char *file) */ static int -lkopen_fcntl(const char *file, int access, mode_t mode) +lkopen_fcntl(const char *file, int access, mode_t mode, int *failed_to_lock) { int fd, i, saved_errno; struct flock flk; @@ -375,17 +376,19 @@ lkopen_fcntl(const char *file, int access, mode_t mode) sleep(1); } + *failed_to_lock = 1; errno = saved_errno; return -1; } +#ifdef HAVE_FLOCK /* * Open and lock a file, using flock locking */ static int -lkopen_flock(const char *file, int access, mode_t mode) +lkopen_flock(const char *file, int access, mode_t mode, int *failed_to_lock) { int fd, i, saved_errno, locktype; @@ -409,17 +412,18 @@ lkopen_flock(const char *file, int access, mode_t mode) sleep(1); } + *failed_to_lock = 1; errno = saved_errno; return -1; } - +#endif /* HAVE_FLOCK */ /* * Open and lock a file, using lockf locking */ static int -lkopen_lockf(const char *file, int access, mode_t mode) +lkopen_lockf(const char *file, int access, mode_t mode, int *failed_to_lock) { int fd, i, saved_errno, saved_access; @@ -461,6 +465,7 @@ lkopen_lockf(const char *file, int access, mode_t mode) sleep(1); } + *failed_to_lock = 1; errno = saved_errno; return -1; } @@ -471,7 +476,7 @@ lkopen_lockf(const char *file, int access, mode_t mode) */ static int -lkopen_dot (const char *file, int access, mode_t mode) +lkopen_dot (const char *file, int access, mode_t mode, int *failed_to_lock) { int fd; struct lockinfo lkinfo; @@ -489,46 +494,50 @@ lkopen_dot (const char *file, int access, mode_t mode) #if !defined(HAVE_LIBLOCKFILE) { int i; - for (i = 0;;) { + for (i = 0; i < LOCK_RETRIES; ++i) { + struct stat st; + /* attempt to create lock file */ if (lockit (&lkinfo) == 0) { /* if successful, turn on timer and return */ timerON (lkinfo.curlock, fd); return fd; - } else { - /* - * Abort locking, if we fail to lock after 5 attempts - * and are never able to stat the lock file. - */ - struct stat st; - if (stat (lkinfo.curlock, &st) == -1) { - if (i++ > 5) - return -1; - sleep (5); - } else { - time_t curtime; - i = 0; - time (&curtime); - - /* check for stale lockfile, else sleep */ - if (curtime > st.st_ctime + RSECS) - unlink (lkinfo.curlock); - else - sleep (5); - } - lockname (file, &lkinfo, 1); } + + /* + * Abort locking, if we fail to lock after 5 attempts + * and are never able to stat the lock file. Or, if + * we can stat the lockfile but exceed LOCK_RETRIES + * seconds waiting for it (by falling out of the loop). + */ + if (stat (lkinfo.curlock, &st) == -1) { + if (i++ > 5) break; + sleep (1); + } else { + time_t curtime; + time (&curtime); + + /* check for stale lockfile, else sleep */ + if (curtime > st.st_ctime + RSECS) + (void) m_unlink (lkinfo.curlock); + else + sleep (1); + } + lockname (file, &lkinfo, 1); } + + *failed_to_lock = 1; + return -1; } #else if (lockfile_create(lkinfo.curlock, 5, 0) == L_SUCCESS) { timerON(lkinfo.curlock, fd); return fd; } - else { - close(fd); - return -1; - } + + close(fd); + *failed_to_lock = 1; + return -1; #endif /* HAVE_LIBLOCKFILE */ } @@ -542,17 +551,18 @@ static int lockit (struct lockinfo *li) { int fd; - char *curlock, *tmplock; + char *curlock, *tmpfile; #if 0 char buffer[128]; #endif curlock = li->curlock; - tmplock = li->tmplock; - if ((fd = mkstemp(tmplock)) == -1) + if ((tmpfile = m_mktemp(li->tmplock, &fd, NULL)) == NULL) { + advise(NULL, "unable to create temporary file in %s", li->tmplock); return -1; + } #if 0 /* write our process id into lock file */ @@ -566,8 +576,8 @@ lockit (struct lockinfo *li) * Now try to create the real lock file * by linking to the temporary file. */ - fd = link(tmplock, curlock); - unlink(tmplock); + fd = link(tmpfile, curlock); + (void) m_unlink(tmpfile); return (fd == -1 ? -1 : 0); } @@ -647,14 +657,10 @@ static void timerON (char *curlock, int fd) { struct lock *lp; - size_t len; - lp = (struct lock *) mh_xmalloc (sizeof(*lp)); - - len = strlen(curlock) + 1; + NEW(lp); + lp->l_lock = mh_xstrdup(curlock); lp->l_fd = fd; - lp->l_lock = mh_xmalloc (len); - memcpy (lp->l_lock, curlock, len); lp->l_next = l_top; if (!l_top) { @@ -662,7 +668,6 @@ timerON (char *curlock, int fd) SIGNAL (SIGALRM, alrmser); alarm (NSECS); } - l_top = lp; } @@ -741,23 +746,25 @@ init_locktype(const char *lockname) { if (strcasecmp(lockname, "fcntl") == 0) { return FCNTL_LOCKING; - } else if (strcasecmp(lockname, "lockf") == 0) { + } + if (strcasecmp(lockname, "lockf") == 0) { #ifdef HAVE_LOCKF return LOCKF_LOCKING; #else /* ! HAVE_LOCKF */ adios(NULL, "lockf not supported on this system"); #endif /* HAVE_LOCKF */ - } else if (strcasecmp(lockname, "flock") == 0) { + } + if (strcasecmp(lockname, "flock") == 0) { #ifdef HAVE_FLOCK return FLOCK_LOCKING; #else /* ! HAVE_FLOCK */ adios(NULL, "flock not supported on this system"); #endif /* HAVE_FLOCK */ - } else if (strcasecmp(lockname, "dot") == 0) { + } + if (strcasecmp(lockname, "dot") == 0) { return DOT_LOCKING; - } else { - adios(NULL, "Unknown lock type: \"%s\"", lockname); - /* NOTREACHED */ - return 0; } + adios(NULL, "Unknown lock type: \"%s\"", lockname); + /* NOTREACHED */ + return 0; }