NSPort cleanup and bugfixes.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@21936 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
CaS 2005-11-01 20:37:34 +00:00
parent 58f48e81e3
commit 96cbb52e59
7 changed files with 204 additions and 86 deletions

View file

@ -7,6 +7,15 @@
the new process tries to use the same name.
* Source/Additions/GSCategories.m: ([uuencodeInto:name:mode:]) fix
error encoding the termination marker of the uuencoded data.
* Headers/Foundation/NSPort.h: Declare missing category of NSObject
Remove some of the subclass stuff that should be private.
* Source/GSPortPrivate.h: Put private port stuff here ... needs
more to be moved out of NSPort.h
* Source/NSMessagePort.m: Hide instance variables. Use GSPortPrivate.h
Add bugfix for possible deadlock situation reported by Wim.
* Source/NSSocketPort.m: ditto
* Source/NSMessagePortNameServer.m: Use GSPortPrivate.h
* Source/NSPort.m: Implement missing informal protocol method.
2005-10-31 Richard Frith-Macdonald <rfm@gnu.org>

View file

@ -47,6 +47,14 @@
@class NSPortMessage;
@class NSHost;
@interface NSObject(NSPortDelegateMethods)
/**
* Subclasses of NSPort send this message to their delegate on receipt
* of a port message.
*/
- (void) handlePortMessage: (NSPortMessage*)aMessage;
@end
/**
* Exception raised by [NSPort], [NSConnection], and friends if sufficient
* time elapses while waiting for a response, or if the receiving port is
@ -175,8 +183,6 @@ GS_EXPORT NSString* const NSPortDidBecomeInvalidNotification;
*/
typedef SOCKET NSSocketNativeHandle;
@class GSTcpHandle;
/**
* <p>An [NSPort] implementation for network object communications based on
* BSD sockets. Can be used for interthread/interprocess
@ -223,11 +229,6 @@ typedef SOCKET NSSocketNativeHandle;
forceAddress: (NSString*)addr
listener: (BOOL)shouldListen;
/**
* Setup method: add new send or receive connection handle.
*/
- (void) addHandle: (GSTcpHandle*)handle forSend: (BOOL)send;
/**
* Returns IP address of underlying socket.
*/
@ -239,12 +240,6 @@ typedef SOCKET NSSocketNativeHandle;
*/
- (void) getFds: (int*)fds count: (int*)count;
/**
*
*/
- (GSTcpHandle*) handleForPort: (NSSocketPort*)recvPort
beforeDate: (NSDate*)when;
/**
* Delegates processing of a message.
*/
@ -260,14 +255,6 @@ typedef SOCKET NSSocketNativeHandle;
*/
- (gsu16) portNumber;
/**
* This is called when a TCP/IP socket connection is broken. We remove the
* connection handle from this port and, if this was the last handle to a
* remote port, we invalidate the port.
*/
- (void) removeHandle: (GSTcpHandle*)handle;
// This is the OS X interface
/*
{
@ -304,54 +291,15 @@ typedef SOCKET NSSocketNativeHandle;
@end
@class GSMessageHandle;
/**
* An [NSPort] implementation for network object communications based on
* Unix domain sockets. Can be used for interthread/interprocess
* communications on the same host, but not between different hosts.
* An [NSPort] implementation for network object communications
* which can be used for interthread/interprocess communications
* on the same host, but not between different hosts.
*/
@interface NSMessagePort : NSPort <GCFinalization>
{
NSData *name;
NSRecursiveLock *myLock;
NSMapTable *handles; /* Handles indexed by socket. */
int listener; /* Descriptor to listen on. */
#if defined(__MINGW32__)
WSAEVENT eventListener;
NSMapTable *events;
#endif
void *_internal;
}
- (int) _listener;
- (const unsigned char *) _name;
/**
* <init/>
* This is the preferred initialisation method for <code>NSMessagePort</code>.
*
* socketName is the name of the socket in the port directory
*/
+ (NSMessagePort*) _portWithName: (const unsigned char *)socketName
listener: (BOOL)shouldListen;
/**
* Setup method: add new send or receive connection handle.
*/
- (void) addHandle: (GSMessageHandle*)handle forSend: (BOOL)send;
/**
* This is called when a socket connection is broken. We remove the
* connection handle from this port and, if this was the last handle to a
* remote port, we invalidate the port.
*/
- (void) removeHandle: (GSMessageHandle*)handle;
/**
* Delegates processing of a message.
*/
- (void) handlePortMessage: (NSPortMessage*)m;
@end

