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 <r...@gnu.org>
 

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
Gnustep-cvs@gna.org
https://mail.gna.org/listinfo/gnustep-cvs

Reply via email to