diff --git a/Source/GSPortPrivate.h b/Source/GSPortPrivate.h index 85900bcd9..af844bc67 100644 --- a/Source/GSPortPrivate.h +++ b/Source/GSPortPrivate.h @@ -25,8 +25,6 @@ #if defined(__MINGW32__) @interface NSMessagePort(Private) -+ (NSMessagePort*) recvPort: (NSString*)name; -+ (NSMessagePort*) sendPort: (NSString*)name; - (id) initWithName: (NSString*)name; - (NSString*) name; - (void) receivedEventRead; diff --git a/Source/win32/GSRunLoopCtxt.m b/Source/win32/GSRunLoopCtxt.m index f7e0026e4..953afb70f 100644 --- a/Source/win32/GSRunLoopCtxt.m +++ b/Source/win32/GSRunLoopCtxt.m @@ -388,8 +388,9 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks = // check wait errors if (wait_return == WAIT_FAILED) { - NSLog(@"WaitForMultipleObjects() error in -acceptInputForMode:beforeDate: '%d'", - GetLastError()); + NSLog(@"WaitForMultipleObjects() error in " + @"-acceptInputForMode:beforeDate: '%s'", + GSLastErrorStr(GetLastError())); abort (); } diff --git a/Source/win32/NSMessagePortNameServerWin32.m b/Source/win32/NSMessagePortNameServerWin32.m index 319e8fb56..b409af347 100644 --- a/Source/win32/NSMessagePortNameServerWin32.m +++ b/Source/win32/NSMessagePortNameServerWin32.m @@ -217,7 +217,7 @@ static void clean_up_names(void) n = [[self class] _query: name]; NSDebugLLog(@"NSMessagePort", @"got %@", n); - return [NSMessagePort sendPort: n]; + return AUTORELEASE([[NSMessagePort alloc] initWithName: n]); } - (BOOL) registerPort: (NSPort *)port diff --git a/Source/win32/NSMessagePortWin32.m b/Source/win32/NSMessagePortWin32.m index 106b318a1..9298a131c 100644 --- a/Source/win32/NSMessagePortWin32.m +++ b/Source/win32/NSMessagePortWin32.m @@ -99,12 +99,14 @@ typedef struct { typedef struct { NSString *name; NSRecursiveLock *lock; - HANDLE handle; - HANDLE event; - OVERLAPPED ov; - DWORD size; - BOOL listener; - + HANDLE rHandle; + HANDLE wHandle; + HANDLE rEvent; + HANDLE wEvent; + OVERLAPPED rOv; + OVERLAPPED wOv; + DWORD rSize; + DWORD wSize; NSMutableData *wData; /* Data object being written. */ DWORD wLength; /* Amount written so far. */ NSMutableArray *wMsgs; /* Message in progress. */ @@ -122,14 +124,53 @@ static NSRecursiveLock *messagePortLock = nil; /* * Maps port name to NSMessagePort objects. */ -static NSMapTable *recvPorts = 0; -static NSMapTable *sendPorts = 0; +static NSMapTable *ports = 0; static Class messagePortClass; #if NEED_WORD_ALIGNMENT static unsigned wordAlign; #endif +- (BOOL) _setupSendPort +{ + internal *this = (internal*)self->_internal; + BOOL result; + + M_LOCK(this->lock); + if (this->wHandle == INVALID_HANDLE_VALUE) + { + NSString *path; + + path = [NSString stringWithFormat: + @"\\\\.\\mailslot\\GNUstep\\NSMessagePort\\%@", this->name]; + + this->wHandle = CreateFileW( + UNISTR(path), + GENERIC_WRITE, + FILE_SHARE_READ|FILE_SHARE_WRITE, + (LPSECURITY_ATTRIBUTES)0, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, + (HANDLE)0); + if (this->wHandle == INVALID_HANDLE_VALUE) + { + result = NO; + } + else + { + this->wEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + this->wMsgs = [NSMutableArray new]; + result = YES; + } + } + else + { + result = YES; + } + M_UNLOCK(this->lock); + return result; +} + + (void) initialize { if (self == [NSMessagePort class]) @@ -138,54 +179,22 @@ static unsigned wordAlign; wordAlign = objc_alignof_type(@encode(gsu32)); #endif messagePortClass = self; - recvPorts = NSCreateMapTable(NSNonRetainedObjectMapKeyCallBacks, - NSNonOwnedPointerMapValueCallBacks, 0); - sendPorts = NSCreateMapTable(NSNonRetainedObjectMapKeyCallBacks, + ports = NSCreateMapTable(NSNonRetainedObjectMapKeyCallBacks, NSNonOwnedPointerMapValueCallBacks, 0); messagePortLock = [GSLazyRecursiveLock new]; } } -+ (NSMessagePort*) recvPort: (NSString*)name -{ - NSMessagePort *p; - - if (name == nil) - { - p = AUTORELEASE([[self alloc] init]); - } - else - { - M_LOCK(messagePortLock); - p = AUTORELEASE(RETAIN((NSMessagePort*)NSMapGet(recvPorts, (void*)name))); - M_UNLOCK(messagePortLock); - } - return p; -} - -+ (NSMessagePort*) sendPort: (NSString*)name -{ - NSMessagePort *p; - - NSAssert(p != nil, @"sendPort: called with nil name"); - M_LOCK(messagePortLock); - p = AUTORELEASE(RETAIN((NSMessagePort*)NSMapGet(sendPorts, (void*)name))); - if (p == nil) - { - p = AUTORELEASE([[self alloc] initWithName: name]); - } - M_UNLOCK(messagePortLock); - return p; -} - - (void) addConnection: (NSConnection*)aConnection toRunLoop: (NSRunLoop*)aLoop forMode: (NSString*)aMode { NSDebugMLLog(@"NSMessagePort", @"%@ add to 0x%x in mode %@", self, aLoop, aMode); - [aLoop addEvent: (void*)(gsaddr)PORT(self)->event + NSAssert(PORT(self)->rHandle != INVALID_HANDLE_VALUE, + @"Attempt to listen on send port"); + [aLoop addEvent: (void*)(gsaddr)PORT(self)->rEvent type: ET_HANDLE watcher: (id)self forMode: aMode]; @@ -250,6 +259,7 @@ static unsigned wordAlign; NSDebugMLLog(@"NSMessagePort", @"delegate doesn't handle messages", 0); return; } + NSDebugMLLog(@"NSMessagePort", @"%@ asking %@ to handle msg", self, d); [d handlePortMessage: m]; } @@ -277,23 +287,24 @@ static unsigned wordAlign; this->name = [[NSString alloc] initWithFormat: @"%08x%08x", ((unsigned)ident), sequence++]; - this->listener = YES; - this->event = CreateEvent(NULL, FALSE, FALSE, NULL); - this->ov.hEvent = this->event; this->lock = [GSLazyRecursiveLock new]; + this->wHandle = INVALID_HANDLE_VALUE; + this->wEvent = INVALID_HANDLE_VALUE; + + this->rEvent = CreateEvent(NULL, FALSE, FALSE, NULL); this->rData = [NSMutableData new]; this->rMsgs = [NSMutableArray new]; path = [NSString stringWithFormat: @"\\\\.\\mailslot\\GNUstep\\NSMessagePort\\%@", this->name]; - this->handle = CreateMailslotW( + this->rHandle = CreateMailslotW( UNISTR(path), 0, /* No max message size. */ MAILSLOT_WAIT_FOREVER, /* No read/write timeout. */ (LPSECURITY_ATTRIBUTES)0); - if (this->handle == INVALID_HANDLE_VALUE) + if (this->rHandle == INVALID_HANDLE_VALUE) { NSLog(@"unable to create mailslot '%@' - %s", this->name, GSLastErrorStr(errno)); @@ -301,7 +312,7 @@ static unsigned wordAlign; } else { - NSMapInsert(recvPorts, (void*)this->name, (void*)self); + NSMapInsert(ports, (void*)this->name, (void*)self); NSDebugMLLog(@"NSMessagePort", @"Created listening port: %@", self); /* @@ -325,11 +336,10 @@ static unsigned wordAlign; NSMessagePort *p; M_LOCK(messagePortLock); - p = RETAIN((NSMessagePort*)NSMapGet(sendPorts, (void*)name)); + p = RETAIN((NSMessagePort*)NSMapGet(ports, (void*)name)); if (p == nil) { internal *this; - NSString *path; _internal = NSZoneMalloc(NSDefaultMallocZone(), sizeof(internal)); memset(_internal, '\0', sizeof(internal)); @@ -337,23 +347,14 @@ static unsigned wordAlign; self->_is_valid = YES; this->name = [name copy]; - this->listener = NO; - this->event = CreateEvent(NULL, FALSE, FALSE, NULL); - this->ov.hEvent = this->event; this->lock = [GSLazyRecursiveLock new]; - this->wMsgs = [NSMutableArray new]; - path = [NSString stringWithFormat: - @"\\\\.\\mailslot\\GNUstep\\NSMessagePort\\%@", this->name]; - this->handle = CreateFileW( - UNISTR(path), - GENERIC_WRITE, - FILE_SHARE_READ|FILE_SHARE_WRITE, - (LPSECURITY_ATTRIBUTES)0, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, - (HANDLE)0); - if (this->handle == INVALID_HANDLE_VALUE) + this->rHandle = INVALID_HANDLE_VALUE; + this->rEvent = INVALID_HANDLE_VALUE; + this->wHandle = INVALID_HANDLE_VALUE; + this->wEvent = INVALID_HANDLE_VALUE; + + if ([self _setupSendPort] == NO) { NSLog(@"unable to access mailslot '%@' - %s", this->name, GSLastErrorStr(errno)); @@ -361,13 +362,14 @@ static unsigned wordAlign; } else { - NSMapInsert(sendPorts, (void*)this->name, (void*)self); + NSMapInsert(ports, (void*)this->name, (void*)self); NSDebugMLLog(@"NSMessagePort", @"Created speaking port: %@", self); } } else { RELEASE(self); + [p _setupSendPort]; self = p; } M_UNLOCK(messagePortLock); @@ -386,28 +388,35 @@ static unsigned wordAlign; if ([self isValid] == YES) { M_LOCK(messagePortLock); - if (this->handle != INVALID_HANDLE_VALUE) + if (this->rHandle != INVALID_HANDLE_VALUE) { - (void) CancelIo(this->handle); + (void) CancelIo(this->rHandle); } - if (this->event != INVALID_HANDLE_VALUE) + if (this->wHandle != INVALID_HANDLE_VALUE) { - (void) CloseHandle(this->event); - this->event = INVALID_HANDLE_VALUE; + (void) CancelIo(this->wHandle); } - if (this->handle != INVALID_HANDLE_VALUE) + if (this->rEvent != INVALID_HANDLE_VALUE) { - (void) CloseHandle(this->handle); - this->handle = INVALID_HANDLE_VALUE; + (void) CloseHandle(this->rEvent); + this->rEvent = INVALID_HANDLE_VALUE; } - if (this->listener == YES) + if (this->wEvent != INVALID_HANDLE_VALUE) { - NSMapRemove(recvPorts, (void*)this->name); + (void) CloseHandle(this->wEvent); + this->wEvent = INVALID_HANDLE_VALUE; } - else + if (this->rHandle != INVALID_HANDLE_VALUE) { - NSMapRemove(sendPorts, (void*)this->name); + (void) CloseHandle(this->rHandle); + this->rHandle = INVALID_HANDLE_VALUE; } + if (this->wHandle != INVALID_HANDLE_VALUE) + { + (void) CloseHandle(this->wHandle); + this->wHandle = INVALID_HANDLE_VALUE; + } + NSMapRemove(ports, (void*)this->name); M_UNLOCK(messagePortLock); [[NSMessagePortNameServer sharedInstance] removePort: self]; @@ -449,17 +458,15 @@ static unsigned wordAlign; M_LOCK(this->lock); -retry: - if (this->rWant > 0) { /* * Have we read something? */ if (GetOverlappedResult( - this->handle, - &this->ov, - &this->size, + this->rHandle, + &this->rOv, + &this->rSize, TRUE) == 0) { errno = GetLastError(); @@ -474,7 +481,7 @@ retry: if (errno == ERROR_INSUFFICIENT_BUFFER) { if (GetMailslotInfo( - this->handle, + this->rHandle, 0, &this->rWant, 0, @@ -488,10 +495,10 @@ retry: else { [this->rData setLength: this->rWant]; - if (ReadFile(this->handle, + if (ReadFile(this->rHandle, [this->rData mutableBytes], // Store results here this->rWant, - &this->size, + &this->rSize, NULL) == 0) { NSLog(@"unable to read from mailslot '%@' - %s", @@ -499,10 +506,10 @@ retry: [self invalidate]; return; } - if (this->size != this->rWant) + if (this->rSize != this->rWant) { NSLog(@"only read %d of %d bytes from mailslot '%@' - %s", - this->size, this->rWant, this->name, + this->rSize, this->rWant, this->name, GSLastErrorStr(errno)); [self invalidate]; return; @@ -512,8 +519,8 @@ retry: NSDebugMLLog(@"NSMessagePort", @"Read complete on %@", self); } - this->rLength = this->size; - this->size = 0; + this->rLength = this->rSize; + this->rSize = 0; } } else @@ -525,9 +532,9 @@ retry: } else { - NSLog(@"GetOverlappedResult succes ...%u", this->size); - this->rLength += this->size; - this->size = 0; + NSLog(@"GetOverlappedResult succes ...%u", this->rSize); + this->rLength += this->rSize; + this->rSize = 0; } /* @@ -587,7 +594,7 @@ retry: length: 16 encoding: NSASCIIStringEncoding]; NSDebugFLLog(@"NSMessagePort", @"Decoded port as '%@'", n); - rPort = [NSMessagePort sendPort: n]; + rPort = [[NSMessagePort alloc] initWithName: n]; RELEASE(n); if (rPort == nil) { @@ -624,7 +631,7 @@ retry: length: 16 encoding: NSASCIIStringEncoding]; NSDebugFLLog(@"NSMessagePort", @"Decoded port as '%@'", n); - p = [NSMessagePort sendPort: n]; + p = [[NSMessagePort alloc] initWithName: n]; RELEASE(n); if (p == nil) { @@ -632,6 +639,7 @@ retry: break; } [rItems addObject: p]; + RELEASE(p); } off += len; if (nItems == [rItems count]) @@ -642,6 +650,7 @@ retry: pm = [pm initWithSendPort: rPort receivePort: self components: rItems]; + DESTROY(rPort); DESTROY(rItems); [pm setMsgid: rId]; [this->rMsgs addObject: pm]; @@ -649,6 +658,7 @@ retry: break; } } + DESTROY(rPort); DESTROY(rItems); this->rWant = 1; // Queue a read this->rLength = 0; @@ -671,23 +681,23 @@ retry: { int rc; - this->ov.Offset = 0; - this->ov.OffsetHigh = 0; - this->ov.hEvent = this->event; + this->rOv.Offset = 0; + this->rOv.OffsetHigh = 0; + this->rOv.hEvent = this->rEvent; if ([this->rData length] < (this->rWant - this->rLength)) { [this->rData setLength: this->rWant - this->rLength]; } - rc = ReadFile(this->handle, + rc = ReadFile(this->rHandle, [this->rData mutableBytes], // Store results here this->rWant - this->rLength, - &this->size, - &this->ov); + &this->rSize, + &this->rOv); if (rc > 0) { NSDebugMLLog(@"NSMessagePort", @"Read immediate on %@", self); - goto retry; + SetEvent(this->rEvent); } else if ((errno = GetLastError()) == ERROR_IO_PENDING) { @@ -696,7 +706,7 @@ retry: else if (errno == ERROR_INSUFFICIENT_BUFFER) { NSDebugMLLog(@"NSMessagePort", @"Read retry on %@", self); - goto retry; + SetEvent(this->rEvent); } else { @@ -749,20 +759,20 @@ retry: if (this->wData != nil) { /* - * Have we read something? + * Have we written something? */ if (GetOverlappedResult( - this->handle, - &this->ov, - &this->size, + this->wHandle, + &this->wOv, + &this->wSize, TRUE) == 0) { NSLog(@"GetOverlappedResult failed ...%s", GSLastErrorStr(errno)); } else { - this->wLength += this->size; - this->size = 0; + this->wLength += this->wSize; + this->wSize = 0; } } @@ -790,18 +800,18 @@ retry: { int rc; - this->ov.Offset = 0; - this->ov.OffsetHigh = 0; - this->ov.hEvent = this->event; - rc = WriteFile(this->handle, + this->wOv.Offset = 0; + this->wOv.OffsetHigh = 0; + this->wOv.hEvent = this->wEvent; + rc = WriteFile(this->wHandle, [this->wData bytes], // Output from here [this->wData length] - this->wLength, - &this->size, // Store number of bytes written - &this->ov); + &this->wSize, // Store number of bytes written + &this->wOv); if (rc > 0) { NSDebugMLLog(@"NSMessagePort", @"Write of %d performs %d", - [this->wData length] - this->wLength, this->size); + [this->wData length] - this->wLength, this->wSize); goto retry; } else if ((errno = GetLastError()) != ERROR_IO_PENDING) @@ -829,7 +839,7 @@ retry: { internal *this = PORT(self); - if (this->listener == YES) + if (this->rEvent == (HANDLE)data) { [self receivedEventRead]; } @@ -856,7 +866,7 @@ retry: { NSDebugMLLog(@"NSMessagePort", @"%@ remove from 0x%x in mode %@", self, aLoop, aMode); - [aLoop removeEvent: (void*)(gsaddr)PORT(self)->event + [aLoop removeEvent: (void*)(gsaddr)PORT(self)->rEvent type: ET_HANDLE forMode: aMode all: NO]; @@ -900,7 +910,9 @@ retry: } this = PORT(self); - NSAssert(PORT(self)->listener == NO, @"Attempt to send through recv port"); + NSAssert(PORT(self)->wHandle != INVALID_HANDLE_VALUE, + @"Attempt to send through recv port"); + c = [components count]; if (c == 0) { @@ -920,13 +932,14 @@ retry: @"Receiving port is not the correct type"); NSAssert([receivingPort isValid] == YES, @"Receiving port is not valid"); - NSAssert(PORT(receivingPort)->listener == YES, + NSAssert(PORT(receivingPort)->rHandle != INVALID_HANDLE_VALUE, @"Attempt to send to send port"); first = [components objectAtIndex: 0]; if (c == 1) { - h = RETAIN(first); + //h = RETAIN(first); + h = [first mutableCopy]; } if (c > 1) { @@ -999,11 +1012,11 @@ retry: { NSRunLoop *loop = [NSRunLoop currentRunLoop]; - [loop addEvent: (void*)(gsaddr)this->event + [loop addEvent: (void*)(gsaddr)this->wEvent type: ET_HANDLE watcher: (id)self forMode: NSConnectionReplyMode]; - [loop addEvent: (void*)(gsaddr)this->event + [loop addEvent: (void*)(gsaddr)this->wEvent type: ET_HANDLE watcher: (id)self forMode: NSDefaultRunLoopMode]; @@ -1017,11 +1030,11 @@ retry: M_LOCK(this->lock); } - [loop removeEvent: (void*)(gsaddr)this->event + [loop removeEvent: (void*)(gsaddr)this->wEvent type: ET_HANDLE forMode: NSConnectionReplyMode all: NO]; - [loop removeEvent: (void*)(gsaddr)this->event + [loop removeEvent: (void*)(gsaddr)this->wEvent type: ET_HANDLE forMode: NSDefaultRunLoopMode all: NO];