48
Source/GSPortPrivate.h Normal file
View file

@ -0,0 +1,48 @@
/* GSPortPrivate
Copyright (C) 2005 Free Software Foundation, Inc.
Written by: Richard Frith-Macdonald <rfm@gnu.org>
This file is part of the GNUstep Base Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
*/
#ifndef __GSPortPrivate_h_
#define __GSPortPrivate_h_
@class GSMessageHandle;
@interface NSMessagePort(Private)
- (int) _listener;
- (const unsigned char *) _name;
+ (NSMessagePort*) _portWithName: (const unsigned char *)socketName
listener: (BOOL)shouldListen;
- (void) addHandle: (GSMessageHandle*)handle forSend: (BOOL)send;
- (void) removeHandle: (GSMessageHandle*)handle;
@end
@class GSTcpHandle;
@interface NSSocketPort (Private)
- (void) addHandle: (GSTcpHandle*)handle forSend: (BOOL)send;
- (GSTcpHandle*) handleForPort: (NSSocketPort*)recvPort
beforeDate: (NSDate*)when;
- (void) removeHandle: (GSTcpHandle*)handle;
@end
#endif

View file

@ -42,6 +42,9 @@
#include "Foundation/NSValue.h"
#include "Foundation/NSFileManager.h"
#include "Foundation/NSProcessInfo.h"
#include "GSPortPrivate.h"
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
@ -124,6 +127,7 @@ static gsu32 maxDataLength = 10 * 1024 * 1024;
/* Private interfaces */
/*
* The GSPortItemType constant is used to identify the type of data in
* each packet read. All data transmitted is in a packet, each packet
@ -399,6 +403,14 @@ static Class runLoopClass;
type: ET_EDESC
watcher: self
forMode: NSConnectionReplyMode];
[l addEvent: (void*)(gsaddr)desc
type: ET_WDESC
watcher: self
forMode: NSDefaultRunLoopMode];
[l addEvent: (void*)(gsaddr)desc
type: ET_EDESC
watcher: self
forMode: NSDefaultRunLoopMode];
while (valid == YES && state == GS_H_TRYCON
&& [when timeIntervalSinceNow] > 0)
@ -414,6 +426,14 @@ static Class runLoopClass;
type: ET_EDESC
forMode: NSConnectionReplyMode
all: NO];
[l removeEvent: (void*)(gsaddr)desc
type: ET_WDESC
forMode: NSDefaultRunLoopMode
all: NO];
[l removeEvent: (void*)(gsaddr)desc
type: ET_EDESC
forMode: NSDefaultRunLoopMode
all: NO];
if (state == GS_H_TRYCON)
{
@ -1014,6 +1034,14 @@ static Class runLoopClass;
type: ET_EDESC
watcher: self
forMode: NSConnectionReplyMode];
[l addEvent: (void*)(gsaddr)desc
type: ET_WDESC
watcher: self
forMode: NSDefaultRunLoopMode];
[l addEvent: (void*)(gsaddr)desc
type: ET_EDESC
watcher: self
forMode: NSDefaultRunLoopMode];
while (valid == YES
&& [wMsgs indexOfObjectIdenticalTo: components] != NSNotFound
@ -1032,6 +1060,14 @@ static Class runLoopClass;
type: ET_EDESC
forMode: NSConnectionReplyMode
all: NO];
[l removeEvent: (void*)(gsaddr)desc
type: ET_WDESC
forMode: NSDefaultRunLoopMode
all: NO];
[l removeEvent: (void*)(gsaddr)desc
type: ET_EDESC
forMode: NSDefaultRunLoopMode
all: NO];
if ([wMsgs indexOfObjectIdenticalTo: components] == NSNotFound)
{
@ -1088,6 +1124,17 @@ static Class runLoopClass;
@implementation NSMessagePort
typedef struct {
NSData *_name;
NSRecursiveLock *_myLock;
NSMapTable *_handles; /* Handles indexed by socket. */
int _listener; /* Descriptor to listen on. */
} internal;
#define name ((internal*)_internal)->_name
#define myLock ((internal*)_internal)->_myLock
#define handles ((internal*)_internal)->_handles
#define lDesc ((internal*)_internal)->_listener
static NSRecursiveLock *messagePortLock = nil;
/*
@ -1100,16 +1147,16 @@ static Class messagePortClass;
static void clean_up_sockets(void)
{
NSMessagePort *port;
NSData *name;
NSData *data;
NSMapEnumerator mEnum;
BOOL unknownThread = GSRegisterCurrentThread();
CREATE_AUTORELEASE_POOL(arp);
mEnum = NSEnumerateMapTable(messagePortMap);
while (NSNextMapEnumeratorPair(&mEnum, (void *)&name, (void *)&port))
while (NSNextMapEnumeratorPair(&mEnum, (void *)&data, (void *)&port))
{
if ([port _listener] != -1)
unlink([name bytes]);
unlink([data bytes]);
}
NSEndMapTableEnumeration(&mEnum);
DESTROY(arp);
@ -1142,7 +1189,7 @@ static unsigned wordAlign;
+ (id) new
{
static int unique_index = 0;
static int unique_index = 0;
NSString *path;
NSNumber *p = [NSNumber numberWithInt: 0700];
NSDictionary *attr;
@ -1195,11 +1242,14 @@ static int unique_index = 0;
if (port == nil)
{
port = (NSMessagePort*)NSAllocateObject(self, 0, NSDefaultMallocZone());
port->name = theName;
port->listener = -1;
port->handles = NSCreateMapTable(NSIntMapKeyCallBacks,
port->_internal = (internal*)NSZoneMalloc(NSDefaultMallocZone(),
sizeof(internal));
((internal*)(port->_internal))->_name = theName;
((internal*)(port->_internal))->_listener = -1;
((internal*)(port->_internal))->_handles
= NSCreateMapTable(NSIntMapKeyCallBacks,
NSObjectMapValueCallBacks, 0);
port->myLock = [GSLazyRecursiveLock new];
((internal*)(port->_internal))->_myLock = [GSLazyRecursiveLock new];
port->_is_valid = YES;
if (shouldListen == YES)
@ -1281,7 +1331,7 @@ static int unique_index = 0;
* number (which will have been set to a real port number when
* we did the 'bind' call.
*/
port->listener = desc;
((internal*)port->_internal)->_listener = desc;
/*
* Make sure we have the map table for this port.
*/
@ -1337,7 +1387,11 @@ static int unique_index = 0;
- (void) dealloc
{
[self gcFinalize];
DESTROY(name);
if (_internal != 0)
{
DESTROY(name);
NSZoneFree(NSDefaultMallocZone(), _internal);
}
[super dealloc];
}
@ -1379,9 +1433,9 @@ static int unique_index = 0;
* Put in our listening socket.
*/
*count = 0;
if (listener >= 0)
if (lDesc >= 0)
{
fds[(*count)++] = listener;
fds[(*count)++] = lDesc;
}
/*
@ -1543,11 +1597,11 @@ static int unique_index = 0;
unsigned i;
M_LOCK(messagePortLock);
if (listener >= 0)
if (lDesc >= 0)
{
(void) close(listener);
(void) close(lDesc);
unlink([name bytes]);
listener = -1;
lDesc = -1;
}
NSMapRemove(messagePortMap, (void*)name);
M_UNLOCK(messagePortLock);
@ -1590,7 +1644,7 @@ static int unique_index = 0;
{
NSMessagePort *o = (NSMessagePort*)anObject;
return [o->name isEqual: name];
return [((internal*)o->_internal)->_name isEqual: name];
}
return NO;
}
@ -1603,12 +1657,12 @@ static int unique_index = 0;
int desc = (int)(gsaddr)extra;
GSMessageHandle *handle;
if (desc == listener)
if (desc == lDesc)
{
struct sockaddr_un sockAddr;
unsigned size = sizeof(sockAddr);
desc = accept(listener, (struct sockaddr*)&sockAddr, &size);
desc = accept(lDesc, (struct sockaddr*)&sockAddr, &size);
if (desc < 0)
{
NSDebugMLLog(@"NSMessagePort",
@ -1683,7 +1737,7 @@ static int unique_index = 0;
handle->recvPort = nil;
}
NSMapRemove(handles, (void*)(gsaddr)[handle descriptor]);
if (listener < 0 && NSCountMapTable(handles) == 0)
if (lDesc < 0 && NSCountMapTable(handles) == 0)
{
[self invalidate];
}
@ -1894,14 +1948,14 @@ static int unique_index = 0;
}
-(const unsigned char *) _name
- (const unsigned char *) _name
{
return [name bytes];
}
-(int) _listener
- (int) _listener
{
return listener;
return lDesc;
}
@end

View file

@ -35,6 +35,8 @@
#include "Foundation/NSValue.h"
#include "Foundation/NSThread.h"
#include "GSPortPrivate.h"
#include <sys/stat.h>
#include <unistd.h>
#include <signal.h>

View file

@ -39,6 +39,12 @@
@class NSMessagePort;
@implementation NSObject(NSPortDelegateMethods)
- (void) handlePortMessage: (NSPortMessage*)aMessage
{
}
@end
@implementation NSPort
/**

View file

@ -41,6 +41,9 @@
#include "Foundation/NSThread.h"
#include "Foundation/NSConnection.h"
#include "Foundation/NSDebug.h"
#include "GSPortPrivate.h"
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
@ -570,6 +573,10 @@ static Class runLoopClass;
type: ET_HANDLE
watcher: self
forMode: NSConnectionReplyMode];
[l addEvent: (void*)(gsaddr)event
type: ET_HANDLE
watcher: self
forMode: NSDefaultRunLoopMode];
inReplyMode = YES;
#else
[l addEvent: (void*)(gsaddr)desc
@ -580,6 +587,14 @@ static Class runLoopClass;
type: ET_EDESC
watcher: self
forMode: NSConnectionReplyMode];
[l addEvent: (void*)(gsaddr)desc
type: ET_WDESC
watcher: self
forMode: NSDefaultRunLoopMode];
[l addEvent: (void*)(gsaddr)desc
type: ET_EDESC
watcher: self
forMode: NSDefaultRunLoopMode];
#endif
while (valid == YES && state == GS_H_TRYCON
@ -595,6 +610,10 @@ static Class runLoopClass;
type: ET_HANDLE
forMode: NSConnectionReplyMode
all: NO];
[l removeEvent: (void*)(gsaddr)event
type: ET_HANDLE
forMode: NSDefaultRunLoopMode
all: NO];
inReplyMode = NO;
#else
[l removeEvent: (void*)(gsaddr)desc
@ -605,6 +624,14 @@ static Class runLoopClass;
type: ET_EDESC
forMode: NSConnectionReplyMode
all: NO];
[l removeEvent: (void*)(gsaddr)desc
type: ET_WDESC
forMode: NSDefaultRunLoopMode
all: NO];
[l removeEvent: (void*)(gsaddr)desc
type: ET_EDESC
forMode: NSDefaultRunLoopMode
all: NO];
#endif
if (state == GS_H_TRYCON)
@ -1330,6 +1357,10 @@ static Class runLoopClass;
type: ET_HANDLE
watcher: self
forMode: NSConnectionReplyMode];
[l addEvent: (void*)(gsaddr)event
type: ET_HANDLE
watcher: self
forMode: NSDefaultRunLoopMode];
inReplyMode = YES;
#else
[l addEvent: (void*)(gsaddr)desc
@ -1340,6 +1371,14 @@ static Class runLoopClass;
type: ET_EDESC
watcher: self
forMode: NSConnectionReplyMode];
[l addEvent: (void*)(gsaddr)desc
type: ET_WDESC
watcher: self
forMode: NSDefaultRunLoopMode];
[l addEvent: (void*)(gsaddr)desc
type: ET_EDESC
watcher: self
forMode: NSDefaultRunLoopMode];
#endif
while (valid == YES
@ -1367,6 +1406,10 @@ static Class runLoopClass;
type: ET_HANDLE
forMode: NSConnectionReplyMode
all: NO];
[l removeEvent: (void*)(gsaddr)event
type: ET_HANDLE
forMode: NSDefaultRunLoopMode
all: NO];
inReplyMode = NO;
#else
[l removeEvent: (void*)(gsaddr)desc
@ -1377,6 +1420,14 @@ static Class runLoopClass;
type: ET_EDESC
forMode: NSConnectionReplyMode
all: NO];
[l removeEvent: (void*)(gsaddr)desc
type: ET_WDESC
forMode: NSDefaultRunLoopMode
all: NO];
[l removeEvent: (void*)(gsaddr)desc
type: ET_EDESC
forMode: NSDefaultRunLoopMode
all: NO];
#endif
if ([wMsgs indexOfObjectIdenticalTo: components] == NSNotFound)