diff --git a/ChangeLog b/ChangeLog index d6b90d2b9..3dee3cbee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2006-09-09 Richard Frith-Macdonald + + * Source/win32/NSMessagePortWin32.m: Restructure to try to avoid + deadlock reported by Wim. Also implement -release to remove port + from name table so that another thread can't find it in the window + between checking the refcount end deallocation. + 2006-09-07 Richard Frith-Macdonald * Headers/Foundation/NSObject.h: Fix incorrect backward compatibility diff --git a/Source/win32/NSMessagePortWin32.m b/Source/win32/NSMessagePortWin32.m index aada0bdda..102cd238e 100644 --- a/Source/win32/NSMessagePortWin32.m +++ b/Source/win32/NSMessagePortWin32.m @@ -203,11 +203,13 @@ static Class messagePortClass = 0; { p = [[self alloc] initWithName: name]; } - else - { - [p _setupSendPort]; - } M_UNLOCK(messagePortLock); + if ([self _setupSendPort] == NO) + { + NSLog(@"unable to access mailslot '%@' - %s", + p->name, GSLastErrorStr(errno)); + DESTROY(p); + } return p; } @@ -382,22 +384,12 @@ static Class messagePortClass = 0; this->wHandle = INVALID_HANDLE_VALUE; this->wEvent = INVALID_HANDLE_VALUE; - if ([self _setupSendPort] == NO) - { - NSLog(@"unable to access mailslot '%@' - %s", - this->name, GSLastErrorStr(errno)); - DESTROY(self); - } - else - { - NSMapInsert(ports, (void*)this->name, (void*)self); - NSDebugMLLog(@"NSMessagePort", @"Created speaking port: %@", self); - } + NSMapInsert(ports, (void*)this->name, (void*)self); + NSDebugMLLog(@"NSMessagePort", @"Created speaking port: %@", self); } else { RELEASE(self); - [p _setupSendPort]; self = p; } M_UNLOCK(messagePortLock); @@ -935,6 +927,28 @@ again: return sizeof(GSPortItemHeader) + sizeof(GSPortMsgHeader); } +- (void) release +{ + /* We lock the port table while checking, to prevent + * another thread from grabbing this port while we are + * checking it. + * If we are going to deallocate the object, we first remove + * it from the table so that no other thread will find it + * and try to use it while it is being deallocated. + */ + M_LOCK(messagePortLock); + if (NSDecrementExtraRefCountWasZero(self)) + { + NSMapRemove(ports, (void*)this->name); + M_UNLOCK(messagePortLock); + [self dealloc]; + } + else + { + M_UNLOCK(messagePortLock); + } +} + - (BOOL) sendBeforeDate: (NSDate*)when msgid: (int)msgId components: (NSMutableArray*)components