* Remove most Cygwin-specific code. Cygwin 1.7 implements advisory
POSIX locks, and simulates Unix-style file deletion semantics sufficiently. Note that this means that Nix won't work on Cygwin 1.5 anymore.
This commit is contained in:
		
							parent
							
								
									2723d9b56e
								
							
						
					
					
						commit
						4bbbe25802
					
				
					 4 changed files with 5 additions and 112 deletions
				
			
		|  | @ -15,11 +15,6 @@ | ||||||
| #include <fcntl.h> | #include <fcntl.h> | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
| 
 | 
 | ||||||
| #ifdef __CYGWIN__ |  | ||||||
| #include <windows.h> |  | ||||||
| #include <sys/cygwin.h> |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| namespace nix { | namespace nix { | ||||||
| 
 | 
 | ||||||
|  | @ -179,15 +174,6 @@ void LocalStore::addTempRoot(const Path & path) | ||||||
| 
 | 
 | ||||||
|             fdGCLock.close(); |             fdGCLock.close(); | ||||||
|        |        | ||||||
| 	    /* Note that on Cygwin a lot of the following complexity
 |  | ||||||
| 	       is unnecessary, since we cannot delete open lock |  | ||||||
| 	       files.  If we have the lock file open, then it's valid; |  | ||||||
| 	       if we can delete it, then it wasn't in use any more.  |  | ||||||
| 
 |  | ||||||
| 	       Also note that on Cygwin we cannot "upgrade" a lock |  | ||||||
| 	       from a read lock to a write lock. */ |  | ||||||
| 
 |  | ||||||
| #ifndef __CYGWIN__ |  | ||||||
|             debug(format("acquiring read lock on `%1%'") % fnTempRoots); |             debug(format("acquiring read lock on `%1%'") % fnTempRoots); | ||||||
|             lockFile(fdTempRoots, ltRead, true); |             lockFile(fdTempRoots, ltRead, true); | ||||||
| 
 | 
 | ||||||
|  | @ -201,10 +187,6 @@ void LocalStore::addTempRoot(const Path & path) | ||||||
|             /* The garbage collector deleted this file before we could
 |             /* The garbage collector deleted this file before we could
 | ||||||
|                get a lock.  (It won't delete the file after we get a |                get a lock.  (It won't delete the file after we get a | ||||||
|                lock.)  Try again. */ |                lock.)  Try again. */ | ||||||
| 
 |  | ||||||
| #else |  | ||||||
|             break; |  | ||||||
| #endif |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
|  | @ -217,14 +199,9 @@ void LocalStore::addTempRoot(const Path & path) | ||||||
|     string s = path + '\0'; |     string s = path + '\0'; | ||||||
|     writeFull(fdTempRoots, (const unsigned char *) s.c_str(), s.size()); |     writeFull(fdTempRoots, (const unsigned char *) s.c_str(), s.size()); | ||||||
| 
 | 
 | ||||||
| #ifndef __CYGWIN__ |  | ||||||
|     /* Downgrade to a read lock. */ |     /* Downgrade to a read lock. */ | ||||||
|     debug(format("downgrading to read lock on `%1%'") % fnTempRoots); |     debug(format("downgrading to read lock on `%1%'") % fnTempRoots); | ||||||
|     lockFile(fdTempRoots, ltRead, true); |     lockFile(fdTempRoots, ltRead, true); | ||||||
| #else |  | ||||||
|     debug(format("releasing write lock on `%1%'") % fnTempRoots); |  | ||||||
|     lockFile(fdTempRoots, ltNone, true); |  | ||||||
| #endif |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -252,19 +229,6 @@ static void readTempRoots(PathSet & tempRoots, FDs & fds) | ||||||
|         Path path = (format("%1%/%2%/%3%") % nixStateDir % tempRootsDir % *i).str(); |         Path path = (format("%1%/%2%/%3%") % nixStateDir % tempRootsDir % *i).str(); | ||||||
| 
 | 
 | ||||||
|         debug(format("reading temporary root file `%1%'") % path); |         debug(format("reading temporary root file `%1%'") % path); | ||||||
| 
 |  | ||||||
