We use in our program DO to communicate between threads.
Now sometimes it happened that our application hanged and
stopped working. Unfortunately it is not very reproducable.
However recently we managed to make it more or less reproducable
and it turned out that roughly the following happens:
A auxiliary thread, which communicates with the main thread will exit
and a call
[NSThread +exit]
will take place. This in turn triggers a call to:
[NSConnection -_threadWillExit:]
which contains the following snippet:
M_LOCK (connection_table_gate);
enumerate over 'connection_table'
and on over 'connection' call:
[connection removeRunLoop: runLoo];
M_UNLOCK (connection_table_gate);
Now very infrequent but it sometimes it happens that the method
[NSConnection -invalidate]
is called while the connection is still valid. In that case we get to the code
snip-pit
M_LOCK (connection_table_gate)
NSHashRemove (connection_table, self)
M_UNLOCK (connection_table_gate)
Now this will block because 'connection_table_gate' is an NSLock.
Unfortunately I don't understand the whole DO system well enough to understand
why this happens.
But I have changed the method [NSConnection -_threadWillExit] to first make a
copy
of the hash table and afterwards iterate over the copy.
This solves our hangs.
Wim Oudshoorn.
--- gnustep-base/Source/NSConnection.m 2006-03-08 12:28:59.000000000 +0100
+++ gnustep-base/Source/NSConnection.m 2006-08-14 13:09:53.000000000 +0200
@@ -3613,6 +3613,7 @@
* On thread exit, we need all connections to be removed from the runloop
* of the thread or they will retain that and cause a memory leak.
*/
+#if 0
+ (void) _threadWillExit: (NSNotification*)notification
{
NSRunLoop *runLoop = GSRunLoopForThread([notification object]);
@@ -3632,6 +3633,36 @@
M_UNLOCK(connection_table_gate);
}
}
+#else
++ (void) _threadWillExit: (NSNotification*)notification
+{
+ NSRunLoop *runLoop = GSRunLoopForThread ([notification object]);
+
+ if (runLoop != nil)
+ {
+ NSMutableArray *connectionArray = [[NSMutableArray alloc] init];
+ NSHashEnumerator enumerator;
+ NSEnumerator *num;
+ NSConnection *c;
+ M_LOCK (connection_table_gate);
+ enumerator = NSEnumerateHashTable (connection_table);
+ while ((c = (NSConnection*) NSNextHashEnumeratorItem (&enumerator)) != nil)
+ {
+ [connectionArray addObject: c];
+ }
+ NSEndHashTableEnumeration (&enumerator);
+ M_UNLOCK (connection_table_gate);
+
+ num = [connectionArray objectEnumerator];
+ while ((c = [num nextObject]))
+ {
+ [c removeRunLoop: runLoop];
+ }
+
+ DESTROY (connectionArray);
+ }
+}
+#endif
@end
_______________________________________________
Bug-gnustep mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/bug-gnustep