DO patch from Richard Frith-MacDonald <richard@brainstorm.co.uk>

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@2410 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Adam Fedor 1997-09-09 15:30:24 +00:00
parent 4d6732922c
commit 79c7545d62
9 changed files with 384 additions and 149 deletions

View file

@ -1,3 +1,31 @@
Tue Sep 9 10:15:00 1997 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* src/NSConnection.m: Made numerous changes to fix memory leak with
ports never being released and to fix problems in port invalidation
associated with that. Also added code to cope with odd cases like
when a remote application dires while we are waiting for a response
from it.
* src/NSPort.m: Added [-release] method which ensures that ports
are invlidated before they are finally deallocated.
* src/NSPortCoder.m: Catch exceptions during attempt to write data.
* src/NSRunLoop.m: Fixed this so that a count is kept of the
number of times a port has been added to the run loop as per the
OPENSTEP documentation.
* src/TcpPort.m: Fixed a minor retain/release problem.
* src/UnixFileHandle.m: Added loads of checks so that attempts to
use a file handle which has been closed will fail/generate an exception
rather than crashing things! Also modified for changes to NSRunLoop.
* src/include/NSRunLoop.h: Modified the interface for adding watchers
for events with a count of the number of times they have been added.
* src/include/Port.h: Removed [-isValid] - now in NSPort.
Tue Aug 26 15:47:54 1997 Adam Fedor <fedor@doc.com>
* src/NSCTemplateValue.m ([NSCTemplateValue -description]): New

View file