| #ifdef __CYGWIN__ |  | ||||||
| 	/* On Cygwin we just try to delete the lock file. */ |  | ||||||
| 	char win32Path[MAX_PATH]; |  | ||||||
| 	cygwin_conv_to_full_win32_path(path.c_str(), win32Path); |  | ||||||
| 	if (DeleteFile(win32Path)) { |  | ||||||
|             printMsg(lvlError, format("removed stale temporary roots file `%1%'") |  | ||||||
|                 % path); |  | ||||||
|             continue; |  | ||||||
|         } else |  | ||||||
|             debug(format("delete of `%1%' failed: %2%") % path % GetLastError()); |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
|         FDPtr fd(new AutoCloseFD(open(path.c_str(), O_RDWR, 0666))); |         FDPtr fd(new AutoCloseFD(open(path.c_str(), O_RDWR, 0666))); | ||||||
|         if (*fd == -1) { |         if (*fd == -1) { | ||||||
|             /* It's okay if the file has disappeared. */ |             /* It's okay if the file has disappeared. */ | ||||||
|  | @ -276,7 +240,6 @@ static void readTempRoots(PathSet & tempRoots, FDs & fds) | ||||||
|         //FDPtr fd(new AutoCloseFD(openLockFile(path, false)));
 |         //FDPtr fd(new AutoCloseFD(openLockFile(path, false)));
 | ||||||
|         //if (*fd == -1) continue;
 |         //if (*fd == -1) continue;
 | ||||||
| 
 | 
 | ||||||
| #ifndef __CYGWIN__ |  | ||||||
|         /* Try to acquire a write lock without blocking.  This can
 |         /* Try to acquire a write lock without blocking.  This can
 | ||||||
|            only succeed if the owning process has died.  In that case |            only succeed if the owning process has died.  In that case | ||||||
|            we don't care about its temporary roots. */ |            we don't care about its temporary roots. */ | ||||||
|  | @ -287,7 +250,6 @@ static void readTempRoots(PathSet & tempRoots, FDs & fds) | ||||||
|             writeFull(*fd, (const unsigned char *) "d", 1); |             writeFull(*fd, (const unsigned char *) "d", 1); | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
|         /* Acquire a read lock.  This will prevent the owning process
 |         /* Acquire a read lock.  This will prevent the owning process
 | ||||||
|            from upgrading to a write lock, therefore it will block in |            from upgrading to a write lock, therefore it will block in | ||||||
|  |  | ||||||
|  | @ -8,11 +8,6 @@ | ||||||
| #include <sys/stat.h> | #include <sys/stat.h> | ||||||
| #include <fcntl.h> | #include <fcntl.h> | ||||||
| 
 | 
 | ||||||
| #ifdef __CYGWIN__ |  | ||||||
| #include <windows.h> |  | ||||||
| #include <sys/cygwin.h> |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| namespace nix { | namespace nix { | ||||||
| 
 | 
 | ||||||
|  | @ -21,72 +16,24 @@ int openLockFile(const Path & path, bool create) | ||||||
| { | { | ||||||
|     AutoCloseFD fd; |     AutoCloseFD fd; | ||||||
| 
 | 
 | ||||||
| #ifdef __CYGWIN__ |  | ||||||
|     /* On Cygwin we have to open the lock file without "DELETE"
 |  | ||||||
|        sharing mode; otherwise Windows will allow open lock files to |  | ||||||
|        be deleted (which is almost but not quite what Unix does). */ |  | ||||||
|     char win32Path[MAX_PATH + 1]; |  | ||||||
|     cygwin_conv_to_full_win32_path(path.c_str(), win32Path); |  | ||||||
| 
 |  | ||||||
|     SECURITY_ATTRIBUTES sa; /* required, otherwise inexplicably bad shit happens */ |  | ||||||
|     sa.nLength = sizeof sa; |  | ||||||
|     sa.lpSecurityDescriptor = 0; |  | ||||||
|     sa.bInheritHandle = TRUE; |  | ||||||
|     HANDLE h = CreateFile(win32Path, GENERIC_READ | GENERIC_WRITE, |  | ||||||
|         FILE_SHARE_READ | FILE_SHARE_WRITE, &sa,  |  | ||||||
|         (create ? OPEN_ALWAYS : OPEN_EXISTING),  |  | ||||||
|         FILE_ATTRIBUTE_NORMAL, 0); |  | ||||||
|     if (h == INVALID_HANDLE_VALUE) { |  | ||||||
|         if (create || GetLastError() != ERROR_FILE_NOT_FOUND) |  | ||||||
|             throw Error(format("opening lock file `%1%'") % path); |  | ||||||
|         fd = -1; |  | ||||||
|     } |  | ||||||
|     else |  | ||||||
|         fd = cygwin_attach_handle_to_fd((char *) path.c_str(), -1, h, 1, O_RDWR); |  | ||||||
| #else         |  | ||||||
|     fd = open(path.c_str(), O_RDWR | (create ? O_CREAT : 0), 0666); |     fd = open(path.c_str(), O_RDWR | (create ? O_CREAT : 0), 0666); | ||||||
|     if (fd == -1 && (create || errno != ENOENT)) |     if (fd == -1 && (create || errno != ENOENT)) | ||||||
|         throw SysError(format("opening lock file `%1%'") % path); |         throw SysError(format("opening lock file `%1%'") % path); | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
|     return fd.borrow(); |     return fd.borrow(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| void deleteLockFilePreClose(const Path & path, int fd) | void deleteLockFile(const Path & path, int fd) | ||||||
| { | { | ||||||
| #ifndef __CYGWIN__ |  | ||||||
|     /* Get rid of the lock file.  Have to be careful not to introduce
 |     /* Get rid of the lock file.  Have to be careful not to introduce
 | ||||||
|        races. */ |        races.  Write a (meaningless) token to the file to indicate to | ||||||
|     /* On Unix, write a (meaningless) token to the file to indicate to
 |  | ||||||
|        other processes waiting on this lock that the lock is stale |        other processes waiting on this lock that the lock is stale | ||||||
|        (deleted). */ |        (deleted). */ | ||||||
|     unlink(path.c_str()); |     unlink(path.c_str()); | ||||||
|     writeFull(fd, (const unsigned char *) "d", 1); |     writeFull(fd, (const unsigned char *) "d", 1); | ||||||
|     /* Note that the result of unlink() is ignored; removing the lock
 |     /* Note that the result of unlink() is ignored; removing the lock
 | ||||||
|        file is an optimisation, not a necessity. */ |        file is an optimisation, not a necessity. */ | ||||||
| #endif |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| void deleteLockFilePostClose(const Path & path) |  | ||||||
| { |  | ||||||
| #ifdef __CYGWIN__ |  | ||||||
|     /* On Windows, just try to delete the lock file.  This will fail
 |  | ||||||
|        if anybody still has the file open.  We cannot use unlink() |  | ||||||
|        here, because Cygwin emulates Unix semantics of allowing an |  | ||||||
|        open file to be deleted (but fakes it - the file isn't actually |  | ||||||
|        deleted until later, so a file with the same name cannot be |  | ||||||
|        created in the meantime). */ |  | ||||||
|     char win32Path[MAX_PATH + 1]; |  | ||||||
|     cygwin_conv_to_full_win32_path(path.c_str(), win32Path); |  | ||||||
|     if (DeleteFile(win32Path)) |  | ||||||
|         debug(format("delete of `%1%' succeeded") % path.c_str()); |  | ||||||
|     else |  | ||||||
|         /* Not an error: probably means that the lock is still opened
 |  | ||||||
|            by someone else. */ |  | ||||||
|         debug(format("delete of `%1%' failed: %2%") % path.c_str() % GetLastError()); |  | ||||||
| #endif |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -220,15 +167,13 @@ PathLocks::~PathLocks() | ||||||
| void PathLocks::unlock() | void PathLocks::unlock() | ||||||
| { | { | ||||||
|     foreach (list<FDPair>::iterator, i, fds) { |     foreach (list<FDPair>::iterator, i, fds) { | ||||||
|         if (deletePaths) deleteLockFilePreClose(i->second, i->first); |         if (deletePaths) deleteLockFile(i->second, i->first); | ||||||
| 
 | 
 | ||||||
|         lockedPaths.erase(i->second); |         lockedPaths.erase(i->second); | ||||||
|         if (close(i->first) == -1) |         if (close(i->first) == -1) | ||||||
|             printMsg(lvlError, |             printMsg(lvlError, | ||||||
|                 format("error (ignored): cannot close lock file on `%1%'") % i->second); |                 format("error (ignored): cannot close lock file on `%1%'") % i->second); | ||||||
| 
 | 
 | ||||||
| 	if (deletePaths) deleteLockFilePostClose(i->second); |  | ||||||
| 
 |  | ||||||
|         debug(format("lock released on `%1%'") % i->second); |         debug(format("lock released on `%1%'") % i->second); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -12,10 +12,8 @@ namespace nix { | ||||||
|    because it doesn't exist.  Any other error throws an exception. */ |    because it doesn't exist.  Any other error throws an exception. */ | ||||||
| int openLockFile(const Path & path, bool create); | int openLockFile(const Path & path, bool create); | ||||||
| 
 | 
 | ||||||
| /* Delete an open lock file.  Both must be called to be fully portable
 | /* Delete an open lock file. */ | ||||||
|    between Unix and Windows. */ | void deleteLockFile(const Path & path, int fd); | ||||||
| void deleteLockFilePreClose(const Path & path, int fd); |  | ||||||
| void deleteLockFilePostClose(const Path & path); |  | ||||||
| 
 | 
 | ||||||
| enum LockType { ltRead, ltWrite, ltNone }; | enum LockType { ltRead, ltWrite, ltNone }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,9 +1,5 @@ | ||||||
| #include "config.h" | #include "config.h" | ||||||
| 
 | 
 | ||||||
| #ifdef __CYGWIN__ |  | ||||||
| #include <windows.h> |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #include <iostream> | #include <iostream> | ||||||
| #include <cerrno> | #include <cerrno> | ||||||
| #include <cstdio> | #include <cstdio> | ||||||
|  | @ -905,15 +901,7 @@ void closeMostFDs(const set<int> & exceptions) | ||||||
| 
 | 
 | ||||||
| void quickExit(int status) | void quickExit(int status) | ||||||
| { | { | ||||||
| #ifdef __CYGWIN__ |  | ||||||
|     /* Hack for Cygwin: _exit() doesn't seem to work quite right,
 |  | ||||||
|        since some Berkeley DB code appears to be called when a child |  | ||||||
|        exits through _exit() (e.g., because execve() failed).  So call |  | ||||||
|        the Windows API directly. */ |  | ||||||
|     ExitProcess(status); |  | ||||||
| #else |  | ||||||
|     _exit(status); |     _exit(status); | ||||||
| #endif |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue