Hi all,

I’ve opened a pull request with some very simple tests for the 
NSHashTable/NSMapTable weak object support:
https://github.com/gnustep/libs-base/pull/80 
<https://github.com/gnustep/libs-base/pull/80>

Unfortunately they are failing on the CI, so it seems that the issues described 
below are not specific to our setup. I also confirmed the tests pass when run 
against Apple’s Foundation.

Does anyone have knowledge of the weak pointer support in GNUstep and could 
take a look at this?

Thanks!
Frederik


> Am 07.10.2019 um 16:51 schrieb Frederik Seiffert <[email protected]>:
> 
> 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 = [NSObject new];
>             [_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 = [NSObject new];
>             [_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
> 

Reply via email to