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;
}