On Dec 22, 2017, at 10:05 AM, Richard Frith-Macdonald wrote:
I think that's a possible indication of a bug in the compiler/ runtime nonfragile API support; it looks as if there may be an inconsistency in calculating the size of a structure used as an ivar.
After more testing, here's some additional info that might be useful:
-- Hardware (virtual): Clean, up-to-date Ubuntu 16.04 VM, 32bit-- GNUstep install: Used the current Ubuntu script from the wiki, with two changes: - Removed the script's workaround for the ivar-offset issue (so it builds using the current version of gnustep-make instead of an old version). - Built a version of gnustep-base from a couple days ago (Dec. 19) which still used the obsolete -fobjc-nonfragile-abi build flag. (As previously mentioned, the current version of base won't build with the Ubuntu script if the script's ivar-offset workaround is removed).
-- Attachments:Attached are 2 patches that print info about NSThread ivars at runtime, and 2 debugging-session outputs that were run with patches installed. The patches assume that the libs-base & libs-gui directories are in the same parent directory as the libobjc2 directory (as they are when running the Ubuntu script), because the patches add an #import "../../libobjc2/ivar.h" in order to use the runtime's ivar & ivar_list types.
The patches - one for base, and one for gui - each add a static C function that prints out the objc-runtime's NSThread ivar layout, obtained using the runtime API function, class_getIvarLayout(). The patch function also prints the locations in memory of the current thread's instance members, obtained using statements like: &thread- >_gcontext.
The base patch adds the diagnostic function to NSAutoreleasePool.m, & calls it from -[NSAutorelease dealloc] before the NSThread's _autorelease_vars is modified (which will leave a garbage value in _gcontext). The gui patch adds a matching function to NSGraphicsContext.m & calls it from -[NSGraphicsContext setCurrentContext:] before it frees the garbage value in _gcontext & segfaults.
The first output file, patched_base_session_output.txt, is the result of installing only the base patch & running a debug session.
The second output file, patched_base_and_gui_session_output.txt, is a followup session after also installing the gui patch. In this session, gnustep-base (previously patched) was not rebuilt, so base is the same binary as the first session.
-- Output summary:In the first session (patched_base_session_output.txt), the diagnostic output shows most of the NSThread members' addresses line up with the runtime's ivar layout - up until the first member after the _autorelease_vars struct, _gcontext.
The runtime's ivar-layout offset for NSThread's _autorelease_vars member is 44, and _gcontext's is 64. The 20-byte space for _autorelease_vars is the smallest possible size for that struct on 32bit, as the struct is made up of 5 members, each of which is 4 bytes (3 ints & 2 pointers - see struct autorelease_thread_vars definition in NSAutoreleasePool.h).
However, the memory address of thread->_gcontext is offset from the thread instance's address by 56 - not the 64 listed by the runtime API - which is only 12 bytes away from thread->_autorelease_vars. At that offset value, _gcontext occupies the same memory location as the _autorelease_vars struct member, pool_cache_size; When pool_cache_size is set in NSAutoreleasePool.m (base), the same value will be accessed later in NSGraphicsContext.m (gui) as _gcontext, causing a crash due to sending an objc message to a non-nil garbage value.
In the second session (patched_base_and_gui_session_output.txt), the NSThread ivar diagnostics are also printed from within gui. Two notes:
1) I had thought the "ivar-offset" issue was due to a mismatch between gui & base ivar offsets (gui using a different offset to _gcontext than base), but the output shows that this is not the case: gui & base actually match each other's objc2-runtime ivar layouts and also have matching memory addresses returned from &thread->member statements; The mismatch is between the runtime's ivar layout and the memory addresses returned by &thread->member statements.
2) NSThread's ivar layout (obtained from the runtime API) was the same between the first & second sessions. This was expected, because the only change made between sessions was to add a static C function to NSGraphicsContext.m, and a call to it from -[NSGraphicsContext setCurrentContext:].
Unexpectedly, the memory locations of NSThread members (as obtained from &thread->member statements) did change between the two sessions, and not just in gui, which was recompiled - it also changed in base, even though it was the same binary in both sessions.
The first session had memory address offsets (obtained from &thread->member statements) for _autorelease_vars & _gcontext at 44 & 56, respectively; In the second session, those members' offsets were 36 & 56 (_gcontext stayed in the same place, _autorelease_vars shifted 8 bytes down, and now both members' addresses disagreed with the runtime's ivar layout offsets of 44 & 64).
The changed offsets also changed the location of the crash, because the in the second session, _autorelease_vars & _gcontext were separated by 20 bytes instead of 12 bytes, so they no longer overlapped. Subsequently, the call to -[NSGraphicsContext setCurrentContext:] (where the first session crashed) returned successfully, because _gcontext wasn't overwritten by a garbage value when writing pool_cache_size. (The crash happened at a later point, in -[GSWindowDecorationView layout]; Stack trace is in the output file).
Hope this helps track down the issue. Cheers, JoshP.S Using the current Ubuntu script unmodified (leaving the workaround in place) still works fine - everything builds, and no crashes when starting apps.
BASE:
class_getIvarLayout([NSThread class])
_target : 4
_arg : 8
_selector : 12
_name : 16
_stackSize : 20
_cancelled : 24
_active : 25
_finished : 26
_exception_handler : 28
_thread_dictionary : 32
_autorelease_vars : 44
_gcontext : 64
_runLoopInfo : 68
_internal : 72
Current thread from GSCurrentThread(): 0x813b51c
thread->_target: 0x813b520 (4)
thread->_arg: 0x813b524 (8)
thread->_selector: 0x813b528 (12)
thread->_name: 0x813b52c (16)
thread->_stackSize: 0x813b530 (20)
thread->_cancelled: 0x813b534 (24)
thread->_active: 0x813b535 (25)
thread->_finished: 0x813b536 (26)
thread->_exception_handler: 0x813b538 (28)
thread->_thread_dictionary: 0x813b53c (32)
thread->_autorelease_vars: 0x813b548 (44)
thread->_gcontext: 0x813b554 (56)
thread->_runLoopInfo: 0x813b560 (68)
Program received signal SIGSEGV, Segmentation fault.
0xb6e4f3bc in objc_msgSend () from
/usr/GNUstep/Local/Library/Libraries/libobjc.so.4.6
(gdb) bt
#0 0xb6e4f3bc in objc_msgSend () from
/usr/GNUstep/Local/Library/Libraries/libobjc.so.4.6
#1 0xb77fbf06 in +[NSGraphicsContext setCurrentContext:] (self=0xb7b9bf2c
<_OBJC_CLASS_NSGraphicsContext>,
_cmd=0xb7b6607c <.objc_selector_list+792>, context=0x82aa05c) at
NSGraphicsContext.m:221
#2 0xb771ee0d in -[NSApplication _init] (self=0x827b1c4, _cmd=0xb7b663fc
<.objc_selector_list+1688>) at NSApplication.m:892
#3 0xb711fc58 in -[NSObject performSelector:withObject:] (self=0x827b1c4,
_cmd=0xb7450acc <.objc_selector_list+280>,
aSelector=0xb7b663fc <.objc_selector_list+1688>, anObject=0x827b1c4) at
NSObject.m:1980
#4 0xb71b4f0f in -[NSObject(NSThreadPerformAdditions)
performSelector:onThread:withObject:waitUntilDone:modes:] (self=0x827b1c4,
_cmd=0xb7450bac <.objc_selector_list+504>, aSelector=0xb7b663fc
<.objc_selector_list+1688>, aThread=0x813b51c,
anObject=0x827b1c4, aFlag=1 '\001', anArray=0x827b29c) at NSThread.m:1672
#5 0xb71b4b8c in -[NSObject(NSThreadPerformAdditions)
performSelectorOnMainThread:withObject:waitUntilDone:modes:] (
self=0x827b1c4, _cmd=0xb7450b4c <.objc_selector_list+408>,
aSelector=0xb7b663fc <.objc_selector_list+1688>, anObject=0x827b1c4,
aFlag=1 '\001', anArray=0x827b29c) at NSThread.m:1627
#6 0xb71b4c31 in -[NSObject(NSThreadPerformAdditions)
performSelectorOnMainThread:withObject:waitUntilDone:] (self=0x827b1c4,
_cmd=0xb7b6634c <.objc_selector_list+1512>, aSelector=0xb7b663fc
<.objc_selector_list+1688>, anObject=0x827b1c4, aFlag=1 '\001')
at NSThread.m:1638
#7 0xb771f44d in -[NSApplication init] (self=0x827b1c4, _cmd=0x80604d4
<.objc_selector_list+1344>) at NSApplication.m:978
#8 0x0804d1f6 in -[Gorm init] (self=0x827b1c4, _cmd=0xb7b66164
<.objc_selector_list+1024>) at Gorm.m:89
#9 0xb771ebdf in +[NSApplication sharedApplication] (self=0x805fc8c
<_OBJC_CLASS_Gorm>, _cmd=0xb7b5c120 <.objc_selector_list+96>)
at NSApplication.m:850
#10 0xb76f39d5 in NSApplicationMain (argc=1, argv=0xbfffe014) at Functions.m:78
#11 0x0805425a in main (argc=1, argv=0xbfffe014) at main.m:30
(gdb)BASE:
class_getIvarLayout([NSThread class])
_target : 4
_arg : 8
_selector : 12
_name : 16
_stackSize : 20
_cancelled : 24
_active : 25
_finished : 26
_exception_handler : 28
_thread_dictionary : 32
_autorelease_vars : 44
_gcontext : 64
_runLoopInfo : 68
_internal : 72
Current thread from GSCurrentThread(): 0x813b51c
thread->_target: 0x813b520 (4)
thread->_arg: 0x813b524 (8)
thread->_selector: 0x813b528 (12)
thread->_name: 0x813b52c (16)
thread->_stackSize: 0x813b530 (20)
thread->_cancelled: 0x813b534 (24)
thread->_active: 0x813b535 (25)
thread->_finished: 0x813b536 (26)
thread->_exception_handler: 0x813b538 (28)
thread->_thread_dictionary: 0x813b53c (32)
thread->_autorelease_vars: 0x813b540 (36)
thread->_gcontext: 0x813b554 (56)
thread->_runLoopInfo: 0x813b558 (60)
GUI:
class_getIvarLayout([NSThread class])
_target : 4
_arg : 8
_selector : 12
_name : 16
_stackSize : 20
_cancelled : 24
_active : 25
_finished : 26
_exception_handler : 28
_thread_dictionary : 32
_autorelease_vars : 44
_gcontext : 64
_runLoopInfo : 68
_internal : 72
Current thread from GSCurrentThread(): 0x813b51c
thread->_target: 0x813b520 (4)
thread->_arg: 0x813b524 (8)
thread->_selector: 0x813b528 (12)
thread->_name: 0x813b52c (16)
thread->_stackSize: 0x813b530 (20)
thread->_cancelled: 0x813b534 (24)
thread->_active: 0x813b535 (25)
thread->_finished: 0x813b536 (26)
thread->_exception_handler: 0x813b538 (28)
thread->_thread_dictionary: 0x813b53c (32)
thread->_autorelease_vars: 0x813b540 (36)
thread->_gcontext: 0x813b554 (56)
thread->_runLoopInfo: 0x813b558 (60)
Program received signal SIGSEGV, Segmentation fault.
0xb6e4f3bc in objc_msgSend () from
/usr/GNUstep/Local/Library/Libraries/libobjc.so.4.6
(gdb) bt
#0 0xb6e4f3bc in objc_msgSend () from
/usr/GNUstep/Local/Library/Libraries/libobjc.so.4.6
#1 0xb7a4877c in -[GSWindowDecorationView layout] (self=0x8393b1c,
_cmd=0xb7c4a244 <.objc_selector_list+344>)
at GSWindowDecorationView.m:284
#2 0xb7a49a58 in -[GSWindowDecorationView setFrame:] (self=0x8393b1c,
_cmd=0xb7c1150c <.objc_selector_list+2256>, frameRect=...)
at GSWindowDecorationView.m:413
#3 0xb799a99e in -[NSWindow sendEvent:] (self=0x838cc5c, _cmd=0xb448f3b8
<.objc_selector_list+880>, theEvent=0x83a8a64)
at NSWindow.m:4155
#4 0xb444a0a4 in -[XGServer(WindowOps) placewindow::] (self=0x825bcc4,
_cmd=0xb7c116cc <.objc_selector_list+2704>, rect=..., win=1)
at XGServerWindow.m:3269
#5 0xb7990eb9 in -[NSWindow setFrame:display:] (self=0x838cc5c,
_cmd=0xb7b66124 <.objc_selector_list+960>, frameRect=...,
flag=1 '\001') at NSWindow.m:2266
#6 0xb7729799 in -[NSApplication(Private) _appIconInit] (self=0x827b1c4,
_cmd=0xb7b666c4 <.objc_selector_list+2400>)
at NSApplication.m:3847
#7 0xb771f438 in -[NSApplication _init] (self=0x827b1c4, _cmd=0xb7b663fc
<.objc_selector_list+1688>) at NSApplication.m:924
#8 0xb711fc58 in -[NSObject performSelector:withObject:] (self=0x827b1c4,
_cmd=0xb7450acc <.objc_selector_list+280>,
aSelector=0xb7b663fc <.objc_selector_list+1688>, anObject=0x827b1c4) at
NSObject.m:1980
#9 0xb71b4f0f in -[NSObject(NSThreadPerformAdditions)
performSelector:onThread:withObject:waitUntilDone:modes:] (self=0x827b1c4,
_cmd=0xb7450bac <.objc_selector_list+504>, aSelector=0xb7b663fc
<.objc_selector_list+1688>, aThread=0x813b51c,
anObject=0x827b1c4, aFlag=1 '\001', anArray=0x827b29c) at NSThread.m:1672
#10 0xb71b4b8c in -[NSObject(NSThreadPerformAdditions)
performSelectorOnMainThread:withObject:waitUntilDone:modes:] (
self=0x827b1c4, _cmd=0xb7450b4c <.objc_selector_list+408>,
aSelector=0xb7b663fc <.objc_selector_list+1688>, anObject=0x827b1c4,
aFlag=1 '\001', anArray=0x827b29c) at NSThread.m:1627
#11 0xb71b4c31 in -[NSObject(NSThreadPerformAdditions)
performSelectorOnMainThread:withObject:waitUntilDone:] (self=0x827b1c4,
_cmd=0xb7b6634c <.objc_selector_list+1512>, aSelector=0xb7b663fc
<.objc_selector_list+1688>, anObject=0x827b1c4, aFlag=1 '\001')
at NSThread.m:1638
#12 0xb771f82d in -[NSApplication init] (self=0x827b1c4, _cmd=0x80604d4
<.objc_selector_list+1344>) at NSApplication.m:978
#13 0x0804d1f6 in -[Gorm init] (self=0x827b1c4, _cmd=0xb7b66164
<.objc_selector_list+1024>) at Gorm.m:89
#14 0xb771efbf in +[NSApplication sharedApplication] (self=0x805fc8c
<_OBJC_CLASS_Gorm>, _cmd=0xb7b5c120 <.objc_selector_list+96>)
at NSApplication.m:850
#15 0xb76f3db5 in NSApplicationMain (argc=1, argv=0xbfffe014) at Functions.m:78
#16 0x0805425a in main (argc=1, argv=0xbfffe014) at main.m:30
(gdb)
base-NSThread-diagnostic.diff
Description: Binary data
gui-NSThread-diagnostic.diff
Description: Binary data
_______________________________________________ Discuss-gnustep mailing list [email protected] https://lists.gnu.org/mailman/listinfo/discuss-gnustep
