mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-23 00:41:02 +00:00
Fix directory creation to use low level methods which consider the presence
of an existing directory to be an error, rather than the NSFileManager methods that consider it a success. The logic of distributed locking requires us to fail if a directory already exists.
This commit is contained in:
parent
a5a2e85423
commit
ed721bf4da
4 changed files with 80 additions and 29 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
|||
2017-06-16 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Source/NSDistributedLock.m: Change code to create lock directory
|
||||
directly rather than via the NSFileManager methods since Wolfgang
|
||||
pointed out that those methods consider a pre-existing directory to
|
||||
have been successfully created, but the distributed locking logic
|
||||
supposes that an attempt to create an existing directory will fail.
|
||||
* Tests/base/NSDistributedLock:
|
||||
* Tests/base/NSDistributedLock/TestInfo:
|
||||
* Tests/base/NSDistributedLock/basic.m:
|
||||
Add a few simple testcases for NSDistributedLock.
|
||||
|
||||
2017-05-19 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* Headers/Foundation/NSFileHandle.h:
|
||||
|
|
|
@ -41,6 +41,14 @@
|
|||
# include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
|
||||
static NSFileManager *mgr = nil;
|
||||
|
||||
|
@ -230,37 +238,36 @@ static NSFileManager *mgr = nil;
|
|||
attributesToSet = [NSMutableDictionary dictionaryWithCapacity: 1];
|
||||
[attributesToSet setObject: [NSNumber numberWithUnsignedInt: 0755]
|
||||
forKey: NSFilePosixPermissions];
|
||||
|
||||
locked = [mgr createDirectoryAtPath: _lockPath
|
||||
withIntermediateDirectories: YES
|
||||
attributes: attributesToSet
|
||||
error: NULL];
|
||||
|
||||
/* We must not use the NSFileManager directory creation methods,
|
||||
* since they consider the presence of an existing directory a
|
||||
* success, and we need to know if we can actually create a new
|
||||
* directory.
|
||||
*/
|
||||
#if defined(_WIN32)
|
||||
{
|
||||
const unichar *lpath;
|
||||
|
||||
lpath = [mgr fileSystemRepresentationWithPath: _lockPath];
|
||||
locked = (CreateDirectoryW(lpath, 0) != FALSE) ? YES : NO;
|
||||
}
|
||||
#else
|
||||
{
|
||||
const char *lpath;
|
||||
|
||||
lpath = [mgr fileSystemRepresentationWithPath: _lockPath];
|
||||
locked = (mkdir(lpath, 0777) == 0) ? YES : NO;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (NO == locked)
|
||||
{
|
||||
NSLog(@"Failed to create lock directory '%@' - %@",
|
||||
_lockPath, [NSError _last]);
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOL dir;
|
||||
|
||||
/* We expect the directory creation to have failed because
|
||||
* it already exists as another processes lock.
|
||||
* If the directory doesn't exist, then either the other
|
||||
* process has removed it's lock (and we can retry)
|
||||
* or we have a severe problem!
|
||||
*/
|
||||
if ([mgr fileExistsAtPath: _lockPath isDirectory: &dir] == NO)
|
||||
{
|
||||
locked = [mgr createDirectoryAtPath: _lockPath
|
||||
withIntermediateDirectories: YES
|
||||
attributes: attributesToSet
|
||||
error: NULL];
|
||||
if (NO == locked)
|
||||
{
|
||||
NSLog(@"Failed to create lock directory '%@' - %@",
|
||||
_lockPath, [NSError _last]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (YES == locked)
|
||||
{
|
||||
[mgr changeFileAttributes: attributesToSet atPath: _lockPath];
|
||||
attributes = [mgr fileAttributesAtPath: _lockPath
|
||||
traverseLink: YES];
|
||||
if (attributes == nil)
|
||||
|
|
0
Tests/base/NSDistributedLock/TestInfo
Normal file
0
Tests/base/NSDistributedLock/TestInfo
Normal file
32
Tests/base/NSDistributedLock/basic.m
Normal file
32
Tests/base/NSDistributedLock/basic.m
Normal file
|
@ -0,0 +1,32 @@
|
|||
#import "ObjectTesting.h"
|
||||
#import <Foundation/NSDistributedLock.h>
|
||||
#import <Foundation/NSFileManager.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
START_SET("basic")
|
||||
|
||||
NSString *path;
|
||||
NSDistributedLock *lock1;
|
||||
NSDistributedLock *lock2;
|
||||
|
||||
test_NSObject(@"NSDistributedLock",
|
||||
[NSArray arrayWithObject: [NSDistributedLock new]]);
|
||||
|
||||
path = [[NSFileManager defaultManager] currentDirectoryPath];
|
||||
path = [path stringByAppendingPathComponent: @"MyLock"];
|
||||
lock1 = [NSDistributedLock lockWithPath: path];
|
||||
lock2 = [NSDistributedLock lockWithPath: path];
|
||||
|
||||
PASS(lock1 != lock2, "locks with the same path differ");
|
||||
|
||||
PASS(YES == [lock1 tryLock], "we can lock the first lock");
|
||||
|
||||
PASS(NO == [lock2 tryLock], "the locks are exclusive");
|
||||
|
||||
[lock1 unlock];
|
||||
PASS(YES == [lock2 tryLock], "unlocking first lock allows second lock");
|
||||
|
||||
END_SET("basic")
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue