Browse Source

Use fcntl for file locking when flock() is not available.

svn:r17391
Nick Mathewson 15 years ago
parent
commit
bc597758dc
3 changed files with 27 additions and 3 deletions
  1. 2 0
      ChangeLog
  2. 1 1
      configure.in
  3. 24 2
      src/common/compat.c

+ 2 - 0
ChangeLog

@@ -18,6 +18,8 @@ Changes in version 0.2.1.8-alpha - 2008-??-??
       0.1.2.8-beta.
     - If one win32 nameserver fails to get added, continue adding the
       rest, and don't automatically fail.
+    - Use fcntl() for locking when flock() is not available.  Should fix
+      compilation on Solaris.  Should fix Bug 873.  Bugfix on 0.2.1.6-alpha.
 
   o Minor features (controller):
     - Return circuit purposes in response to GETINFO circuit-status.  Fixes

+ 1 - 1
configure.in

@@ -196,7 +196,7 @@ dnl -------------------------------------------------------------------
 dnl Check for functions before libevent, since libevent-1.2 apparently
 dnl exports strlcpy without defining it in a header.
 
-AC_CHECK_FUNCS(gettimeofday ftime socketpair uname inet_aton strptime getrlimit strlcat strlcpy strtoull ftello getaddrinfo localtime_r gmtime_r memmem strtok_r inet_pton inet_ntop writev readv)
+AC_CHECK_FUNCS(gettimeofday ftime socketpair uname inet_aton strptime getrlimit strlcat strlcpy strtoull ftello getaddrinfo localtime_r gmtime_r memmem strtok_r inet_pton inet_ntop writev readv flock)
 
 using_custom_malloc=no
 if test x$enable_openbsd_malloc = xyes ; then

+ 24 - 2
src/common/compat.c

@@ -491,6 +491,10 @@ struct tor_lockfile_t {
  * otherwise.
  *
  * Return a <b>tor_lockfile_t</b> on success, NULL on failure.
+ *
+ * (Implementation note: because we need to fall back to fcntl on some
+ *  platforms, these locks are per-process, not per-thread.  If you want
+ *  to do in-process locking, use tor_mutex_t like a normal person.)
  */
 tor_lockfile_t *
 tor_lockfile_lock(const char *filename, int blocking, int *locked_out)
@@ -506,6 +510,7 @@ tor_lockfile_lock(const char *filename, int blocking, int *locked_out)
              strerror(errno));
     return NULL;
   }
+
 #ifdef WIN32
   _lseek(fd, 0, SEEK_SET);
   if (_locking(fd, blocking ? _LK_LOCK : _LK_NBLCK, 1) < 0) {
@@ -516,7 +521,7 @@ tor_lockfile_lock(const char *filename, int blocking, int *locked_out)
     close(fd);
     return NULL;
   }
-#else
+#elif defined(HAVE_FLOCK)
   if (flock(fd, LOCK_EX|(blocking ? 0 : LOCK_NB)) < 0) {
     if (errno != EWOULDBLOCK)
       log_warn(LD_FS,"Couldn't lock \"%s\": %s", filename, strerror(errno));
@@ -525,6 +530,21 @@ tor_lockfile_lock(const char *filename, int blocking, int *locked_out)
     close(fd);
     return NULL;
   }
+#else
+  {
+    struct flock lock;
+    memset(&lock, 0, sizeof(lock));
+    lock.l_type = F_WRLCK;
+    lock.l_whence = SEEK_SET;
+    if (fcntl(fd, blocking ? F_SETLKW : F_SETLK, &lock) < 0) {
+      if (errno != EACCES && errno != EAGAIN)
+        log_warn(LD_FS, "Couldn't lock \"%s\": %s", filename, strerror(errno));
+      else
+        *locked_out = 1;
+      close(fd);
+      return NULL;
+    }
+  }
 #endif
 
   result = tor_malloc(sizeof(tor_lockfile_t));
@@ -546,11 +566,13 @@ tor_lockfile_unlock(tor_lockfile_t *lockfile)
     log_warn(LD_FS,"Error unlocking \"%s\": %s", lockfile->filename,
              strerror(errno));
   }
-#else
+#elif defined(HAVE_FLOCK)
   if (flock(lockfile->fd, LOCK_UN) < 0) {
     log_warn(LD_FS, "Error unlocking \"%s\": %s", lockfile->filename,
              strerror(errno));
   }
+#else
+  /* Closing the lockfile is sufficient. */
 #endif
 
   close(lockfile->fd);