* 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:
Eelco Dolstra 2010-02-02 15:28:36 +00:00
parent 2723d9b56e
commit 4bbbe25802
4 changed files with 5 additions and 112 deletions

View file

@ -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

View file

@ -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);
} }

View file

@ -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 };

View file

@ -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
} }