[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: SIGABRT and SIGV in libobjc2
From: |
David Chisnall |
Subject: |
Re: SIGABRT and SIGV in libobjc2 |
Date: |
Fri, 8 Dec 2017 12:09:50 +0000 |
> On 6 Dec 2017, at 13:46, Andreas Fink <afink@list.fink.org> wrote:
>
> Hello folks,
>
> I have a heavily multithreaded application which produces two different
> crashes in libobjc2 code now.
> I believe I have hit a race condition.
>
> Here is the firs thread at SIGABRT:
>
>
> * frame #0: 0x00007ffff6f701be
> libobjc.so.4.6`objc_storeWeak(addr=0x00007fff7be0d628,
> obj=0x0000000000d32620) + 958 at arc.m:602
>
> Thread #27
>
> lldb) * thread #27: tid = 22581, 0x00007ffff6f701be
> libobjc.so.4.6`objc_storeWeak(addr=0x00007fff7be0d628,
> obj=0x0000000000d32620) + 958 at arc.m:602, name = 'tcap-task-queue'
> frame #0: 0x00007ffff6f701be
> libobjc.so.4.6`objc_storeWeak(addr=0x00007fff7be0d628,
> obj=0x0000000000d32620) + 958 at arc.m:602
> 599 {
> 600 for (int i=0 ; i<4 ; i++)
> 601 {
> -> 602 if (0 == ref->ref[i])
> 603 {
> 604 ref->ref[i] = addr;
> 605 *addr = obj;
This thread is storing a reference to an object 0x0000000000d32620 at address
0x00007fff7be0d628.
It has acquired the weak table lock, and is now modifying the metadata for the
weak reference. It should be safe to dereference ref, because we’ve already
done a check that it’s not null, and this table is only modified with the lock
held.
> Thread #26
>
> * thread #26: tid = 22580, 0x00007fffefd46fcf libc.so.6`gsignal + 207, name
> = 'tcap-task-queue', stop reason = signal SIGABRT
> frame #0: 0x00007fffefd46fcf libc.so.6`gsignal + 207
> frame #1: 0x00007fffefd483fa libc.so.6`abort + 362
> frame #2: 0x00007fffefd84bd0
> libc.so.6`___lldb_unnamed_symbol235$$libc.so.6 + 704
> frame #3: 0x00007fffefd8af96
> libc.so.6`___lldb_unnamed_symbol294$$libc.so.6 + 166
> frame #4: 0x00007fffefd8c091
> libc.so.6`___lldb_unnamed_symbol299$$libc.so.6 + 2513
> frame #5: 0x00007ffff78c0f49
> libgnustep-base.so.1.25`default_free(zone=0x00007ffff7d7c608,
> ptr=0x00007fff288f7270) + 25 at NSZone.m:150
> frame #6: 0x00007ffff78c0d66
> libgnustep-base.so.1.25`NSZoneFree(zone=0x00007ffff7d7c608,
> ptr=0x00007fff288f7270) + 54 at NSZone.m:1792
> frame #7: 0x00007ffff77dd5ec
> libgnustep-base.so.1.25`NSDeallocateObject(anObject=0x00007fff288f7280) + 236
> at NSObject.m:705
> frame #8: 0x00007ffff77ddd4c libgnustep-base.so.1.25`-[NSObject
> dealloc](self=0x00007fff288f7280, _cmd="\x11") + 28 at NSObject.m:1195
> frame #9: 0x00007ffff6f6f7f1
> libobjc.so.4.6`release(obj=0x00007fff288f7280) + 225 at arc.m:212
> frame #10: 0x00007ffff6f6fb98
> libobjc.so.4.6`objc_release(obj=0x00007fff288f7280) + 40 at arc.m:454
>
> (lldb) up
> frame #5: 0x00007ffff78c0f49
> libgnustep-base.so.1.25`default_free(zone=0x00007ffff7d7c608,
> ptr=0x00007fff288f7270) + 25 at NSZone.m:150
> 147 static void
> 148 default_free (NSZone *zone, void *ptr)
> 149 {
> -> 150 free(ptr);
> 151 }
> 152
> 153 static void
> (lldb) up
> frame #6: 0x00007ffff78c0d66
> libgnustep-base.so.1.25`NSZoneFree(zone=0x00007ffff7d7c608,
> ptr=0x00007fff288f7270) + 54 at NSZone.m:1792
> 1789 {
> 1790 if (!zone)
> 1791 zone = NSDefaultMallocZone();
> -> 1792 (zone->free)(zone, ptr);
> 1793 }
> 1794
> 1795 BOOL
> (lldb) up
> frame #7: 0x00007ffff77dd5ec
> libgnustep-base.so.1.25`NSDeallocateObject(anObject=0x00007fff288f7280) + 236
> at NSObject.m:705
> 702 else
> 703 {
> 704 object_setClass((id)anObject,
> (Class)(void*)0xdeadface);
> -> 705 NSZoneFree(z, o);
> 706 }
> 707 }
> 708 return;
> (lldb) up
> frame #8: 0x00007ffff77ddd4c libgnustep-base.so.1.25`-[NSObject
> dealloc](self=0x00007fff288f7280, _cmd="\x11") + 28 at NSObject.m:1195
> 1192 */
> 1193 - (void) dealloc
> 1194 {
> -> 1195 NSDeallocateObject (self);
> 1196 }
The -release method should have called objc_delete_weak_refs, which will have
cleared all weak pointers, while holding the lock held. Weak pointers are
materialised only while holding the lock.
David