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

svn:r17391
This commit is contained in:
Nick Mathewson 2008-11-26 16:10:56 +00:00
parent cfd21c58b5
commit bc597758dc
3 changed files with 27 additions and 3 deletions

View File

@ -18,6 +18,8 @@ Changes in version 0.2.1.8-alpha - 2008-??-??
0.1.2.8-beta. 0.1.2.8-beta.
- If one win32 nameserver fails to get added, continue adding the - If one win32 nameserver fails to get added, continue adding the
rest, and don't automatically fail. 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): o Minor features (controller):
- Return circuit purposes in response to GETINFO circuit-status. Fixes - Return circuit purposes in response to GETINFO circuit-status. Fixes

View File

@ -196,7 +196,7 @@ dnl -------------------------------------------------------------------
dnl Check for functions before libevent, since libevent-1.2 apparently dnl Check for functions before libevent, since libevent-1.2 apparently
dnl exports strlcpy without defining it in a header. 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 using_custom_malloc=no
if test x$enable_openbsd_malloc = xyes ; then if test x$enable_openbsd_malloc = xyes ; then

View File

@ -491,6 +491,10 @@ struct tor_lockfile_t {
* otherwise. * otherwise.
* *
* Return a <b>tor_lockfile_t</b> on success, NULL on failure. * 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_t *
tor_lockfile_lock(const char *filename, int blocking, int *locked_out) 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)); strerror(errno));
return NULL; return NULL;
} }
#ifdef WIN32 #ifdef WIN32
_lseek(fd, 0, SEEK_SET); _lseek(fd, 0, SEEK_SET);
if (_locking(fd, blocking ? _LK_LOCK : _LK_NBLCK, 1) < 0) { 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); close(fd);
return NULL; return NULL;
} }
#else #elif defined(HAVE_FLOCK)
if (flock(fd, LOCK_EX|(blocking ? 0 : LOCK_NB)) < 0) { if (flock(fd, LOCK_EX|(blocking ? 0 : LOCK_NB)) < 0) {
if (errno != EWOULDBLOCK) if (errno != EWOULDBLOCK)
log_warn(LD_FS,"Couldn't lock \"%s\": %s", filename, strerror(errno)); 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); close(fd);
return NULL; 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 #endif
result = tor_malloc(sizeof(tor_lockfile_t)); 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, log_warn(LD_FS,"Error unlocking \"%s\": %s", lockfile->filename,
strerror(errno)); strerror(errno));
} }
#else #elif defined(HAVE_FLOCK)
if (flock(lockfile->fd, LOCK_UN) < 0) { if (flock(lockfile->fd, LOCK_UN) < 0) {
log_warn(LD_FS, "Error unlocking \"%s\": %s", lockfile->filename, log_warn(LD_FS, "Error unlocking \"%s\": %s", lockfile->filename,
strerror(errno)); strerror(errno));
} }
#else
/* Closing the lockfile is sufficient. */
#endif #endif
close(lockfile->fd); close(lockfile->fd);