Am 07.10.2019 um 16:51 schrieb Frederik Seiffert
<frederik@algoriddim.com <mailto:frederik@algoriddim.com>>:
Hi David,
While replacing the hash table, I managed to turn it into a
reproduceable fault on at least one machine. The bug is quite subtle:
We have a map from objects to weak reference structures.
The weak reference structure points to the object.
When we delete the last weak reference, we delete the object from the
map.
We delete the object from the map using the object as the key.
But by the time a weak reference is deallocated, its object pointer
has been zeroed...
...so we always remove a random element from the map and leave a
dangling pointer in the table.
Should this already be fixed on the latest libobjc2 master?
Going back to my original issue about NSHashTable with weak objects,
I’m still seeing it crash with the latest libobjc2 master and also
using the arc-cxx branch.
It reproduces quite easily with the following code (compiled with
ARC), which crashes either directly in addObject: on the first
invocation (when using weakObjectsHashTable), or in -allObjects on the
second or third invocation (when using hashTableWithWeakObjects).
static __strong NSHashTable *_hashTable = nil;
static __strong NSObject *_test = nil;
- (void)testHashTable
{
@autoreleasepool {
if (!_hashTable) {
_hashTable = [NSHashTable weakObjectsHashTable];// or
hashTableWithWeakObjects
_test = [NSObjectnew];
[_hashTable addObject:_test];// crash 1
}else {
_test =nil;
}
NSLog(@"HashTable %@ (_test: %@)", _hashTable.allObjects, _test);//
crash 2
}
}
Similarly, NSMapTable crashes as well in the second invocation of the
following function, although I’m not sure if this is the same root
cause as the hash table crash:
static __strong NSMapTable *_mapTable = nil;
static __strong NSObject *_test = nil;
- (void)testMapTable
{
@autoreleasepool {
if (!_mapTable) {
_mapTable = [NSMapTable strongToWeakObjectsMapTable];
_test = [NSObjectnew];
[_mapTable setObject:_test forKey:@"test"];
}else {
NSLog(@"obj pre: %@", [_mapTable objectForKey:@"test"]);// crash!!!
_test =nil;
NSLog(@"obj post: %@", [_mapTable objectForKey:@"test"]);
}
NSLog(@"MapTable %@ (_test: %@)", _mapTable.dictionaryRepresentation,
_test);
}
}
I’m pasting the stack traces below. I’d appreciate if anyone can shed
some light on this.
Thanks!
Frederik
*NSHashTable crash using weakObjectsHashTable:*
* frame #0: 0xeca8c1d0 libart.so`art_sigsegv_fault
frame #1: 0xeca8c774 libart.so`art::FaultManager::HandleFault(int,
siginfo*, void*) + 372
frame #2: 0xeca8c49b libart.so`art::art_fault_handler(int,
siginfo*, void*) (.llvm.650222801) + 43
frame #3: 0x625bd6af
app_process32`___lldb_unnamed_symbol22$$app_process32 + 623
frame #4: 0xefee7c50 libc.so`___lldb_unnamed_symbol2$$libc.so + 1
frame #5: 0xd1e56762 libobjc.so`objc_msgSend at
objc_msgSend.x86-32.S:120
frame #6: 0xd14f69cd
libgnustep-base.so`hashObject(item=0xcf40c100, size=0x00000000) at
NSConcretePointerFunctions.m:126
frame #7: 0xd1400a72
libgnustep-base.so`pointerFunctionsHash(PF=0xd0ea7900,
item=0xcf40c100) at NSConcretePointerFunctions.h:180
frame #8: 0xd13fd9b6
libgnustep-base.so`GSIMapBucketForKey(map=0xd0ea78d4, key=GSIMapKey @
0xff99f2a4) at GSIMap.h:410
frame #9: 0xd1400ce3
libgnustep-base.so`GSIMapAddNodeToMap(map=0xd0ea78d4, node=0xcf40c0f0)
at GSIMap.h:453
frame #10: 0xd13fcb64
libgnustep-base.so`GSIMapAddKey(map=0xd0ea78d4, key=GSIMapKey @
0xff99f334) at GSIMap.h:1118
frame #11: 0xd13fe82f libgnustep-base.so`-[NSConcreteHashTable
addObject:](self=0xd0ea78d4, _cmd="C", anObject=0xd0efd14c) at
NSConcreteHashTable.m:848
frame #12: 0xd1e2e7ff libnative-lib.so`::-[ObjectiveCTest
testHashTable](self=0xcf40c0e4, _cmd="V\x1c") at ObjectiveCTest.mm:78
*NSHashTable crash using hashTableWithWeakObjects:*
* frame #0: 0xeca8c1d0 libart.so`art_sigsegv_fault
frame #1: 0xeca8c774 libart.so`art::FaultManager::HandleFault(int,
siginfo*, void*) + 372
frame #2: 0xeca8c49b libart.so`art::art_fault_handler(int,
siginfo*, void*) (.llvm.650222801) + 43
frame #3: 0x625bd6af
app_process32`___lldb_unnamed_symbol22$$app_process32 + 623
frame #4: 0xefee7c50 libc.so`___lldb_unnamed_symbol2$$libc.so + 1
frame #5: 0xd1ea975d libobjc.so`objc_msgSend at
objc_msgSend.x86-32.S:120
frame #6: 0xd13170bd libgnustep-base.so`-[GSInlineArray
initWithObjects:count:](self=0xcf4fd184, _cmd="\xffffff81",
objects=0xff99f320, count=1) at GSArray.m:420
frame #7: 0xd131a41d libgnustep-base.so`-[GSPlaceholderArray
initWithObjects:count:](self=0xcf4fd184, _cmd="\xffffff81",
objects=0xff99f320, count=1) at GSArray.m:1199
frame #8: 0xd13c2b80 libgnustep-base.so`-[NSConcreteHashTable
allObjects](self=0xd0da9a14, _cmd="m\x02") at NSConcreteHashTable.m:875
frame #9: 0xd1df7844 libnative-lib.so`::-[ObjectiveCTest
testHashTable](self=0xcf391444, _cmd="V\x1c") at ObjectiveCTest.mm:84
*NSMapTable crash:*
* frame #0: 0xeca8c1d1 libart.so`art_sigsegv_fault + 1
frame #1: 0xeca8c774 libart.so`art::FaultManager::HandleFault(int,
siginfo*, void*) + 372
frame #2: 0xeca8c49b libart.so`art::art_fault_handler(int,
siginfo*, void*) (.llvm.650222801) + 43
frame #3: 0x625bd6af
app_process32`___lldb_unnamed_symbol22$$app_process32 + 623
frame #4: 0xefee7c50 libc.so`___lldb_unnamed_symbol2$$libc.so + 1
frame #5: 0xd1e29c6d
libobjc.so`::objc_retainAutoreleasedReturnValue(id) [inlined]
isPersistentObject(obj=0xd0bfb27c) at arc.mm:291
frame #6: 0xd1e29c66
libobjc.so`::objc_retainAutoreleasedReturnValue(id) [inlined]
retain(obj=0xd0bfb27c) at arc.mm:296
frame #7: 0xd1e29c66
libobjc.so`::objc_retainAutoreleasedReturnValue(id) [inlined]
objc_retain(obj=0xd0bfb27c) at arc.mm:587
frame #8: 0xd1e29c62
libobjc.so`::objc_retainAutoreleasedReturnValue(obj=0xd0bfb27c) at
arc.mm:581
frame #9: 0xd1175a04 libnative-lib.so`::-[ObjectiveCTest
testMapTable](self=0xcf66c064, _cmd="X\x1c") at ObjectiveCTest.mm:97