mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-01 20:40:53 +00:00
Fix for processes interfering with eath others changes to names and ports.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/branches/stable@26090 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
cc93ad9017
commit
e6a6d04987
2 changed files with 120 additions and 27 deletions
|
@ -1,3 +1,8 @@
|
||||||
|
2008-02-18 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
* Source/NSMessagePortNameServer.m: Use locks to prevent two
|
||||||
|
processes from interfering with each other.
|
||||||
|
|
||||||
2008-02-14 Richard Frith-Macdonald <rfm@gnu.org>
|
2008-02-14 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
* Source/GSHTTPURLHandle.m: Remove self as observer of socket
|
* Source/GSHTTPURLHandle.m: Remove self as observer of socket
|
||||||
|
|
|
@ -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,7 +78,8 @@ static NSMapTable portToNamesMap;
|
||||||
|
|
||||||
|
|
||||||
@interface NSMessagePortNameServer (private)
|
@interface NSMessagePortNameServer (private)
|
||||||
+(NSString *) _pathForName: (NSString *)name;
|
+ (NSDistributedLock*) _fileLock;
|
||||||
|
+ (NSString *) _pathForName: (NSString *)name;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@ -139,21 +141,77 @@ 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 != 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
|
+ (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)
|
||||||
|
{
|
||||||
|
name = @"lock";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* Make sure name is representable as a filename ... assume base64 encoded
|
* Make sure name is representable as a filename ... assume base64 encoded
|
||||||
* strings are valid on all filesystems.
|
* strings are valid on all filesystems.
|
||||||
*/
|
*/
|
||||||
data = [name dataUsingEncoding: NSUTF8StringEncoding];
|
data = [name dataUsingEncoding: NSUTF8StringEncoding];
|
||||||
data = [GSMimeDocument encodeBase64: data];
|
data = [GSMimeDocument encodeBase64: data];
|
||||||
name = [[NSString alloc] initWithData: data encoding: NSASCIIStringEncoding];
|
name = [[NSString alloc] initWithData: data
|
||||||
|
encoding: NSASCIIStringEncoding];
|
||||||
AUTORELEASE(name);
|
AUTORELEASE(name);
|
||||||
|
}
|
||||||
[serverLock lock];
|
[serverLock lock];
|
||||||
if (!base_path)
|
if (!base_path)
|
||||||
{
|
{
|
||||||
|
@ -260,6 +318,7 @@ static void clean_up_names(void)
|
||||||
- (NSPort*) portForName: (NSString *)name
|
- (NSPort*) portForName: (NSString *)name
|
||||||
onHost: (NSString *)host
|
onHost: (NSString *)host
|
||||||
{
|
{
|
||||||
|
NSDistributedLock *dl;
|
||||||
NSString *path;
|
NSString *path;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
char socket_path[512];
|
char socket_path[512];
|
||||||
|
@ -278,8 +337,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 +352,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 +362,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 +373,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 +384,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 +402,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 +428,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
|
||||||
{
|
{
|
||||||
|
NSDistributedLock *dl;
|
||||||
NSString *path;
|
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 +486,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)
|
||||||
|
{
|
||||||
|
[dl unlock];
|
||||||
return YES;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue