[Top][All Lists]
[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.
- Thread question, Banlu Kemiyatorn, 2011/03/01
- Re: Thread question, Richard Frith-Macdonald, 2011/03/01
- Re: Thread question, Banlu Kemiyatorn, 2011/03/01
- Re: Thread question, Richard Frith-Macdonald, 2011/03/02
- Re: Thread question, Richard Frith-Macdonald, 2011/03/02
- Re: Thread question, Banlu Kemiyatorn, 2011/03/04
- Re: Thread question,
Richard Frith-Macdonald <=
- Re: Thread question, Banlu Kemiyatorn, 2011/03/04
- Re: Thread question, Richard Frith-Macdonald, 2011/03/05
- Re: Thread question, Philippe Roussel, 2011/03/07
- Re: Thread question, Richard Frith-Macdonald, 2011/03/07
- Re: Thread question, Philippe Roussel, 2011/03/07
- Re: Thread question, Philippe Roussel, 2011/03/07
- Re: Thread question, Richard Frith-Macdonald, 2011/03/07
- Re: Thread question, Philippe Roussel, 2011/03/07