Author: rfm
Date: Wed Jun 22 11:09:29 2016
New Revision: 39902
URL: http://svn.gna.org/viewcvs/gnustep?rev=39902&view=rev
Log:
Thread-safety fixes.
Modified:
libs/base/trunk/ChangeLog
libs/base/trunk/Headers/Foundation/NSDistributedLock.h
libs/base/trunk/Source/NSDistributedLock.m
Modified: libs/base/trunk/ChangeLog
URL:
http://svn.gna.org/viewcvs/gnustep/libs/base/trunk/ChangeLog?rev=39902&r1=39901&r2=39902&view=diff
==============================================================================
--- libs/base/trunk/ChangeLog (original)
+++ libs/base/trunk/ChangeLog Wed Jun 22 11:09:29 2016
@@ -6,6 +6,8 @@
* Source/NSOperation.m: When starting an operation, have it retain
itself in case it'ss removed from the queue and released while
running.
+ * Headers/Foundation/NSDistributedLock.h: Add lock ivar.
+ * Source/NSDistributedLock.m: Make class thread-safe using lock.
2016-06-19 Richard Frith-Macdonald <[email protected]>
Modified: libs/base/trunk/Headers/Foundation/NSDistributedLock.h
URL:
http://svn.gna.org/viewcvs/gnustep/libs/base/trunk/Headers/Foundation/NSDistributedLock.h?rev=39902&r1=39901&r2=39902&view=diff
==============================================================================
--- libs/base/trunk/Headers/Foundation/NSDistributedLock.h (original)
+++ libs/base/trunk/Headers/Foundation/NSDistributedLock.h Wed Jun 22
11:09:29 2016
@@ -27,8 +27,10 @@
#import <GNUstepBase/GSVersionMacros.h>
#import <Foundation/NSObject.h>
-#import <Foundation/NSString.h>
-#import <Foundation/NSDate.h>
+
+@class NSDate;
+@class NSLock;
+@class NSString;
#if defined(__cplusplus)
extern "C" {
@@ -39,6 +41,7 @@
#if GS_EXPOSE(NSDistributedLock)
NSString *_lockPath;
NSDate *_lockTime;
+ NSLock *_localLock;
#endif
#if GS_NONFRAGILE
#else
Modified: libs/base/trunk/Source/NSDistributedLock.m
URL:
http://svn.gna.org/viewcvs/gnustep/libs/base/trunk/Source/NSDistributedLock.m?rev=39902&r1=39901&r2=39902&view=diff
==============================================================================
--- libs/base/trunk/Source/NSDistributedLock.m (original)
+++ libs/base/trunk/Source/NSDistributedLock.m Wed Jun 22 11:09:29 2016
@@ -28,8 +28,9 @@
#import "common.h"
#define EXPOSE_NSDistributedLock_IVARS 1
#import "Foundation/NSDistributedLock.h"
+#import "Foundation/NSException.h"
#import "Foundation/NSFileManager.h"
-#import "Foundation/NSException.h"
+#import "Foundation/NSLock.h"
#import "Foundation/NSValue.h"
#import "GSPrivate.h"
@@ -74,27 +75,39 @@
*/
- (void) breakLock
{
- NSDictionary *attributes;
-
- DESTROY(_lockTime);
- attributes = [mgr fileAttributesAtPath: _lockPath traverseLink: YES];
- if (attributes != nil)
- {
- NSDate *modDate = [attributes fileModificationDate];
-
- if ([mgr removeFileAtPath: _lockPath handler: nil] == NO)
- {
- NSString *err = [[NSError _last] localizedDescription];
-
- attributes = [mgr fileAttributesAtPath: _lockPath traverseLink: YES];
- if ([modDate isEqual: [attributes fileModificationDate]] == YES)
- {
- [NSException raise: NSGenericException
- format: @"Failed to remove lock directory '%@' - %@",
- _lockPath, err];
- }
- }
- }
+ [_localLock lock];
+ NS_DURING
+ {
+ NSDictionary *attributes;
+
+ DESTROY(_lockTime);
+ attributes = [mgr fileAttributesAtPath: _lockPath traverseLink: YES];
+ if (attributes != nil)
+ {
+ NSDate *modDate = [attributes fileModificationDate];
+
+ if ([mgr removeFileAtPath: _lockPath handler: nil] == NO)
+ {
+ NSString *err = [[NSError _last] localizedDescription];
+
+ attributes = [mgr fileAttributesAtPath: _lockPath
+ traverseLink: YES];
+ if ([modDate isEqual: [attributes fileModificationDate]] == YES)
+ {
+ [NSException raise: NSGenericException
+ format: @"Failed to remove lock directory '%@' - %@",
+ _lockPath, err];
+ }
+ }
+ }
+ }
+ NS_HANDLER
+ {
+ [_localLock unlock];
+ [localException raise];
+ }
+ NS_ENDHANDLER
+ [_localLock unlock];
}
- (void) dealloc
@@ -107,21 +120,27 @@
}
RELEASE(_lockPath);
RELEASE(_lockTime);
+ RELEASE(_localLock);
[super dealloc];
}
- (NSString*) description
{
+ NSString *result;
+
+ [_localLock lock];
if (_lockTime == nil)
{
- return [[super description] stringByAppendingFormat:
+ result = [[super description] stringByAppendingFormat:
@" path '%@' not locked", _lockPath];
}
else
{
- return [[super description] stringByAppendingFormat:
+ result = [[super description] stringByAppendingFormat:
@" path '%@' locked at %@", _lockPath, _lockTime];
}
+ [_localLock unlock];
+ return result;
}
/**
@@ -137,6 +156,7 @@
NSString *lockDir;
BOOL isDirectory;
+ _localLock = [NSLock new];
_lockPath = [[aPath stringByStandardizingPath] copy];
_lockTime = nil;
@@ -189,59 +209,79 @@
*/
- (BOOL) tryLock
{
- NSMutableDictionary *attributesToSet;
- NSDictionary *attributes;
- BOOL locked;
-
- attributesToSet = [NSMutableDictionary dictionaryWithCapacity: 1];
- [attributesToSet setObject: [NSNumber numberWithUnsignedInt: 0755]
- forKey: NSFilePosixPermissions];
-
- locked = [mgr createDirectoryAtPath: _lockPath
- withIntermediateDirectories: YES
- attributes: attributesToSet
- error: NULL];
- if (locked == NO)
- {
- 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 (locked == NO)
- {
- NSLog(@"Failed to create lock directory '%@' - %@",
- _lockPath, [NSError _last]);
- }
- }
- }
-
- if (locked == NO)
- {
- return NO;
- }
- else
- {
- attributes = [mgr fileAttributesAtPath: _lockPath
- traverseLink: YES];
- if (attributes == nil)
+ BOOL locked = NO;
+
+ [_localLock lock];
+ NS_DURING
+ {
+ NSMutableDictionary *attributesToSet;
+ NSDictionary *attributes;
+
+ if (nil != _lockTime)
{
[NSException raise: NSGenericException
- format: @"Unable to get attributes of lock file we made at %@",
- _lockPath];
- }
- ASSIGN(_lockTime, [attributes fileModificationDate]);
- return YES;
- }
+ format: @"Attempt to re-lock distributed lock %@",
+ _lockPath];
+ }
+ attributesToSet = [NSMutableDictionary dictionaryWithCapacity: 1];
+ [attributesToSet setObject: [NSNumber numberWithUnsignedInt: 0755]
+ forKey: NSFilePosixPermissions];
+
+ locked = [mgr createDirectoryAtPath: _lockPath
+ withIntermediateDirectories: YES
+ attributes: attributesToSet
+ error: NULL];
+ if (NO == locked)
+ {
+ 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)
+ {
+ attributes = [mgr fileAttributesAtPath: _lockPath
+ traverseLink: YES];
+ if (attributes == nil)
+ {
+ [NSException raise: NSGenericException
+ format: @"Unable to get attributes of lock file we made at %@",
+ _lockPath];
+ }
+ ASSIGN(_lockTime, [attributes fileModificationDate]);
+ if (nil == _lockTime)
+ {
+ [NSException raise: NSGenericException
+ format: @"Unable to get date of lock file we made at %@",
+ _lockPath];
+ }
+ }
+ }
+ NS_HANDLER
+ {
+ [_localLock unlock];
+ [localException raise];
+ }
+ NS_ENDHANDLER
+ [_localLock unlock];
+ return locked;
}
/**
@@ -251,43 +291,53 @@
*/
- (void) unlock
{
- NSDictionary *attributes;
-
- if (_lockTime == nil)
- {
- [NSException raise: NSGenericException format: @"not locked by us"];
- }
-
- /*
- * Don't remove the lock if it has already been broken by someone
- * else and re-created. Unfortunately, there is a window between
- * testing and removing, but we do the bset we can.
- */
- attributes = [mgr fileAttributesAtPath: _lockPath traverseLink: YES];
- if (attributes == nil)
- {
+ [_localLock lock];
+ NS_DURING
+ {
+ NSDictionary *attributes;
+
+ if (_lockTime == nil)
+ {
+ [NSException raise: NSGenericException format: @"not locked by us"];
+ }
+
+ /* Don't remove the lock if it has already been broken by someone
+ * else and re-created. Unfortunately, there is a window between
+ * testing and removing, but we do the bset we can.
+ */
+ attributes = [mgr fileAttributesAtPath: _lockPath traverseLink: YES];
+ if (attributes == nil)
+ {
+ DESTROY(_lockTime);
+ [NSException raise: NSGenericException
+ format: @"lock '%@' already broken", _lockPath];
+ }
+ if ([_lockTime isEqual: [attributes fileModificationDate]])
+ {
+ DESTROY(_lockTime);
+ if ([mgr removeFileAtPath: _lockPath handler: nil] == NO)
+ {
+ [NSException raise: NSGenericException
+ format: @"Failed to remove lock directory '%@' - %@",
+ _lockPath, [NSError _last]];
+ }
+ }
+ else
+ {
+ DESTROY(_lockTime);
+ [NSException raise: NSGenericException
+ format: @"lock '%@' already broken and in use again",
+ _lockPath];
+ }
DESTROY(_lockTime);
- [NSException raise: NSGenericException
- format: @"lock '%@' already broken", _lockPath];
- }
- if ([_lockTime isEqual: [attributes fileModificationDate]])
- {
- DESTROY(_lockTime);
- if ([mgr removeFileAtPath: _lockPath handler: nil] == NO)
- {
- [NSException raise: NSGenericException
- format: @"Failed to remove lock directory '%@' - %@",
- _lockPath, [NSError _last]];
- }
- }
- else
- {
- DESTROY(_lockTime);
- [NSException raise: NSGenericException
- format: @"lock '%@' already broken and in use again",
- _lockPath];
- }
- DESTROY(_lockTime);
+ }
+ NS_HANDLER
+ {
+ [_localLock unlock];
+ [localException raise];
+ }
+ NS_ENDHANDLER
+ [_localLock unlock];
}
@end
_______________________________________________
Gnustep-cvs mailing list
[email protected]
https://mail.gna.org/listinfo/gnustep-cvs