I have some code which sets and clears lock files that works fine on
linux but the Windows equivalent does not seem to handle empty files
properly. Is there some way to lock an empty file on Windows? Any
suggestions will be greatly appreciated.
Details...
This is what I have now (partially, it is part of something much
larger):
#ifdef USE_WINDOWS
typedef HANDLE LOCK_HANDLE;
#else
typedef int LOCK_HANDLE;
#endif
LOCK_HANDLE lock_set(const char *lfname){
fprintf(stderr,"binorder: status: waiting for lock on %s\n",lfname);
LOCK_HANDLE lh;
#ifdef USE_WINDOWS
lh = CreateFile(_MT(lfname), GENERIC_READ | GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, 0, NULL);
if(lh == INVALID_HANDLE_VALUE){
// try just read, if it already exists then hopefully it has at
least one byte in it
lh = CreateFile(_MT(lfname), GENERIC_READ, 0, NULL, CREATE_ALWAYS,
0, NULL);
if(lh == INVALID_HANDLE_VALUE){
insane("binorder: fatal error: could not open or create a lock
file\n");
}
}
else {
// write 1 byte of data to it
char buf=0x12; // value does not matter, but set it to something
DWORD dwNumBytesWritten;
if(!WriteFile(lh, &buf, 1, &dwNumBytesWritten, NULL)){
insane("binorder: fatal error: could not write one byte to lock
file\n");
}
}
if(!LockFile(lh, 0, 0, 1, 0)){ // lock the first byte
insane("binorder: fatal error: could not lock an open file\n");
}
#else
lh = open(lfname, O_RDWR|O_CREAT,S_IRWXU);
if(lh==-1){ /* maybe it already exists and we cannot write it, try RD
*/
lh = open(lfname, O_RDONLY);
if(lh==-1)insane("binorder: fatal error: could not open a lock
file\n");
}
/* get an exclusive lock, wait until that happens, potentially
forever */
int result = flock(lh, LOCK_EX);
if(result)insane("binorder: fatal error: could not place a lock on a
lock file\n");
fprintf(stderr,"binorder: status: locked %s with lh %d\n",lfname,lh);
#endif
return(lh);
}
/* release a lock. If the program exits locks are automatically
released, so
there is no need to call this on exits caused by errors. */
void lock_clr(LOCK_HANDLE lh){
#ifdef USE_WINDOWS
LPBY_HANDLE_FILE_INFORMATION lhfi =
malloc(sizeof(BY_HANDLE_FILE_INFORMATION));
if(!GetFileInformationByHandle(lh,lhfi))return; // not fatal, but no
lock to clear
fprintf(stderr,"binorder: status: releasing lock on lh %p\n",lh);
if(!UnlockFile(lh, 0, 0, 1, 0)){
insane("binorder: fatal error: could not release a lock on a lock
file\n");
}
if(!CloseHandle(lh)){
insane("binorder: fatal error: could close handle on unlocked
file\n");
}
#else
if(!lh)return;
fprintf(stderr,"binorder: status: releasing lock on lh %d\n",lh);
int result = flock(lh, LOCK_UN);
if(result)insane("binorder: fatal error: could not release a lock on
a lock file\n");
(void) close(lh);
#endif
}
----
Some code to test it is:
NOW=`date`; echo "! Testing wlock - the wait for a write lock should
last ~5 seconds"
if [ false ]
then
rm -f /tmp/wlock
fi
(exec 200>$/tmp/wlock; \
NOW=`date`; echo "! ${NOW} locked wlock" ; \
flock -x 200; \
sleep 5; \
exec 200>&- ; \
NOW=`date`; echo "! ${NOW} unlocked wlock" ; \
NOW=`date`; echo "! ${NOW} locker/unlocker exits" \
)&
# give it a second to notice the unlock \
sleep 2 #give the subprocess time to place the lock
program -wlock /tmp/wlock
The test program just tries to lock, and then unlock that file. It
should do so 3 only
after the subprocess releases its lock.
This works fine (always) on Linux and sometimes on Windows. For the
latter if wlock already exists and is at least 1 byte everything is
fine. However if the "false" is changed to true
then the flock program creates an empty /tmp/wlock and Filelock() fails,
presumably because the range it has been told to lock does not exist.
But I don't see how to tell Filelock() to lock "no bytes"!
Thanks,
David Mathog
[email protected]
Manager, Sequence Analysis Facility, Biology Division, Caltech
_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public