More fixups and added debugging

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@21980 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
CaS 2005-11-10 13:37:01 +00:00
parent 846003afda
commit 5807565afc
2 changed files with 183 additions and 206 deletions

View file

@ -826,8 +826,8 @@ static NSLock *cached_proxies_gate = nil;
if (debug_connection) if (debug_connection)
{ {
NSLog(@"Initialising new connection with parent %@, %@\n\t%@\n\t%@", NSLog(@"Initialising new connection with parent %@, %@\n "
parent, self, r, s); @"Send: %@\n Recv: %@", parent, self, s, r);
} }
M_LOCK(connection_table_gate); M_LOCK(connection_table_gate);

View file

@ -93,7 +93,7 @@ typedef struct {
gsu32 mId; /* The ID for the message starting with this. */ gsu32 mId; /* The ID for the message starting with this. */
gsu32 nItems; /* Number of items (including this one). */ gsu32 nItems; /* Number of items (including this one). */
unsigned char version; unsigned char version;
unsigned char port[24]; unsigned char port[16];
} GSPortMsgHeader; } GSPortMsgHeader;
typedef struct { typedef struct {
@ -111,10 +111,7 @@ typedef struct {
NSMutableData *rData; /* Buffer for incoming data */ NSMutableData *rData; /* Buffer for incoming data */
DWORD rLength; /* Amount read so far. */ DWORD rLength; /* Amount read so far. */
DWORD rWant; /* Amount desired. */ DWORD rWant; /* Amount desired. */
NSMessagePort *rPort; /* Port of message being read. */ NSMutableArray *rMsgs; /* Messages in progress. */
NSMutableArray *rItems; /* Message in progress. */
gsu32 rId; /* Id of incoming message. */
unsigned nItems; /* Number of items to be read. */
} internal; } internal;
#define PORT(X) ((internal*)((NSMessagePort*)X)->_internal) #define PORT(X) ((internal*)((NSMessagePort*)X)->_internal)
@ -129,8 +126,6 @@ static NSMapTable *recvPorts = 0;
static NSMapTable *sendPorts = 0; static NSMapTable *sendPorts = 0;
static Class messagePortClass; static Class messagePortClass;
#define HDR (sizeof(GSPortItemHeader) + sizeof(GSPortMsgHeader))
#if NEED_WORD_ALIGNMENT #if NEED_WORD_ALIGNMENT
static unsigned wordAlign; static unsigned wordAlign;
#endif #endif
@ -227,7 +222,7 @@ static unsigned wordAlign;
{ {
DESTROY(this->name); DESTROY(this->name);
DESTROY(this->rData); DESTROY(this->rData);
DESTROY(this->rItems); DESTROY(this->rMsgs);
DESTROY(this->wMsgs); DESTROY(this->wMsgs);
DESTROY(this->lock); DESTROY(this->lock);
NSZoneFree(NSDefaultMallocZone(), _internal); NSZoneFree(NSDefaultMallocZone(), _internal);
@ -279,19 +274,15 @@ static unsigned wordAlign;
memset(_internal, '\0', sizeof(internal)); memset(_internal, '\0', sizeof(internal));
this = PORT(self); this = PORT(self);
self->_is_valid = YES; self->_is_valid = YES;
#if (GS_SIZEOF_INT > 4) this->name = [[NSString alloc] initWithFormat: @"%08x%08x",
this->name = [[NSString alloc] initWithFormat: @"%08x%08x%08x",
(((unsigned)ident) >> 32), (((unsigned)ident) & 0xffffffff), sequence++];
#else
this->name = [[NSString alloc] initWithFormat: @"00000000%08x%08x",
((unsigned)ident), sequence++]; ((unsigned)ident), sequence++];
#endif
this->listener = YES; this->listener = YES;
this->event = CreateEvent(NULL, FALSE, FALSE, NULL); this->event = CreateEvent(NULL, FALSE, FALSE, NULL);
this->ov.hEvent = this->event; this->ov.hEvent = this->event;
this->lock = [GSLazyRecursiveLock new]; this->lock = [GSLazyRecursiveLock new];
this->rData = [NSMutableData new]; this->rData = [NSMutableData new];
this->rMsgs = [NSMutableArray new];
path = [NSString stringWithFormat: path = [NSString stringWithFormat:
@"\\\\.\\mailslot\\GNUstep\\NSMessagePort\\%@", this->name]; @"\\\\.\\mailslot\\GNUstep\\NSMessagePort\\%@", this->name];
@ -455,10 +446,11 @@ static unsigned wordAlign;
- (void) receivedEventRead - (void) receivedEventRead
{ {
internal *this = PORT(self); internal *this = PORT(self);
BOOL shouldDispatch = NO;
M_LOCK(this->lock); M_LOCK(this->lock);
retry:
if (this->rWant > 0) if (this->rWant > 0)
{ {
/* /*
@ -515,7 +507,12 @@ static unsigned wordAlign;
[self invalidate]; [self invalidate];
return; return;
} }
this->rLength += this->size; else
{
NSDebugMLLog(@"NSMessagePort", @"Read complete on %@",
self);
}
this->rLength = this->size;
this->size = 0; this->size = 0;
} }
} }
@ -528,6 +525,7 @@ static unsigned wordAlign;
} }
else else
{ {
NSLog(@"GetOverlappedResult succes ...%u", this->size);
this->rLength += this->size; this->rLength += this->size;
this->size = 0; this->size = 0;
} }
@ -541,20 +539,24 @@ static unsigned wordAlign;
GSPortItemType rType; GSPortItemType rType;
GSPortItemHeader *pih; GSPortItemHeader *pih;
unsigned off = 0; unsigned off = 0;
unsigned l; unsigned len;
unsigned rId;
unsigned nItems;
NSMessagePort *rPort = nil;
NSMutableArray *rItems = nil;
while (off + sizeof(GSPortItemHeader) < this->rLength) while (off + sizeof(GSPortItemHeader) <= this->rLength)
{ {
pih = (GSPortItemHeader*)(buf + off); pih = (GSPortItemHeader*)(buf + off);
off += sizeof(GSPortItemHeader); off += sizeof(GSPortItemHeader);
rType = GSSwapBigI32ToHost(pih->type); rType = GSSwapBigI32ToHost(pih->type);
l = GSSwapBigI32ToHost(pih->length); len = GSSwapBigI32ToHost(pih->length);
if (l + off > this->rLength) if (len + off > this->rLength)
{ {
NSLog(@"%@ - unreasonable length (%u) for data", self, l); NSLog(@"%@ - unreasonable length (%u) for data", self, len);
break; break;
} }
if (rType != GSP_HEAD && [this->rItems count] == 0) if (rType != GSP_HEAD && rItems == nil)
{ {
NSLog(@"%@ - initial part of message had bad type"); NSLog(@"%@ - initial part of message had bad type");
break; break;
@ -564,77 +566,62 @@ static unsigned wordAlign;
{ {
GSPortMsgHeader *pmh; GSPortMsgHeader *pmh;
NSString *n; NSString *n;
NSMessagePort *p;
NSMutableData *d; NSMutableData *d;
if (l < sizeof(GSPortMsgHeader)) if (len < sizeof(GSPortMsgHeader))
{ {
NSLog(@"%@ - bad length for header", self); NSLog(@"%@ - bad length for header", self);
break; break;
} }
pmh = (GSPortMsgHeader*)(buf + off); pmh = (GSPortMsgHeader*)(buf + off);
off += sizeof(GSPortMsgHeader); off += sizeof(GSPortMsgHeader);
l -= sizeof(GSPortMsgHeader); len -= sizeof(GSPortMsgHeader);
this->rId = GSSwapBigI32ToHost(pmh->mId); rId = GSSwapBigI32ToHost(pmh->mId);
this->nItems = GSSwapBigI32ToHost(pmh->nItems); nItems = GSSwapBigI32ToHost(pmh->nItems);
if (this->nItems == 0) if (nItems == 0)
{ {
NSLog(@"%@ - unable to decode item count", self); NSLog(@"%@ - unable to decode item count", self);
break; break;
} }
n = [[NSString alloc] initWithBytes: pmh->port n = [[NSString alloc] initWithBytes: pmh->port
length: 24 length: 16
encoding: NSASCIIStringEncoding]; encoding: NSASCIIStringEncoding];
NSDebugFLLog(@"NSMessagePort", @"Decoded port as '%@'", n); NSDebugFLLog(@"NSMessagePort", @"Decoded port as '%@'", n);
p = [NSMessagePort sendPort: n]; rPort = [NSMessagePort sendPort: n];
RELEASE(n); RELEASE(n);
if (p == nil) if (rPort == nil)
{ {
NSLog(@"%@ - unable to decode remote port", self); NSLog(@"%@ - unable to decode remote port", self);
break; break;
} }
ASSIGN(this->rPort, p); rItems = [NSMutableArray alloc];
this->rItems rItems = [rItems initWithCapacity: nItems];
= [NSMutableArray allocWithZone: NSDefaultMallocZone()];
this->rItems = [this->rItems initWithCapacity: this->nItems];
d = [[NSMutableData alloc] initWithBytes: buf + off d = [[NSMutableData alloc] initWithBytes: buf + off
length: l]; length: len];
[this->rItems addObject: d]; [rItems addObject: d];
RELEASE(d); RELEASE(d);
if (this->nItems == [this->rItems count])
{
shouldDispatch = YES;
break;
}
off += l;
} }
else if (rType == GSP_DATA) else if (rType == GSP_DATA)
{ {
NSMutableData *d; NSMutableData *d;
d = [[NSMutableData alloc] initWithBytes: buf + off d = [[NSMutableData alloc] initWithBytes: buf + off
length: l]; length: len];
[this->rItems addObject: d]; [rItems addObject: d];
RELEASE(d); RELEASE(d);
if (this->nItems == [this->rItems count])
{
shouldDispatch = YES;
break;
}
off += l;
} }
else if (rType == GSP_PORT) else if (rType == GSP_PORT)
{ {
NSMessagePort *p; NSMessagePort *p;
NSString *n; NSString *n;
if (l != 24) if (len != 16)
{ {
NSLog(@"%@ - bad length for port item", self); NSLog(@"%@ - bad length for port item", self);
break; break;
} }
n = [[NSString alloc] initWithBytes: buf + off n = [[NSString alloc] initWithBytes: buf + off
length: 24 length: 16
encoding: NSASCIIStringEncoding]; encoding: NSASCIIStringEncoding];
NSDebugFLLog(@"NSMessagePort", @"Decoded port as '%@'", n); NSDebugFLLog(@"NSMessagePort", @"Decoded port as '%@'", n);
p = [NSMessagePort sendPort: n]; p = [NSMessagePort sendPort: n];
@ -644,15 +631,25 @@ static unsigned wordAlign;
NSLog(@"%@ - unable to decode remote port", self); NSLog(@"%@ - unable to decode remote port", self);
break; break;
} }
[this->rItems addObject: p]; [rItems addObject: p];
if (this->nItems == [this->rItems count]) }
{ off += len;
shouldDispatch = YES; if (nItems == [rItems count])
break; {
} NSPortMessage *pm;
pm = [NSPortMessage allocWithZone: NSDefaultMallocZone()];
pm = [pm initWithSendPort: rPort
receivePort: self
components: rItems];
DESTROY(rItems);
[pm setMsgid: rId];
[this->rMsgs addObject: pm];
RELEASE(pm);
break;
} }
off += l;
} }
DESTROY(rItems);
this->rWant = 1; // Queue a read this->rWant = 1; // Queue a read
this->rLength = 0; this->rLength = 0;
} }
@ -667,36 +664,6 @@ static unsigned wordAlign;
this->rLength = 0; this->rLength = 0;
} }
if (shouldDispatch == YES)
{
NSPortMessage *pm;
pm = [NSPortMessage allocWithZone: NSDefaultMallocZone()];
pm = [pm initWithSendPort: this->rPort
receivePort: self
components: this->rItems];
[pm setMsgid: this->rId];
this->rId = 0;
DESTROY(this->rPort);
DESTROY(this->rItems);
NSDebugMLLog(@"NSMessagePort", @"got message %@ on 0x%x", pm, self);
M_UNLOCK(this->lock);
NS_DURING
{
[self handlePortMessage: pm];
}
NS_HANDLER
{
M_LOCK(this->lock);
RELEASE(pm);
[localException raise];
}
NS_ENDHANDLER
M_LOCK(this->lock);
RELEASE(pm);
}
/* /*
* Got something ... is it all we want? If not, ask to read more. * Got something ... is it all we want? If not, ask to read more.
*/ */
@ -719,15 +686,17 @@ static unsigned wordAlign;
if (rc > 0) if (rc > 0)
{ {
[self receivedEventRead]; // Read completed synchronously NSDebugMLLog(@"NSMessagePort", @"Read immediate on %@", self);
goto retry;
} }
else if ((errno = GetLastError()) == ERROR_IO_PENDING) else if ((errno = GetLastError()) == ERROR_IO_PENDING)
{ {
; // OK ... NSDebugMLLog(@"NSMessagePort", @"Read queued on %@", self);
} }
else if (errno == ERROR_INSUFFICIENT_BUFFER) else if (errno == ERROR_INSUFFICIENT_BUFFER)
{ {
[self receivedEventRead]; // Need to determine message size NSDebugMLLog(@"NSMessagePort", @"Read retry on %@", self);
goto retry;
} }
else else
{ {
@ -736,6 +705,31 @@ static unsigned wordAlign;
[self invalidate]; [self invalidate];
} }
} }
while ([this->rMsgs count] > 0)
{
NSPortMessage *pm;
pm = RETAIN([this->rMsgs objectAtIndex: 0]);
[this->rMsgs removeObjectAtIndex: 0];
NSDebugMLLog(@"NSMessagePort", @"got message %@ on 0x%x", pm, self);
M_UNLOCK(this->lock);
NS_DURING
{
[self handlePortMessage: pm];
}
NS_HANDLER
{
M_LOCK(this->lock);
RELEASE(pm);
[localException raise];
}
NS_ENDHANDLER
M_LOCK(this->lock);
RELEASE(pm);
}
M_UNLOCK(this->lock); M_UNLOCK(this->lock);
} }
@ -750,6 +744,8 @@ static unsigned wordAlign;
M_LOCK(this->lock); M_LOCK(this->lock);
retry:
if (this->wData != nil) if (this->wData != nil)
{ {
/* /*
@ -778,24 +774,15 @@ static unsigned wordAlign;
{ {
if (this->wData != nil) if (this->wData != nil)
{ {
unsigned idx;
NSDebugMLLog(@"NSMessagePort", NSDebugMLLog(@"NSMessagePort",
@"completed 0x%x on 0x%x", this->wData, self); @"completed write on 0x%x", self);
idx = [this->wMsgs indexOfObjectIdenticalTo: this->wData]; [this->wMsgs removeObjectIdenticalTo: this->wData];
if (idx != NSNotFound) this->wData = nil;
{
[this->wMsgs removeObjectAtIndex: idx];
}
} }
if ([this->wMsgs count] > 0) if ([this->wMsgs count] > 0)
{ {
this->wData = [this->wMsgs objectAtIndex: 0]; this->wData = [this->wMsgs objectAtIndex: 0];
} }
else
{
this->wData = nil; // Nothing to write.
}
this->wLength = 0; // Nothing written yet. this->wLength = 0; // Nothing written yet.
} }
@ -815,7 +802,7 @@ static unsigned wordAlign;
{ {
NSDebugMLLog(@"NSMessagePort", @"Write of %d performs %d", NSDebugMLLog(@"NSMessagePort", @"Write of %d performs %d",
[this->wData length] - this->wLength, this->size); [this->wData length] - this->wLength, this->size);
[self receivedEventWrite]; // Completed synchronously goto retry;
} }
else if ((errno = GetLastError()) != ERROR_IO_PENDING) else if ((errno = GetLastError()) != ERROR_IO_PENDING)
{ {
@ -894,14 +881,18 @@ static unsigned wordAlign;
from: (NSPort*)receivingPort from: (NSPort*)receivingPort
reserved: (unsigned)length reserved: (unsigned)length
{ {
NSMutableData *h; NSMutableData *h;
NSRunLoop *loop; NSMutableData *first;
BOOL sent = NO; BOOL sent = NO;
unsigned rl; unsigned c;
unsigned l = 0; unsigned i;
unsigned c; internal *this;
unsigned i; GSPortItemHeader *pih;
internal *this; GSPortMsgHeader *pmh;
NSDebugMLLog(@"NSMessagePort",
@"send message\n Send: %@\n Recv: %@\n Components -\n%@",
self, receivingPort, components);
if ([self isValid] == NO) if ([self isValid] == NO)
{ {
@ -918,11 +909,9 @@ static unsigned wordAlign;
} }
/* /*
* If the reserved length in the first data object is wrong - we have to * If the reserved length in the first data object is wrong - we have to
* fail, unless it's zero, in which case we can insert a data object for * fail.
* the header.
*/ */
rl = [self reservedSpaceLength]; if (length != [self reservedSpaceLength])
if (length != 0 && length != rl)
{ {
NSLog(@"bad reserved length - %u", length); NSLog(@"bad reserved length - %u", length);
return NO; return NO;
@ -934,83 +923,67 @@ static unsigned wordAlign;
NSAssert(PORT(receivingPort)->listener == YES, NSAssert(PORT(receivingPort)->listener == YES,
@"Attempt to send to send port"); @"Attempt to send to send port");
if (c == 1 && length == rl) first = [components objectAtIndex: 0];
if (c == 1)
{ {
GSPortItemHeader *pih; h = RETAIN(first);
GSPortMsgHeader *pmh;
h = [components objectAtIndex: 0];
pih = (GSPortItemHeader*)[h mutableBytes];
pih->type = GSSwapHostI32ToBig(GSP_HEAD);
l = [h length] - sizeof(GSPortItemHeader);
pih->length = GSSwapHostI32ToBig(l);
pmh = (GSPortMsgHeader*)&pih[1];
pmh->mId = GSSwapHostI32ToBig(msgId);
pmh->nItems = GSSwapHostI32ToBig(c);
pmh->version = 0;
memcpy(pmh->port, [[(NSMessagePort*)receivingPort name] UTF8String], 24);
} }
else if (c > 1)
{ {
for (i = 0; i < c; i++) unsigned l = 0;
{ id o;
id o = [components objectAtIndex: i];
for (i = 1; i < c; i++)
{
o = [components objectAtIndex: i];
if ([o isKindOfClass: [NSData class]] == YES) if ([o isKindOfClass: [NSData class]] == YES)
{ {
l += sizeof(GSPortItemHeader) + [o length]; l += sizeof(GSPortItemHeader) + [o length];
} }
else else
{ {
l += sizeof(GSPortItemHeader) + 24; // A port l += sizeof(GSPortItemHeader) + 16; // A port
} }
} }
h = [[NSMutableData alloc] initWithCapacity: sizeof(GSPortMsgHeader) + l]; h = [[NSMutableData alloc] initWithCapacity: [first length] + l];
[h appendData: first];
for (i = 0; i < c; i++)
for (i = 1; i < c; i++)
{ {
id o = [components objectAtIndex: i]; GSPortItemHeader ih;
GSPortItemHeader pih;
o = [components objectAtIndex: i];
if (i == 0) if ([o isKindOfClass: [NSData class]] == YES)
{ {
GSPortMsgHeader pmh; ih.type = GSSwapHostI32ToBig(GSP_DATA);
ih.length = GSSwapHostI32ToBig([o length]);
// First item must be an NSData [h appendBytes: &ih length: sizeof(ih)];
pih.type = GSSwapHostI32ToBig(GSP_HEAD);
l = sizeof(GSPortMsgHeader) + [o length];
pih.length = GSSwapHostI32ToBig(l);
[h appendBytes: &pih length: sizeof(pih)];
pmh.mId = GSSwapHostI32ToBig(msgId);
pmh.nItems = GSSwapHostI32ToBig(c);
pmh.version = 0;
memcpy(pmh.port,
[[(NSMessagePort*)receivingPort name] UTF8String], 24);
[h appendBytes: &pmh length: sizeof(pmh)];
[h appendData: o];
}
else if ([o isKindOfClass: [NSData class]] == YES)
{
pih.type = GSSwapHostI32ToBig(GSP_DATA);
l = [o length];
pih.length = GSSwapHostI32ToBig(l);
[h appendBytes: &pih length: sizeof(pih)];
[h appendData: o]; [h appendData: o];
} }
else else
{ {
pih.type = GSSwapHostI32ToBig(GSP_PORT); ih.type = GSSwapHostI32ToBig(GSP_PORT);
l = 24; ih.length = GSSwapHostI32ToBig(16);
pih.length = GSSwapHostI32ToBig(l); [h appendBytes: &ih length: sizeof(ih)];
[h appendBytes: &pih length: sizeof(pih)]; [h appendBytes: [o UTF8String] length: 16];
[h appendBytes: [o UTF8String] length: 24];
} }
} }
} }
pih = (GSPortItemHeader*)[h mutableBytes];
pih->type = GSSwapHostI32ToBig(GSP_HEAD);
pih->length = GSSwapHostI32ToBig([first length] - sizeof(GSPortItemHeader));
pmh = (GSPortMsgHeader*)&pih[1];
pmh->mId = GSSwapHostI32ToBig(msgId);
pmh->nItems = GSSwapHostI32ToBig(c);
pmh->version = 0;
memcpy(pmh->port, [[(NSMessagePort*)receivingPort name] UTF8String], 16);
/* /*
* Now send the message. * Now send the message.
*/ */
RETAIN(self);
M_LOCK(this->lock); M_LOCK(this->lock);
[this->wMsgs addObject: h]; [this->wMsgs addObject: h];
if (this->wData == nil) if (this->wData == nil)
@ -1018,45 +991,49 @@ static unsigned wordAlign;
[self receivedEventWrite]; // Start async write. [self receivedEventWrite]; // Start async write.
} }
loop = [NSRunLoop currentRunLoop];
RETAIN(self);
AUTORELEASE(RETAIN(components));
[loop addEvent: (void*)(gsaddr)this->event
type: ET_HANDLE
watcher: (id<RunLoopEvents>)self
forMode: NSConnectionReplyMode];
[loop addEvent: (void*)(gsaddr)this->event
type: ET_HANDLE
watcher: (id<RunLoopEvents>)self
forMode: NSDefaultRunLoopMode];
while ([self isValid] == YES
&& [this->wMsgs indexOfObjectIdenticalTo: h] != NSNotFound
&& [when timeIntervalSinceNow] > 0)
{
M_UNLOCK(this->lock);
[loop runMode: NSConnectionReplyMode beforeDate: when];
M_LOCK(this->lock);
}
[loop removeEvent: (void*)(gsaddr)this->event
type: ET_HANDLE
forMode: NSConnectionReplyMode
all: NO];
[loop removeEvent: (void*)(gsaddr)this->event
type: ET_HANDLE
forMode: NSDefaultRunLoopMode
all: NO];
if ([this->wMsgs indexOfObjectIdenticalTo: h] == NSNotFound) if ([this->wMsgs indexOfObjectIdenticalTo: h] == NSNotFound)
{ {
sent = YES; sent = YES; // Write completed synchronously
}
else
{
NSRunLoop *loop = [NSRunLoop currentRunLoop];
[loop addEvent: (void*)(gsaddr)this->event
type: ET_HANDLE
watcher: (id<RunLoopEvents>)self
forMode: NSConnectionReplyMode];
[loop addEvent: (void*)(gsaddr)this->event
type: ET_HANDLE
watcher: (id<RunLoopEvents>)self
forMode: NSDefaultRunLoopMode];
while ([self isValid] == YES
&& [this->wMsgs indexOfObjectIdenticalTo: h] != NSNotFound
&& [when timeIntervalSinceNow] > 0)
{
M_UNLOCK(this->lock);
[loop runMode: NSConnectionReplyMode beforeDate: when];
M_LOCK(this->lock);
}
[loop removeEvent: (void*)(gsaddr)this->event
type: ET_HANDLE
forMode: NSConnectionReplyMode
all: NO];
[loop removeEvent: (void*)(gsaddr)this->event
type: ET_HANDLE
forMode: NSDefaultRunLoopMode
all: NO];
if ([this->wMsgs indexOfObjectIdenticalTo: h] == NSNotFound)
{
sent = YES;
}
} }
RELEASE(h);
M_UNLOCK(this->lock); M_UNLOCK(this->lock);
RELEASE(self); RELEASE(self);
RELEASE(h);
return sent; return sent;
} }