Lock names directory.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@26088 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
rfm 2008-02-18 12:31:23 +00:00
parent f2528f2c9f
commit 4a65b59dc6
3 changed files with 99 additions and 28 deletions

View file

@ -1,11 +1,13 @@
2008-02-17 Richard Frith-Macdonald <rfm@gnu.org> 2008-02-17 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSDistributedNotificationCenter.m: Remove delay and change * Source/NSDistributedNotificationCenter.m: Remove delay and change
code to immediately release resources used while trying to conneect code to immediately release resources used while trying to connect
to server. to server.
* Source/NSConnection.m: When creating a connection and getting its * Source/NSConnection.m: When creating a connection and getting its
proxy, release the connection immediately if the proxy is nil, so proxy, release the connection immediately if the proxy is nil, so
that repeated calls don't use more resources. that repeated calls don't use more resources.
* Source/NSMessagePortNameServer.m: Implement distributed locking
of names directory.
* Source/NSNSAutoreleasePool.m: When emptying pool, add diagnostic * Source/NSNSAutoreleasePool.m: When emptying pool, add diagnostic
message and exceptions where an object we are releasing is bad in message and exceptions where an object we are releasing is bad in
some way. some way.

View file

@ -29,6 +29,7 @@
#include "Foundation/NSDebug.h" #include "Foundation/NSDebug.h"
#include "Foundation/NSException.h" #include "Foundation/NSException.h"
#include "Foundation/NSLock.h" #include "Foundation/NSLock.h"
#include "Foundation/NSDistributedLock.h"
#include "Foundation/NSMapTable.h" #include "Foundation/NSMapTable.h"
#include "Foundation/NSPathUtilities.h" #include "Foundation/NSPathUtilities.h"
#include "Foundation/NSPort.h" #include "Foundation/NSPort.h"
@ -77,16 +78,17 @@ static NSMapTable portToNamesMap;
@interface NSMessagePortNameServer (private) @interface NSMessagePortNameServer (private)
+(NSString *) _pathForName: (NSString *)name; + (NSDistributedLock*) _fileLock;
+ (NSString *) _pathForName: (NSString *)name;
@end @end
static void clean_up_names(void) static void clean_up_names(void)
{ {
NSMapEnumerator mEnum; NSMapEnumerator mEnum;
NSMessagePort *port; NSMessagePort *port;
NSString *name; NSString *name;
BOOL unknownThread = GSRegisterCurrentThread(); BOOL unknownThread = GSRegisterCurrentThread();
CREATE_AUTORELEASE_POOL(arp); CREATE_AUTORELEASE_POOL(arp);
mEnum = NSEnumerateMapTable(portToNamesMap); mEnum = NSEnumerateMapTable(portToNamesMap);
@ -139,21 +141,56 @@ static void clean_up_names(void)
return defaultServer; return defaultServer;
} }
+ (NSDistributedLock*) _fileLock
{
NSDistributedLock *dl;
dl = [NSDistributedLock lockWithPath: [self _pathForName: nil]];
if ([dl tryLock] == NO)
{
NSDate *limit = [NSDate dateWithTimeIntervalSinceNow: 2.0];
while ([dl tryLock] == NO)
{
if ([limit timeIntervalSinceNow] > 0.0)
{
[NSThread sleepForTimeInterval: 0.1];
}
else
{
NSLog(@"Failed to lock names for NSMessagePortNameServer");
return nil;
}
}
}
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 + (NSString *) _pathForName: (NSString *)name
{ {
static NSString *base_path = nil; static NSString *base_path = nil;
NSString *path; NSString *path;
NSData *data; NSData *data;
/* if (name == nil)
* Make sure name is representable as a filename ... assume base64 encoded {
* strings are valid on all filesystems. name = @"lock";
*/ }
data = [name dataUsingEncoding: NSUTF8StringEncoding]; else
data = [GSMimeDocument encodeBase64: data]; {
name = [[NSString alloc] initWithData: data encoding: NSASCIIStringEncoding]; /*
AUTORELEASE(name); * 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];
AUTORELEASE(name);
}
[serverLock lock]; [serverLock lock];
if (!base_path) if (!base_path)
{ {
@ -260,9 +297,10 @@ static void clean_up_names(void)
- (NSPort*) portForName: (NSString *)name - (NSPort*) portForName: (NSString *)name
onHost: (NSString *)host onHost: (NSString *)host
{ {
NSString *path; NSDistributedLock *dl;
FILE *f; NSString *path;
char socket_path[512]; FILE *f;
char socket_path[512];
NSDebugLLog(@"NSMessagePort", @"portForName: %@ host: %@", name, host); NSDebugLLog(@"NSMessagePort", @"portForName: %@ host: %@", name, host);
@ -278,8 +316,14 @@ static void clean_up_names(void)
} }
path = [[self class] _pathForName: name]; 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]) if (![[self class] _livePort: path])
{ {
[dl unlock];
NSDebugLLog(@"NSMessagePort", @"not a live port"); NSDebugLLog(@"NSMessagePort", @"not a live port");
return nil; return nil;
} }
@ -287,6 +331,7 @@ static void clean_up_names(void)
f = fopen([path fileSystemRepresentation], "rt"); f = fopen([path fileSystemRepresentation], "rt");
if (!f) if (!f)
{ {
[dl unlock];
NSDebugLLog(@"NSMessagePort", @"can't open file (%m)"); NSDebugLLog(@"NSMessagePort", @"can't open file (%m)");
return nil; return nil;
} }
@ -296,6 +341,7 @@ static void clean_up_names(void)
fclose(f); fclose(f);
NSDebugLLog(@"NSMessagePort", @"got %s", socket_path); NSDebugLLog(@"NSMessagePort", @"got %s", socket_path);
[dl unlock];
return [NSMessagePort _portWithName: (unsigned char*)socket_path return [NSMessagePort _portWithName: (unsigned char*)socket_path
listener: NO]; listener: NO];
@ -306,6 +352,7 @@ static void clean_up_names(void)
{ {
int fd; int fd;
unsigned char buf[32]; unsigned char buf[32];
NSDistributedLock *dl;
NSString *path; NSString *path;
const unsigned char *socket_name; const unsigned char *socket_name;
NSMutableArray *a; NSMutableArray *a;
@ -316,13 +363,17 @@ static void clean_up_names(void)
[NSException raise: NSInvalidArgumentException [NSException raise: NSInvalidArgumentException
format: @"Attempted to register a non-NSMessagePort (%@)", format: @"Attempted to register a non-NSMessagePort (%@)",
port]; port];
return NO;
} }
path = [[self class] _pathForName: name]; 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]) if ([[self class] _livePort: path])
{ {
[dl unlock];
NSDebugLLog(@"NSMessagePort", @"fail, is a live port (%@)", name); NSDebugLLog(@"NSMessagePort", @"fail, is a live port (%@)", name);
return NO; return NO;
} }
@ -330,6 +381,7 @@ static void clean_up_names(void)
fd = open([path fileSystemRepresentation], O_CREAT|O_EXCL|O_WRONLY, 0600); fd = open([path fileSystemRepresentation], O_CREAT|O_EXCL|O_WRONLY, 0600);
if (fd < 0) if (fd < 0)
{ {
[dl unlock];
NSDebugLLog(@"NSMessagePort", @"fail, can't open file (%@) for %@", NSDebugLLog(@"NSMessagePort", @"fail, can't open file (%@) for %@",
path, name); path, name);
return NO; return NO;
@ -355,17 +407,25 @@ static void clean_up_names(void)
[a addObject: [name copy]]; [a addObject: [name copy]];
[serverLock unlock]; [serverLock unlock];
[dl unlock];
return YES; return YES;
} }
- (BOOL) removePortForName: (NSString *)name - (BOOL) removePortForName: (NSString *)name
{ {
NSString *path; NSDistributedLock *dl;
NSString *path;
NSDebugLLog(@"NSMessagePort", @"removePortForName: %@", name); NSDebugLLog(@"NSMessagePort", @"removePortForName: %@", name);
path = [[self class] _pathForName: 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]); unlink([path fileSystemRepresentation]);
[dl unlock];
return YES; return YES;
} }
@ -405,29 +465,36 @@ static void clean_up_names(void)
{ {
FILE *f; FILE *f;
char socket_path[512]; char socket_path[512];
NSDistributedLock *dl;
NSString *path; NSString *path;
const unsigned char *port_path; const unsigned char *port_path;
NSDebugLLog(@"NSMessagePort", @"removePort: %@ forName: %@", port, name); NSDebugLLog(@"NSMessagePort", @"removePort: %@ forName: %@", port, name);
path = [[self class] _pathForName: 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"); f = fopen([path fileSystemRepresentation], "rt");
if (!f) if (!f)
return YES; {
[dl unlock];
return YES;
}
fgets(socket_path, sizeof(socket_path), f); 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); fclose(f);
port_path = [(NSMessagePort *)port _name]; port_path = [(NSMessagePort *)port _name];
if (!strcmp((char*)socket_path, (char*)port_path)) if (!strcmp((char*)socket_path, (char*)port_path))
{ {
unlink([path fileSystemRepresentation]); unlink([path fileSystemRepresentation]);
} }
[dl unlock];
return YES; return YES;
} }

View file

@ -472,6 +472,7 @@ ihandler(int sig)
name = [service stringByAppendingFormat: @"-%@", name]; name = [service stringByAppendingFormat: @"-%@", name];
if ([ns registerPort: port forName: name] == NO) if ([ns registerPort: port forName: name] == NO)
{ {
NSLog(@"gdnc - failed to register as %@", name);
} }
} }
a = [host addresses]; a = [host addresses];
@ -483,6 +484,7 @@ ihandler(int sig)
name = [service stringByAppendingFormat: @"-%@", name]; name = [service stringByAppendingFormat: @"-%@", name];
if ([ns registerPort: port forName: name] == NO) if ([ns registerPort: port forName: name] == NO)
{ {
NSLog(@"gdnc - failed to register as %@", name);
} }
} }
} }