|
From: | Graham J Lee |
Subject: | Thread (usually) not doing what I'd expect |
Date: | Tue, 7 Nov 2006 14:29:06 +0000 |
Hi all,The code below demonstrates the problem I'm seeing with gnustep-base 1.13.0 on i386/Linux, where NSThread +detachNewThreadSelector:toTarget:withObject: is not consistently executing the method indicated. I'm trying to choose my words carefully here, because it *does* create a new LWP. In fact, if I set a breakpoint at the [NSThread ...] line, I can step through NSThread.m and see that objc_thread_dispatch returns non-NULL[*]. However, the global variable x never gets set and none of the NSLog() lines in the -doStuff method appear. I'm not so good with debugging multiple-threaded apps but if I step past objc_thread_detach then look at the threads display in ddd, I only see one thread, although I do get a notification of a new LWP from the debugger.
It looks like it might be racy, because if I step past the section (lines 551-555 here, I'm on base 1.13.0) in NSThread.m: if (objc_thread_detach(@selector(__sendThreadMethod),thread,nil) == NULL)
{ [NSException raise: NSInternalConsistencyException format: @"Unable to detach thread (unknown error)"]; } // <--step to here }and continue from there, I do get the change in x and the NSLog() messages as expected. Similarly if I execute the objc_thread_detach () function myself in the debugger by assigning its return value to a convenience variable, I get the expected result. But never when just running the code, debug=yes or not. The same program does what I expect - i.e. prints out all the NSLog()s and sets x to 3 - with the Apple Foundation.
[*] I can't step _into_ it, I guess because my objc runtime wasn't built with debugging symbols.
Here's the source. --8<--
#include <Foundation/Foundation.h> NSLock *lock; int x=0; @interface AnObject:NSObject { } - (void)doStuff; @end @implementation AnObject - (void)doStuff { id localPool=[[NSAutoreleasePool alloc] init]; NSLog(@"Here we go, acquiring lock..."); [lock lock]; x=3; NSLog(@"Relinquish lock..."); [lock unlock]; [localPool release]; } @end int main(int argc, const char *argv[]) { id pool = [[NSAutoreleasePool alloc] init]; AnObject *obj=[[AnObject alloc] init]; lock=[[NSLock alloc] init]; // Your code here... NSLog(@"Spawning the thread...");[NSThread detachNewThreadSelector:@selector(doStuff) toTarget:obj withObject:nil];NSLog(@"It's been launched."); // The end... while([lock tryLock]==NO); NSLog(@"Teardown: x=%d",x); [obj release]; [lock release]; [pool release]; return 0; }
--8<-- Cheers, Graham. -- Graham J Lee http://www.thaesofereode.info/
[Prev in Thread] | Current Thread | [Next in Thread] |