tags 463416 + patch
thanks

On Tue, Mar 11, 2008 at 02:27:17AM +0200, Yavor Doganov wrote:
> I have the patch lying at work

Here it is.
2008-02-18  Richard Frith-Macdonald <[EMAIL PROTECTED]>

	* Source/NSMessagePortNameServer.m: Use locks to prevent two
	processes from interfering with each other.

Index: NSMessagePortNameServer.m
===================================================================
--- NSMessagePortNameServer.m	(revision 25483)
+++ NSMessagePortNameServer.m	(revision 26090)
@@ -29,6 +29,7 @@
 #include "Foundation/NSDebug.h"
 #include "Foundation/NSException.h"
 #include "Foundation/NSLock.h"
+#include "Foundation/NSDistributedLock.h"
 #include "Foundation/NSMapTable.h"
 #include "Foundation/NSPathUtilities.h"
 #include "Foundation/NSPort.h"
@@ -77,6 +78,7 @@
 
 
 @interface NSMessagePortNameServer (private)
++ (NSDistributedLock*) _fileLock;
 +(NSString *) _pathForName: (NSString *)name;
 @end
 
@@ -139,21 +141,77 @@
   return defaultServer;
 }
 
++ (NSDistributedLock*) _fileLock
+{
+  NSDistributedLock	*dl;
 
+  dl = [NSDistributedLock lockWithPath: [self _pathForName: nil]];
+  if ([dl tryLock] == NO)
+    {
+      NSDate	*limit = [NSDate dateWithTimeIntervalSinceNow: 2.0];
+
+      while (dl != nil && [dl tryLock] == NO)
+	{
+          CREATE_AUTORELEASE_POOL(pool);
+
+	  if ([limit timeIntervalSinceNow] > 0.0)
+	    {
+	      [NSThread sleepUntilDate:
+                [NSDate dateWithTimeIntervalSinceNow: 0.1]];
+	    }
+	  else
+	    {
+              if ([[dl lockDate] timeIntervalSinceNow] < -15.0)
+                {
+                  NS_DURING
+                    {
+                      [dl breakLock];
+                    }
+                  NS_HANDLER
+                    {
+                      NSLog(@"Failed to break lock on names for "
+                        @"NSMessagePortNameServer: %@", localException);
+                      dl = nil;
+                    }
+                  NS_ENDHANDLER
+                }
+              else
+                {
+                  NSLog(@"Failed to lock names for NSMessagePortNameServer");
+                  dl = nil;
+                }
+	    }
+          RELEASE(pool);
+	}
+    }
+  return dl;
+}
+
+/* Return the full path for the supplied port name or, if it's nil,
+ * the path for the distributed lock protecting all names.
+ */
 + (NSString *) _pathForName: (NSString *)name
 {
   static NSString	*base_path = nil;
   NSString		*path;
   NSData		*data;
 
+  if (name == nil)
+    {
+      name = @"lock";
+    }
+  else
+    {
   /*
    * Make sure name is representable as a filename ... assume base64 encoded
    * strings are valid on all filesystems.
    */
   data = [name dataUsingEncoding: NSUTF8StringEncoding];
   data = [GSMimeDocument encodeBase64: data];
-  name = [[NSString alloc] initWithData: data encoding: NSASCIIStringEncoding];
+      name = [[NSString alloc] initWithData: data
+				   encoding: NSASCIIStringEncoding];
   AUTORELEASE(name);
+    }
   [serverLock lock];
   if (!base_path)
     {
@@ -260,6 +318,7 @@
 - (NSPort*) portForName: (NSString *)name
 		 onHost: (NSString *)host
 {
+  NSDistributedLock	*dl;
   NSString	*path;
   FILE		*f;
   char		socket_path[512];
@@ -278,8 +337,14 @@
     }
 
   path = [[self class] _pathForName: name];
+  if ((dl = [[self class] _fileLock]) == nil)
+    {
+      [NSException raise: NSGenericException
+		  format: @"Failed to lock names for NSMessagePortNameServer"];
+    }
   if (![[self class] _livePort: path])
     {
+      [dl unlock];
       NSDebugLLog(@"NSMessagePort", @"not a live port");
       return nil;
     }
@@ -287,6 +352,7 @@
   f = fopen([path fileSystemRepresentation], "rt");
   if (!f)
     {
+      [dl unlock];
       NSDebugLLog(@"NSMessagePort", @"can't open file (%m)");
       return nil;
     }
@@ -296,6 +362,7 @@
   fclose(f);
 
   NSDebugLLog(@"NSMessagePort", @"got %s", socket_path);
+  [dl unlock];
 
   return [NSMessagePort _portWithName: (unsigned char*)socket_path
 			     listener: NO];
@@ -306,6 +373,7 @@
 {
   int			fd;
   unsigned char		buf[32];
+  NSDistributedLock	*dl;
   NSString		*path;
   const unsigned char	*socket_name;
   NSMutableArray	*a;
@@ -316,13 +384,17 @@
       [NSException raise: NSInvalidArgumentException
 		  format: @"Attempted to register a non-NSMessagePort (%@)",
 	port];
-      return NO;
     }
 
   path = [[self class] _pathForName: name];
-
+  if ((dl = [[self class] _fileLock]) == nil)
+    {
+      [NSException raise: NSGenericException
+		  format: @"Failed to lock names for NSMessagePortNameServer"];
+    }
   if ([[self class] _livePort: path])
     {
+      [dl unlock];
       NSDebugLLog(@"NSMessagePort", @"fail, is a live port (%@)", name);
       return NO;
     }
@@ -330,6 +402,7 @@
   fd = open([path fileSystemRepresentation], O_CREAT|O_EXCL|O_WRONLY, 0600);
   if (fd < 0)
     {
+      [dl unlock];
       NSDebugLLog(@"NSMessagePort", @"fail, can't open file (%@) for %@",
 	path, name);
       return NO;
@@ -355,17 +428,25 @@
 
   [a addObject: [name copy]];
   [serverLock unlock];
+  [dl unlock];
 
   return YES;
 }
 
 - (BOOL) removePortForName: (NSString *)name
 {
+  NSDistributedLock	*dl;
   NSString	*path;
 
   NSDebugLLog(@"NSMessagePort", @"removePortForName: %@", name);
   path = [[self class] _pathForName: name];
+  if ((dl = [[self class] _fileLock]) == nil)
+    {
+      [NSException raise: NSGenericException
+		  format: @"Failed to lock names for NSMessagePortNameServer"];
+    }
   unlink([path fileSystemRepresentation]);
+  [dl unlock];
   return YES;
 }
 
@@ -405,29 +486,36 @@
 {
   FILE			*f;
   char			socket_path[512];
+  NSDistributedLock	*dl;
   NSString		*path;
   const unsigned char	*port_path;
 
   NSDebugLLog(@"NSMessagePort", @"removePort: %@  forName: %@", port, name);
 
   path = [[self class] _pathForName: name];
-
+  if ((dl = [[self class] _fileLock]) == nil)
+    {
+      [NSException raise: NSGenericException
+		  format: @"Failed to lock names for NSMessagePortNameServer"];
+    }
   f = fopen([path fileSystemRepresentation], "rt");
   if (!f)
+    {
+      [dl unlock];
     return YES;
-
+    }
   fgets(socket_path, sizeof(socket_path), f);
-  if (strlen(socket_path) > 0) socket_path[strlen(socket_path) - 1] = 0;
-
+  if (strlen(socket_path) > 0)
+    {
+      socket_path[strlen(socket_path) - 1] = 0;
+    }
   fclose(f);
-
   port_path = [(NSMessagePort *)port _name];
-
   if (!strcmp((char*)socket_path, (char*)port_path))
     {
       unlink([path fileSystemRepresentation]);
     }
-
+  [dl unlock];
   return YES;
 }
 

Reply via email to