@ -143,7 +143,12 @@ typedef enum {
/*
* These next two are general purpose methods for letting objects
* ask the runloop to watch for events for them. Only one object
* at a time may be watching for a particular event in a mode.
* at a time may be watching for a particular event in a mode, but
* that object may add itsself as a watcher many times as long as
* each addition is matched by a removal (the run loop keeps count).
* Alternatively, the 'removeAll' parameter may be set to 'YES' for
* [-removeEvent:type:forMode:all:] in order to remove the watcher
* irrespective of the number of times it has been added.
*/
- (void) addEvent: (void*)data
type: (RunLoopEventType)type
@ -151,7 +156,8 @@ typedef enum {
forMode: (NSString*)mode;
- (void) removeEvent: (void*)data
type: (RunLoopEventType)type
forMode: (NSString*)mode;
forMode: (NSString*)mode
all: (BOOL)removeAll;
/*
* The next four methods are rendered obsolete by
* [-addEvent:type:watcher:forMode:] and

View file

@ -40,7 +40,6 @@
{
}
- (void) invalidate;
- (BOOL) isValid;
- (void) close;
+ (Class) outPacketClass;

View file

@ -278,9 +278,10 @@ static int messages_received_count;
+ new
{
id newPort = [default_receive_port_class newForReceiving];
id newConn =
[NSConnection newForInPort:newPort outPort:nil ancestorConnection:nil];
id newPort = [[default_receive_port_class newForReceiving] autorelease];
id newConn = [NSConnection newForInPort:newPort
outPort:nil
ancestorConnection:nil];
return newConn;
}
@ -291,7 +292,7 @@ static int messages_received_count;
if (p == nil) {
return nil;
}
return [self rootProxyAtPort: p];
return [self rootProxyAtPort: [p autorelease]];
}
- (void) addRequestMode: (NSString*)mode
@ -308,14 +309,24 @@ static int messages_received_count;
if (debug_connection)
printf("deallocating 0x%x\n", (unsigned)self);
[self invalidate];
/* Remove rootObject from root_object_dictionary
if this is last connection */
if (![NSConnection connectionsCountWithInPort:receive_port])
[NSConnection setRootObject:nil forInPort:receive_port];
[NotificationDispatcher removeObserver: self];
/* Remove receive port from run loop. */
[self setRequestMode: nil];
[[NSRunLoop currentRunLoop] removePort: receive_port
forMode: NSConnectionReplyMode];
[request_modes release];
/* Finished with ports - releasing them may generate a notification */
[receive_port release];
[send_port release];
[request_modes release];
/* Don't need notifications any more - so remove self as observer. */
[NotificationDispatcher removeObserver: self];
[proxiesHashGate lock];
NSFreeMapTable (remote_proxies);
@ -339,9 +350,10 @@ static int messages_received_count;
- (id) init
{
id newPort = [default_receive_port_class newForReceiving];
id newConn =
[NSConnection newForInPort:newPort outPort:nil ancestorConnection:nil];
id newPort = [[default_receive_port_class newForReceiving] autorelease];
id newConn = [NSConnection newForInPort:newPort
outPort:nil
ancestorConnection:nil];
[self release];
return newConn;
}
@ -365,6 +377,12 @@ static int messages_received_count;
{
is_valid = 0;
/*
* We can't be the ancestor of anything if we are invalid.
*/
if (self == NSMapGet(receive_port_2_ancestor, receive_port))
NSMapRemove(receive_port_2_ancestor, receive_port);
/*
* If we have been invalidated, we don't need to retain proxies
* for local objects any more. In fact, we want to get rid of
@ -515,7 +533,7 @@ static int messages_received_count;
while ([request_modes count]>1) {
[self removeRequestMode:[request_modes objectAtIndex:1]];
}
if ([request_modes count] == 0) {
if (mode != nil && [request_modes count] == 0) {
[self addRequestMode:mode];
}
}
@ -667,7 +685,7 @@ static int messages_received_count;
id newPort;
id newConn;
newPort = [default_receive_port_class newForReceiving];
newPort = [[default_receive_port_class newForReceiving] autorelease];
newConn = [self newForInPort:newPort outPort:nil
ancestorConnection:nil];
[self setRootObject:anObj forInPort:newPort];
@ -687,8 +705,9 @@ static int messages_received_count;
id newConn;
newPort = [default_receive_port_class newForReceivingFromRegisteredName: n];
newConn = [self newForInPort:newPort outPort:nil
ancestorConnection:nil];
newConn = [self newForInPort:[newPort autorelease]
outPort:nil
ancestorConnection:nil];
[self setRootObject:anObj forInPort:newPort];
return newConn;
}
@ -706,10 +725,12 @@ static int messages_received_count;
+ (NSDistantObject*) rootProxyAtPort: (NSPort*)anOutPort
{
id newInPort = [default_receive_port_class newForReceiving];
return [self rootProxyAtPort: anOutPort withInPort: newInPort];
return [self rootProxyAtPort: anOutPort
withInPort: [newInPort autorelease]];
}
+ (NSDistantObject*) rootProxyAtPort: (NSPort*)anOutPort withInPort: (NSPort *)anInPort
+ (NSDistantObject*) rootProxyAtPort: (NSPort*)anOutPort
withInPort: (NSPort *)anInPort
{
NSConnection *newConn = [self newForInPort:anInPort
outPort:anOutPort
@ -809,10 +830,6 @@ static int messages_received_count;
if (!(ancestor = NSMapGet (receive_port_2_ancestor, ip)))
{
NSMapInsert (receive_port_2_ancestor, ip, newConn);
[[NSRunLoop currentRunLoop] addPort: (NSPort*)ip
forMode: NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] addPort: (NSPort*)ip
forMode: NSConnectionReplyMode];
/* This will cause the connection with the registered name
to receive the -invokeWithObject: from the IN_PORT.
This ends up being the ancestor of future new NSConnections
@ -837,8 +854,16 @@ static int messages_received_count;
newConn->independant_queueing = NO;
newConn->reply_depth = 0;
newConn->delegate = nil;
/*
* Set up request modes array and make sure the receiving port is
* added to the run loop to get data.
*/
newConn->request_modes = [[NSMutableArray arrayWithObject:
NSDefaultRunLoopMode] retain];
[[NSRunLoop currentRunLoop] addPort: (NSPort*)ip
forMode: NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] addPort: (NSPort*)ip
forMode: NSConnectionReplyMode];
/* Ssk the delegate for permission, (OpenStep-style and GNUstep-style). */
@ -967,6 +992,7 @@ static int messages_received_count;
int seq_num;
NSParameterAssert (is_valid);
[[self retain] autorelease];
op = [self newSendingRequestRmc];
seq_num = [op sequenceNumber];
@ -1018,6 +1044,11 @@ static int messages_received_count;
/* If we didn't get the reply packet yet, get it now. */
if (!ip)
{
if (!is_valid)
{
[NSException raise: NSGenericException
format: @"connection waiting for request was shut down"];
}
/* xxx Why do we get the reply packet in here, and not
just before calling dissect_method_return() below? */
ip = [self _getReceivedReplyRmcWithSequenceNumber:seq_num];
@ -1100,6 +1131,11 @@ static int messages_received_count;
if (op == nil)
{
BOOL is_exception = NO;
/* It is possible that our connection died while the method was
being called - in this case we mustn't try to send the result
back to the remote application! */
if (!is_valid)
return;
op = [self newSendingReplyRmcWithSequenceNumber:
reply_sequence_number];
[op encodeValueOfCType: @encode(BOOL)
@ -1152,13 +1188,16 @@ static int messages_received_count;
[op release];
/* Send the exception back to the client. */
op = [self newSendingReplyRmcWithSequenceNumber: reply_sequence_number];
[op encodeValueOfCType: @encode(BOOL)
at: &is_exception
withName: @"Exceptional reply flag"];
[op encodeBycopyObject: localException
withName: @"Exception object"];
[op dismiss];
if (is_valid)
{
op=[self newSendingReplyRmcWithSequenceNumber: reply_sequence_number];
[op encodeValueOfCType: @encode(BOOL)
at: &is_exception
withName: @"Exceptional reply flag"];
[op encodeBycopyObject: localException
withName: @"Exception object"];
[op dismiss];
}
}
NS_ENDHANDLER;
@ -1315,18 +1354,20 @@ static int messages_received_count;
- (void) _handleRmc: rmc
{
NSConnection* conn = [[rmc connection] retain];
switch ([rmc identifier])
{
case ROOTPROXY_REQUEST:
/* It won't take much time to handle this, so go ahead and service
it, even if we are waiting for a reply. */
[[rmc connection] _service_rootObject: rmc];
[conn _service_rootObject: rmc];
[rmc dismiss];
break;
case METHODTYPE_REQUEST:
/* It won't take much time to handle this, so go ahead and service
it, even if we are waiting for a reply. */
[[rmc connection] _service_typeForSelector: rmc];
[conn _service_typeForSelector: rmc];
[rmc dismiss];
break;
case METHOD_REQUEST:
@ -1343,15 +1384,17 @@ static int messages_received_count;
then we may still want to service it now if DELAY_DIALOG_INTERRUPTIONS
is false. */
if (reply_depth == 0
|| ([rmc connection] == self && independant_queueing == NO)
|| (conn == self && independant_queueing == NO)
|| !delay_dialog_interruptions)
{
[[rmc connection] _service_forwardForProxy: rmc];
[self retain];
[conn _service_forwardForProxy: rmc];
/* Service any requests that were queued while we
were waiting for replies.
xxx Is this the right place for this check? */
if (reply_depth == 0)
[self _handleQueuedRmcRequests];
[self release];
}
else
{
@ -1370,18 +1413,20 @@ static int messages_received_count;
break;
case CONNECTION_SHUTDOWN:
{
[[rmc connection] _service_shutdown: rmc forConnection: self];
[conn _service_shutdown: rmc forConnection: self];
break;
}
case PROXY_RELEASE:
{
[[rmc connection] _service_release: rmc forConnection: self];
[conn _service_release: rmc forConnection: self];
break;
}
default:
[conn release];
[NSException raise: NSGenericException
format: @"unrecognized NSPortCoder identifier"];
}
[conn release];
}
- (void) _handleQueuedRmcRequests
@ -1389,7 +1434,7 @@ static int messages_received_count;
id rmc;
[received_request_rmc_queue_gate lock];
while ((rmc = [received_request_rmc_queue dequeueObject]))
while (is_valid && (rmc = [received_request_rmc_queue dequeueObject]))
{
[received_request_rmc_queue_gate unlock];
[self _handleRmc: rmc];
@ -1561,34 +1606,44 @@ static int messages_received_count;
- (void) _release_targets: (unsigned int*)list count:(unsigned int)number
{
/*
* Tell the remote app that it can release its local objects
* for the targets in the specified list since we don't have
* proxies for them any more.
*/
if (receive_port && is_valid && number > 0) {
id op;
unsigned int i;
NS_DURING
{
/*
* Tell the remote app that it can release its local objects
* for the targets in the specified list since we don't have
* proxies for them any more.
*/
if (receive_port && is_valid && number > 0) {
id op;
unsigned int i;
op = [[self encodingClass]
newForWritingWithConnection: self
sequenceNumber: [self _newMsgNumber]
identifier: PROXY_RELEASE];
op = [[self encodingClass]
newForWritingWithConnection: self
sequenceNumber: [self _newMsgNumber]
identifier: PROXY_RELEASE];
[op encodeValueOfCType: @encode(typeof(number))
at: &number
withName: NULL];
for (i = 0; i < number; i++) {
unsigned int target = list[i];
[op encodeValueOfCType: @encode(typeof(target))
at: &target
[op encodeValueOfCType: @encode(typeof(number))
at: &number
withName: NULL];
}
[op dismiss];
for (i = 0; i < number; i++) {
unsigned int target = list[i];
[op encodeValueOfCType: @encode(typeof(target))
at: &target
withName: NULL];
}
[op dismiss];
}
}
NS_HANDLER
{
if (debug_connection)
fprintf (stderr, "failed to release targets - %s\n",
[[localException name] cStringNoCopy]);
}
NS_ENDHANDLER
}
- (void) removeProxy: (NSDistantObject*)aProxy
@ -1828,33 +1883,29 @@ static int messages_received_count;
/* Shutting down and deallocating. */
/* We register this method with NotificationDispatcher for when a port dies. */
/*
* We register this method for a notification when a port dies.
* NB. It is possible that the death of a port could be notified
* to us after we are invalidated - in which case we must ignore it.
*/
- (void) portIsInvalid: notification
{
id port = [notification object];
if (is_valid) {
id port = [notification object];
NSParameterAssert (is_valid);
if (debug_connection)
fprintf (stderr, "Received port invalidation notification for "
"connection 0x%x\n\t%s\n", (unsigned)self,
[[port description] cStringNoCopy]);
/* We shouldn't be getting any port invalidation notifications,
except from our own ports; this is how we registered ourselves
with the NotificationDispatcher in
+newForInPort:outPort:ancestorConnection. */
NSParameterAssert (port == receive_port || port == send_port);
if (debug_connection)
fprintf (stderr, "Received port invalidation notification for "
"connection 0x%x\n\t%s\n", (unsigned)self,
[[port description] cStringNoCopy]);
/* xxx This also needs to be done properly in cases where the
Connection invalidates itself. */
/* Remove ourselves from the receive_port_2_ancestor, if necessary. */
{
id ancestor;
if ([port isKindOfClass: [InPort class]]
&& (self == (ancestor = NSMapGet (receive_port_2_ancestor, port))))
NSMapRemove (receive_port_2_ancestor, port);
}
[self invalidate];
/* xxx Anything else? */
/* We shouldn't be getting any port invalidation notifications,
except from our own ports; this is how we registered ourselves
with the NotificationDispatcher in
+newForInPort:outPort:ancestorConnection. */
NSParameterAssert (port == receive_port || port == send_port);
[self invalidate];
}
}
@end

View file

@ -1,8 +1,8 @@
/* Implementation of abstract superclass port for use with Connection
Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
Written by: Andrew Kachites McCallum <mccallum@gnu.ai.mit.edu>
Created: July 1994
Written by: Richard Frith-Macdonald <richard@brainstorm.co.uk>
Created: August 1997
This file is part of the GNUstep Base Library.
@ -23,6 +23,7 @@
#include <Foundation/NSString.h>
#include <Foundation/NSPort.h>
#include <Foundation/NSAutoreleasePool.h>
NSString* NSPortDidBecomeInvalidNotification
= @"NSPortDidBecomeInvalidNotification";
@ -91,6 +92,27 @@ NSString *NSPortTimeoutException
return nil;
}
- (void) release
{
if (is_valid && [self retainCount] == 1) {
NSAutoreleasePool *arp;
/*
* If the port is about to have a final release deallocate it
* we must invalidate it. Use a local autorelease pool when
* invalidating so that we know that anything refering to this
* port during the invalidation process is released immediately.
* Also - bracket with retain/release pair to prevent recursion.
*/
[super retain];
arp = [[NSAutoreleasePool alloc] init];
[self invalidate];
[arp release];
[super release];
}
[super release];
}
- (void) setDelegate: anObject
{
delegate = anObject;

View file

@ -34,6 +34,7 @@
#include <gnustep/base/CStream.h>
#include <gnustep/base/Port.h>
#include <gnustep/base/MemoryStream.h>
#include <Foundation/NSException.h>
#include <Foundation/DistributedObjects.h>
#include <assert.h>
@ -103,8 +104,19 @@ static BOOL debug_connected_coder = NO;
- (void) dismiss
{
id packet = [cstream stream];
[(OutPort*)[connection sendPort] sendPacket: packet
NS_DURING
{
[(OutPort*)[connection sendPort] sendPacket: packet
timeout: [connection requestTimeout]];
}
NS_HANDLER
{
if (debug_connected_coder)
fprintf(stderr, "dismiss 0x%x: #=%d i=%d write failed - %s\n",
(unsigned)self, sequence_number, identifier,
[[localException reason] cStringNoCopy]);
}
NS_ENDHANDLER
if (debug_connected_coder)
fprintf(stderr, "dismiss 0x%x: #=%d i=%d %d\n",
(unsigned)self, sequence_number, identifier,

View file

@ -115,12 +115,15 @@ static int debug_run_loop = 0;
id receiver;
RunLoopEventType type;
NSDate* limit;
unsigned count;
}
- (void) eventFor: (void*)info mode: (NSString*)mode;
- (void*) getData;
- (NSDate*) getLimit;
- (id) getReceiver;
- (RunLoopEventType) getType;
- (BOOL) decrement;
- (void) increment;
- initWithType: (RunLoopEventType)type
receiver: (id)anObj
data: (void*)data;
@ -135,11 +138,23 @@ static int debug_run_loop = 0;
- (void) dealloc
{
[self invalidate];
[limit release];
[receiver release];
[super dealloc];
}
- (BOOL) decrement
{
if (count > 0) {
count--;
if (count > 0) {
return YES;
}
}
return NO;
}
- (void) eventFor: (void*)info mode: (NSString*)mode
{
if ([self isValid] == NO) {
@ -184,6 +199,11 @@ static int debug_run_loop = 0;
return type;
}
- (void) increment
{
count++;
}
- initWithType: (RunLoopEventType)aType
receiver: (id)anObj
data: (void*)item
@ -202,6 +222,7 @@ static int debug_run_loop = 0;
[self setReceiver:anObj];
[self setData:item];
[self setLimit:nil];
count = 0;
}
return self;
}
@ -239,10 +260,11 @@ static int debug_run_loop = 0;
- (void) setReceiver: anObject
{
id obj = [anObject retain];
id obj = receiver;
[receiver release];
receiver = obj;
receiver = [anObject retain];
[obj release];
}
@end
@ -333,8 +355,15 @@ static int debug_run_loop = 0;
@interface NSRunLoop (Private)
- (void) _addWatcher: (RunLoopWatcher*) item forMode: (NSString*)mode;
- (void) _addWatcher: (RunLoopWatcher*)item
forMode: (NSString*)mode;
- (void) _checkPerformers;
- (RunLoopWatcher*) _getWatcher: (void*)data
type: (RunLoopEventType)type
forMode: (NSString*)mode;
- (void) _removeWatcher: (void*)data
type: (RunLoopEventType)type
forMode: (NSString*)mode;
@end
@ -344,14 +373,14 @@ static int debug_run_loop = 0;
limit-date order. */
- (void) _addWatcher: (RunLoopWatcher*) item forMode: (NSString*)mode
{
Array *watchers;
id obj;
NSDate* limit;
int count;
NSMutableArray *watchers;
id obj;
NSDate *limit;
int count;
watchers = NSMapGet (_mode_2_watchers, mode);
if (watchers == nil) {
watchers = [Array new];
watchers = [NSMutableArray new];
NSMapInsert (_mode_2_watchers, mode, watchers);
[watchers release];
count = 0;
@ -463,15 +492,26 @@ static int debug_run_loop = 0;
if (mode == nil)
mode = _current_mode;
/* Remove any existing handler for the specified descriptor. */
[self removeEvent: data type: type forMode: mode];
info = [self _getWatcher: data type: type forMode: mode];
/* Create new object to hold information. */
info = [[RunLoopWatcher alloc] initWithType: type
receiver: watcher
data: data];
[self _addWatcher:info forMode:mode];
[info release];
if (info && [info getReceiver] == watcher) {
/* Increment usage count for this watcher. */
[info increment];
}
else {
/* Remove any existing handler for another watcher. */
[self _removeWatcher: data type: type forMode: mode];
/* Create new object to hold information. */
info = [[RunLoopWatcher alloc] initWithType: type
receiver: watcher
data: data];
/* Add the object to the array for the mode and keep count. */
[self _addWatcher:info forMode:mode];
[info increment];
[info release]; /* Now held in array. */
}
}
- (void) addReadDescriptor: (int)fd
@ -498,38 +538,35 @@ static int debug_run_loop = 0;
- (void) removeEvent: (void*)data
type: (RunLoopEventType)type
forMode: (NSString*)mode
all: (BOOL)removeAll
{
Array* watchers;
if (mode == nil)
mode = _current_mode;
if (removeAll) {
[self _removeWatcher: data type: type forMode: mode];
}
else {
RunLoopWatcher *info;
if (mode == nil )
mode = _current_mode;
watchers = NSMapGet (_mode_2_watchers, mode);
if (watchers) {
int i;
for (i = [watchers count]; i > 0; i--) {
RunLoopWatcher* info;
info = (RunLoopWatcher*)[watchers objectAtIndex:(i-1)];
if ([info getType] == type && [info getData] == data) {
[info invalidate];
[watchers removeObject: info];
}
}
info = [self _getWatcher: data type: type forMode: mode];
if (info && [info decrement] == NO) {
[self _removeWatcher: data type: type forMode: mode];
}
}
}
- (void) removeReadDescriptor: (int)fd
forMode: (NSString*)mode
{
return [self removeEvent:(void*)fd type: ET_RDESC forMode:mode];
return [self removeEvent:(void*)fd type: ET_RDESC forMode:mode all:NO];
}
- (void) removeWriteDescriptor: (int)fd
forMode: (NSString*)mode
{
return [self removeEvent:(void*)fd type: ET_WDESC forMode:mode];
return [self removeEvent:(void*)fd type: ET_WDESC forMode:mode all:NO];
}
- (BOOL) runOnceBeforeDate: date
@ -646,7 +683,7 @@ static int debug_run_loop = 0;
Heap *timers;
NSTimer *min_timer = nil;
RunLoopWatcher *min_watcher = nil;
Array *watchers;
NSArray *watchers;
NSDate *when;
saved_mode = _current_mode;
@ -872,10 +909,62 @@ static int debug_run_loop = 0;
wfd_2_object = NSCreateMapTable (NSIntMapKeyCallBacks,
NSObjectMapValueCallBacks, 0);
- (RunLoopWatcher*) _getWatcher: (void*)data
type: (RunLoopEventType)type
forMode: (NSString*)mode
{
NSArray *watchers;
RunLoopWatcher *info;
int count;
if (mode == nil)
mode = _current_mode;
watchers = NSMapGet (_mode_2_watchers, mode);
if (watchers == nil) {
return nil;
}
for (count = 0; count < [watchers count]; count++) {
info = [watchers objectAtIndex: count];
if ([info getType] == type) {
if ([info getData] == data) {
return info;
}
}
}
return nil;
}
- (void) _removeWatcher: (void*)data
type: (RunLoopEventType)type
forMode: (NSString*)mode
{
NSMutableArray *watchers;
if (mode == nil )
mode = _current_mode;
watchers = NSMapGet (_mode_2_watchers, mode);
if (watchers) {
int i;
for (i = [watchers count]; i > 0; i--) {
RunLoopWatcher* info;
info = (RunLoopWatcher*)[watchers objectAtIndex:(i-1)];
if ([info getType] == type && [info getData] == data) {
[info invalidate];
[watchers removeObject: info];
}
}
}
}
/* Do the pre-listening set-up for the file descriptors of this mode. */
{
Array* watchers;
NSArray *watchers;
watchers = NSMapGet (_mode_2_watchers, mode);
if (watchers) {
@ -1117,7 +1206,7 @@ id NSDefaultRunLoopMode = @"NSDefaultRunLoopMode";
- (void) removePort: (NSPort*)port
forMode: (NSString*)mode
{
return [self removeEvent:(void*)port type: ET_RPORT forMode:mode];
return [self removeEvent:(void*)port type: ET_RPORT forMode:mode all:NO];
}
@end

View file

@ -699,7 +699,7 @@ static NSMapTable* port_number_2_port;
if ((p = (id) NSMapGet (port_number_2_port, (void*)((int)n))))
{
assert (p->is_valid);
return p;
return [p retain];
}
/* There isn't already a TcpInPort for this port number, so create
@ -878,6 +878,7 @@ static NSMapTable* port_number_2_port;
want to wait for one directly from a port, you can use this method. */
- newPacketReceivedBeforeDate: date
{
NSString* saved_mode = [NSRunLoop currentMode];
id saved_packet_invocation;
id packet = nil;
id handle_packet (id p)
@ -894,7 +895,7 @@ static NSMapTable* port_number_2_port;
/* Make sure we're in the run loop, and run it, waiting for the
incoming packet. */
[[NSRunLoop currentRunLoop] addPort: self
forMode: [NSRunLoop currentMode]];
forMode: saved_mode];
while ([NSRunLoop runOnceBeforeDate: date]
&& !packet)
;
@ -904,7 +905,7 @@ static NSMapTable* port_number_2_port;
this run loop. */
_packet_invocation = saved_packet_invocation;
[[NSRunLoop currentRunLoop] removePort: self
forMode: [NSRunLoop currentMode]];
forMode: saved_mode];
return packet;
}
@ -1347,7 +1348,7 @@ static NSMapTable *out_port_bag = NULL;
work because sin_zero's may differ. */
{
assert (p->is_valid);
return p;
return [p retain];
}
}
}
@ -1681,8 +1682,7 @@ static NSMapTable *out_port_bag = NULL;
- (void) dealloc
{
if (is_valid)
[self invalidate];
[self invalidate];
[super dealloc];
}

View file

@ -144,14 +144,16 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin)
[self ignoreReadDescriptor];
[self ignoreWriteDescriptor];
if (closeOnDealloc == YES)
if (descriptor != -1)
{
close(descriptor);
descriptor = -1;
if (closeOnDealloc == YES)
{
close(descriptor);
descriptor = -1;
}
else if (isNonBlocking != wasNonBlocking)
[self setNonBlocking:wasNonBlocking];
}
else if (isNonBlocking != wasNonBlocking)
[self setNonBlocking:wasNonBlocking];
[readInfo release];
[writeInfo release];
[super dealloc];
@ -531,9 +533,11 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin)
- (NSData*)availableData
{
char buf[NETBUF_SIZE];
NSMutableData* d = [NSMutableData dataWithCapacity:0];
NSMutableData* d;
int len;
[self checkRead];
d = [NSMutableData dataWithCapacity:0];
if (isStandardFile)
{
while ((len = read(descriptor, buf, sizeof(buf))) > 0)
@ -560,9 +564,11 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin)
- (NSData*)readDataToEndOfFile
{
char buf[NETBUF_SIZE];
NSMutableData* d = [NSMutableData dataWithCapacity:0];
NSMutableData* d;
int len;
[self checkRead];
d = [NSMutableData dataWithCapacity:0];
while ((len = read(descriptor, buf, sizeof(buf))) > 0)
{
[d appendBytes:buf length:len];
@ -578,9 +584,11 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin)
- (NSData*)readDataOfLength:(unsigned int)len
{
NSMutableData* d = [NSMutableData dataWithCapacity:len];
NSMutableData* d;
int pos;
[self checkRead];
d = [NSMutableData dataWithCapacity:len];
if ((pos = read(descriptor, [d mutableBytes], len)) < 0)
{
[NSException raise: NSFileHandleOperationException
@ -598,6 +606,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin)
unsigned int len = [item length];
unsigned int pos = 0;
[self checkWrite];
while (pos < len)
{
int toWrite = len - pos;
@ -678,7 +687,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin)
{
off_t result = -1;
if (isStandardFile)
if (isStandardFile && descriptor >= 0)
result = lseek(descriptor, 0, SEEK_CUR);
if (result < 0)
{
@ -693,7 +702,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin)
{
off_t result = -1;
if (isStandardFile)
if (isStandardFile && descriptor >= 0)
result = lseek(descriptor, 0, SEEK_END);
if (result < 0)
{
@ -708,7 +717,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin)
{
off_t result = -1;
if (isStandardFile)
if (isStandardFile && descriptor >= 0)
result = lseek(descriptor, (off_t)pos, SEEK_SET);
if (result < 0)
{
@ -739,6 +748,10 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin)
(void)close(descriptor);
descriptor = -1;
acceptOK = NO;
connectOK = NO;
readOK = NO;
writeOK = NO;
}
- (void)synchronizeFile
@ -749,7 +762,7 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin)
- (void)truncateFileAtOffset:(unsigned long long)pos
{
if (isStandardFile)
if (isStandardFile && descriptor >= 0)
(void)ftruncate(descriptor, pos);
[self seekToFileOffset:pos];
}
@ -855,13 +868,15 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin)
{
[l removeEvent: (void*)descriptor
type: ET_RDESC
forMode: [modes objectAtIndex:i]];
forMode: [modes objectAtIndex:i]
all: YES];
}
}
else
[l removeEvent: (void*)descriptor
type: ET_RDESC
forMode: NSDefaultRunLoopMode];
forMode: NSDefaultRunLoopMode
all: YES];
}
- (void)ignoreWriteDescriptor
@ -887,19 +902,25 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin)
{
[l removeEvent: (void*)descriptor
type: ET_WDESC
forMode: [modes objectAtIndex:i]];
forMode: [modes objectAtIndex:i]
all: YES];
}
}
else
[l removeEvent: (void*)descriptor
type: ET_WDESC
forMode: NSDefaultRunLoopMode];
forMode: NSDefaultRunLoopMode
all: YES];
}
- (void)watchReadDescriptorForModes:(NSArray*)modes;
{
NSRunLoop* l = [NSRunLoop currentRunLoop];
NSRunLoop* l;
if (descriptor < 0)
return;
l = [NSRunLoop currentRunLoop];
[self setNonBlocking:YES];
if (modes && [modes count])
{
@ -925,6 +946,9 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin)
- (void)watchWriteDescriptor
{
if (descriptor < 0)
return;
if ([writeInfo count] > 0)
{
NSMutableDictionary* info = [writeInfo objectAtIndex:0];
@ -1020,8 +1044,9 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin)
}
}
else if (type == ET_WDESC) {
NSMutableDictionary* info = [writeInfo objectAtIndex:0];
NSMutableDictionary* info;
info = [writeInfo objectAtIndex:0];
operation = [info objectForKey:NotificationKey];
if (operation == GSFileHandleWriteCompletionNotification) {
NSData* item;
@ -1073,6 +1098,9 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin)
{
int e;
if (descriptor < 0)
return;
if (isStandardFile)
return;