diff --git a/ChangeLog b/ChangeLog index c6022f9d4..259c727e5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,11 @@ * Source/NSTimeZone.m: Remove unnecessary check on fiel name as Roland Schwingel reported that it caught legitimate files on windows. + * Source/NSMessagePort.m: + * Source/NSSocketPort.m: + Protect -release with lock and remove port from gloibal table within + protected region, to avoid possible double deallocation in a + multithreaded process. 2006-09-09 Richard Frith-Macdonald diff --git a/Source/NSMessagePort.m b/Source/NSMessagePort.m index 73205cc44..9d7a6582c 100644 --- a/Source/NSMessagePort.m +++ b/Source/NSMessagePort.m @@ -1574,14 +1574,14 @@ typedef struct { unsigned i; M_LOCK(messagePortLock); + NSMapRemove(messagePortMap, (void*)name); + M_UNLOCK(messagePortLock); if (lDesc >= 0) { (void) close(lDesc); unlink([name bytes]); lDesc = -1; } - NSMapRemove(messagePortMap, (void*)name); - M_UNLOCK(messagePortLock); if (handles != 0) { @@ -1691,6 +1691,21 @@ typedef struct { } } +- (void) release +{ + M_LOCK(messagePortLock); + if (NSDecrementExtraRefCountWasZero(self)) + { + NSMapRemove(messagePortMap, (void*)name); + M_UNLOCK(messagePortLock); + [self dealloc]; + } + else + { + M_UNLOCK(messagePortLock); + } +} + - (void) removeHandle: (GSMessageHandle*)handle { M_LOCK(myLock); diff --git a/Source/NSSocketPort.m b/Source/NSSocketPort.m index 98ab968c8..428679c92 100644 --- a/Source/NSSocketPort.m +++ b/Source/NSSocketPort.m @@ -18,7 +18,8 @@ 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. + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02111 USA. */ #include "config.h" @@ -1693,7 +1694,8 @@ static Class tcpPortClass; NSLog(@"Invalid Event - '%d'", WSAGetLastError()); abort(); } - rc = WSAEventSelect(port->listener, port->eventListener, FD_ACCEPT); + rc = WSAEventSelect(port->listener, + port->eventListener, FD_ACCEPT); NSAssert(rc == 0, @"WSAEventSelect failed!"); #endif /* @@ -1725,7 +1727,8 @@ static Class tcpPortClass; * Make sure we have the map table for this port. */ port->portNum = number; - thePorts = (NSMapTable*)NSMapGet(tcpPortMap, (void*)(uintptr_t)number); + thePorts + = (NSMapTable*)NSMapGet(tcpPortMap, (void*)(uintptr_t)number); if (thePorts == 0) { /* @@ -1734,7 +1737,8 @@ static Class tcpPortClass; */ thePorts = NSCreateMapTable(NSIntMapKeyCallBacks, NSNonOwnedPointerMapValueCallBacks, 0); - NSMapInsert(tcpPortMap, (void*)(uintptr_t)number, (void*)thePorts); + NSMapInsert(tcpPortMap, + (void*)(uintptr_t)number, (void*)thePorts); } /* * Record the port by host. @@ -2057,19 +2061,20 @@ static Class tcpPortClass; thePorts = NSMapGet(tcpPortMap, (void*)(uintptr_t)portNum); if (thePorts != 0) { - if (listener >= 0) - { - (void) close(listener); - listener = -1; -#if defined(__MINGW32__) - WSACloseEvent(eventListener); - eventListener = WSA_INVALID_EVENT; -#endif - } NSMapRemove(thePorts, (void*)host); } M_UNLOCK(tcpPortLock); + if (listener >= 0) + { + (void) close(listener); + listener = -1; +#if defined(__MINGW32__) + WSACloseEvent(eventListener); + eventListener = WSA_INVALID_EVENT; +#endif + } + if (handles != 0) { handleArray = NSAllMapTableValues(handles); @@ -2216,6 +2221,28 @@ static Class tcpPortClass; } } +- (void) release +{ + M_LOCK(tcpPortLock); + if (NSDecrementExtraRefCountWasZero(self)) + { + NSMapTable *thePorts; + + thePorts = NSMapGet(tcpPortMap, (void*)(uintptr_t)portNum); + if (thePorts != 0) + { + NSMapRemove(thePorts, host); + } + M_UNLOCK(tcpPortLock); + [self dealloc]; + } + else + { + M_UNLOCK(tcpPortLock); + } +} + + /* * 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