gnustep-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Thread question


From: Richard Frith-Macdonald
Subject: Re: Thread question
Date: Fri, 4 Mar 2011 18:03:09 +0000

On 4 Mar 2011, at 14:54, Banlu Kemiyatorn wrote:

> On Wed, Mar 2, 2011 at 1:24 PM, Richard Frith-Macdonald
> <address@hidden> wrote:
>> 
>> On 2 Mar 2011, at 06:21, Richard Frith-Macdonald wrote:
>> 
>> 
>>> 
>>> OK ... that should build and run for you (and does for me) without trouble.
>>> If it usually works, but fails, rarely, I guess there might be some race 
>>> condition in gnustep-base (but from looking at the source I can't see how 
>>> that could be).
>>> If it fails consistently, I think there is something wrong with locking or 
>>> threading on your machine.
>> 
>> 
>> Of course, the best thing you can do is run under gdb, set a breakpoint to 
>> catch the exception, and try to see where/how things are going wrong.
> 
> #0  -[NSRecursiveLock unlock] (self=0xb580a3b0, _cmd=0xb7fb5808) at 
> NSLock.m:270
> #1  0xb7d9b623 in +[NSUserDefaults standardUserDefaults]
> (self=0xb7fb5700, _cmd=0xb7fb57f0)
>    at NSUserDefaults.m:691
> #2  0xb7d9b81b in GSPrivateDefaultsFlag (type=GSLogSyslog) at
> NSUserDefaults.m:2144
> #3  0xb7ce6a95 in NSLogv (format=0x804a23c,
>    args=0xb615a264
> "��\004\b[�ȷ�_��\b�\004\bl�\004\b��\004\b(�\b\b��\004\b\b�\004\b�\210\004\b�_��\b�\004\b\020z\a\b��\025�0�Ϸ\020z\a\b\b�\004\b")
> at NSLog.m:305
> #4  0xb7ce6f04 in NSLog (format=0x804a23c) at NSLog.m:252
> #5  0x08048922 in -[MyObj launch:] (self=0x8077a10, _cmd=0x804a208,
> task=0x0) at problem.m:24
> #6  0xb7cfdb30 in -[NSObject performSelector:withObject:]
> (self=0x8077a10, _cmd=0xb7fa5da8,
>    aSelector=0x804a208, anObject=0x0) at NSObject.m:1763
> #7  0xb7d6bc6a in -[NSThread main] (self=0x808df10, _cmd=0xb7fa5db0)
> at NSThread.m:729
> #8  0xb7d6c291 in nsthreadLauncher (thread=0x808df10) at NSThread.m:792
> #9  0xb7b36cc9 in start_thread () from /lib/libpthread.so.0
> #10 0xb7a4569e in clone () from /lib/libc.so.6
> 
> Above is what I got from bt, below is the code that cause the problem
> which, commenting out any NSLog will put away the "Uncaught exception
> NSLockException, reason: failed to unlock mutex" problem.
> 
> #include <unistd.h>
> #import <Foundation/Foundation.h>
> 
> @implementation NSObject (Launch)
> - (void) launch:(id)task
> {
>        id p = [NSAutoreleasePool new];
>        NSLog(@"hello");
>        [p release];
> }
> @end
> 
> int main (int argc, const char * argv[]) {
>        [NSAutoreleasePool new];
>        id obj = [NSObject new];
>        [NSThread detachNewThreadSelector:@selector(launch:)
> toTarget:obj withObject:nil];
>        NSLog(@"failing");
>        [NSThread detachNewThreadSelector:@selector(launch:)
> toTarget:obj withObject:nil];
>        return 0;
> }

I suspect that what you have run into here is a bug in the gnu Objective-C 
runtime.

You have two threads started and immediately calling NSLog, which in turn 
immediately tries to access the user defaults system.
The user defaults system is protected by a lock 'classLock' created in its 
+initialize method, which is run automatically by the runtime.
The +initialize method is supposed to run in a thread-safe manner *before* any 
other method in the class can run ... so this should mean that classLock, 
created in +initialize, can safely be used later.

What I think is happening is that one thread calls the +standarduserDefault 
method, and the runtime calls +initialize, then before +initialize has 
completed, the second thread calls +standardUserDefaults (and the runtime 
incorrectly lets it), which tries to lock classLock before it has been created. 
 This will send a _lock method to a nil object, which does nothing.  The thread 
then creates the shared user defaults object and tries to unlock classLock, but 
by this time the first thread has created the lock, so an -unlock message is 
sent to classLock when in has not been locked.

This bug only rarely manifests, since it depends on a race condition when a 
class is initialized, and in most non-trivial programs, most important classes 
are used before any threads are started.  You could check to see if this is 
your problem by calling any NSUserDefaults method before starting the 
threads...  if it is, doing that will prevent the exception from occurring.

Unless it's been fixed, this is probably the biggest outstanding bug in the gnu 
runtime.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]