# include <sys/time.h>
#endif
#include <time.h>
-#include <errno.h>
#include <fcntl.h>
#ifdef HAVE_FLOCK
# include <sys/file.h>
#endif
-#ifdef HAVE_LOCKF
-# include <unistd.h>
-#endif
-
-#include <signal.h>
#if defined(HAVE_LIBLOCKFILE)
-#include <lockfile.h>
+# include <lockfile.h>
#endif
#ifdef LOCKDIR
/*
* Number of tries to retry locking
*/
-#define LOCK_RETRIES 5
+#define LOCK_RETRIES 60
/*
* Amount of time to wait before
/* 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);
*/
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");
datalockinit = 1;
}
- return lkopen(file, access, mode, datalocktype);
+ return lkopen(file, access, mode, datalocktype, failed_to_lock);
}
* 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);
spoollockinit = 1;
}
- return lkopen(file, access, mode, spoollocktype);
+ return lkopen(file, access, mode, spoollocktype, failed_to_lock);
}
*/
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);
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) {
{
FILE *fp;
int oflags = str2accbits(mode);
+ int failed_to_lock = 0;
int fd;
if (oflags == -1) {
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) {
int
lkfclosedata(FILE *f, const char *name)
{
- int fd = fileno(f);
- int rc = fclose(f);
+ int fd, rc;
+
+ if (f == NULL)
+ return 0;
+
+ fd = fileno(f);
+ rc = fclose(f);
if (datalocktype == DOT_LOCKING)
lkclose_dot(fd, name);
int
lkfclosespool(FILE *f, const char *name)
{
- int fd = fileno(f);
- int rc = fclose(f);
+ int fd, rc;
+
+ if (f == NULL)
+ return 0;
+
+ fd = fileno(f);
+ rc = fclose(f);
if (spoollocktype == DOT_LOCKING)
lkclose_dot(fd, name);
{
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;
}
/*
*/
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:
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 */
*/
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;
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;
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;
sleep(1);
}
+ *failed_to_lock = 1;
errno = saved_errno;
return -1;
}
*/
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;
#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 */
}
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 */
* 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);
}
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) {
SIGNAL (SIGALRM, alrmser);
alarm (NSECS);
}
-
l_top = lp;
}
static enum locktype
init_locktype(const char *lockname)
{
- if (mh_strcasecmp(lockname, "fcntl") == 0) {
+ if (strcasecmp(lockname, "fcntl") == 0) {
return FCNTL_LOCKING;
- } else if (mh_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 (mh_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 (mh_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;
}