Mercurial > noffle
view src/lock.c @ 129:6b2b93288caa noffle
[svn] Fix potential lock bug
author | bears |
---|---|
date | Wed, 09 Aug 2000 22:20:12 +0100 |
parents | 3c71e28c8eef |
children | 8ea6b5ddc5a5 |
line wrap: on
line source
/* lock.c $Id: lock.c 183 2000-07-25 12:14:54Z bears $ */ #if HAVE_CONFIG_H #include <config.h> #endif #include <stdio.h> #include "lock.h" #include <errno.h> #include <ctype.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #if TIME_WITH_SYS_TIME #include <sys/time.h> #include <time.h> #else #if HAVE_SYS_TIME_H #include <sys/time.h> #else #include <time.h> #endif #endif #include <unistd.h> #include "configfile.h" #include "log.h" #include "database.h" #include "group.h" #include "request.h" #include "portable.h" struct Lock { const char *name; int lockFd; Str lockFile; }; struct Lock globalLock = { "global", -1, "" }; struct Lock fetchLock = { "fetch", -1, "" }; /* Check the global lock held. */ static Bool gotLock( struct Lock *lock ) { return ( lock->lockFd != -1 ); } static Bool waitLock( struct Lock *lock, enum LockRequestWait wait ) { int fd; struct flock l; ASSERT( ! gotLock( lock ) ); Log_dbg( "Waiting for lock %s ...", lock->name ); if ( lock->lockFile[ 0 ] == '\0' ) snprintf( lock->lockFile, MAXCHAR, "%s/lock/%s", Cfg_spoolDir(), lock->name ); if ( ( fd = open( lock->lockFile, O_WRONLY | O_CREAT, 0644 ) ) < 0 ) { Log_err( "Cannot open %s (%s)", lock->lockFile, strerror( errno ) ); return FALSE; } l.l_type = F_WRLCK; l.l_start = 0; l.l_whence = SEEK_SET; l.l_len = 0; if ( wait == LOCK_WAIT ) { if ( fcntl( fd, F_SETLKW, &l ) < 0 ) { Log_err( "Cannot lock %s: %s", lock->lockFile, strerror( errno ) ); close( lock->lockFd ); return FALSE; } } else { if ( fcntl( fd, F_SETLK, &l ) < 0 ) { close( lock->lockFd ); return FALSE; } } lock->lockFd = fd; Log_dbg( "Lock successful" ); return TRUE; } static void releaseLock( struct Lock *lock ) { struct flock l; ASSERT( gotLock( lock ) ); l.l_type = F_UNLCK; l.l_start = 0; l.l_whence = SEEK_SET; l.l_len = 0; if ( fcntl( lock->lockFd, F_SETLK, &l ) < 0 ) Log_err( "Cannot release %s: %s", lock->lockFile, strerror( errno ) ); close( lock->lockFd ); lock->lockFd = -1; Log_dbg( "Releasing lock" ); } /* Open all databases and set global lock. */ Bool Lock_openDatabases( void ) { if ( ! waitLock( &globalLock, LOCK_WAIT ) ) { Log_err( "Could not get write lock" ); return FALSE; } if ( ! Db_open() ) { Log_err( "Could not open database" ); releaseLock( &globalLock ); return FALSE; } if ( ! Grp_open() ) { Log_err( "Could not open groupinfo" ); Db_close(); releaseLock( &globalLock ); return FALSE; } if ( ! Req_open() ) { Log_err( "Could not initialize request database" ); Grp_close(); Db_close(); releaseLock( &globalLock ); return FALSE; } return TRUE; } /* Close all databases and release global lock. */ void Lock_closeDatabases( void ) { Grp_close(); Db_close(); Req_close(); releaseLock( &globalLock ); } /* Check the global lock held. */ Bool Lock_gotLock( void ) { return gotLock( &globalLock ); } /* Get fetch lock. */ Bool Lock_getFetchLock( enum LockRequestWait wait ) { return waitLock( &fetchLock, wait ); } /* Release fetch lock. */ void Lock_releaseFetchLock( void ) { releaseLock( &fetchLock ); } /* Check the fetch lock held. */ Bool Lock_fetchLock( void ) { return gotLock( &fetchLock ); }