gnustep-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Newbie back again...


From: Fred Kiefer
Subject: Re: Newbie back again...
Date: Sun, 23 Apr 2017 22:18:10 +0200

Thank you Josh,

this was an excellent analysis. Did you try to unset GNUSTEP_BASE_LIBRARY in 
NSGraphicsContext.m? That should switch to the other code path that won’t use 
internal structures from base.

As for the problem with the NSThread ivars. What has changed on your test 
system? Do you think the change in on the GNUstep side or was there a behaviour 
change in clang?

Fred


> Am 23.04.2017 um 09:39 schrieb Josh Freeman <address@hidden>:
> 
> Hi Bertrand,
> 
>   Thanks for the info! I'm seeing the same issue - after making a clean 
> GNUstep install from the trunk, any app built from it segfaults immediately, 
> always in the same location: +[NSGraphicsContext setCurrentContext:]. This is 
> on two different virtual machines, one with Ubuntu 16.04, the other with 
> Linux Mint MATE 18.1 (both up-to-date, 32-bit, Clang 3.8).
> 
>   I've tried a few different ways of installing GS, including some old 
> scripts that used to work, as well as the current "16.04 & 16.10" script from 
> the "GNUstep under Ubuntu Linux" wiki page. I also tried disabling blocks & 
> ARC, but still get the same problem: the apps (ProjectCenter, Gorm, 
> GWorkspace, SystemPreferences, PikoPixel) build fine, then crash when run.
> 
>   One thing that still works is building with GCC & its runtime, though this 
> means no blocks, ARC, etc. I've attached a modified version of the "16.04 & 
> 16.10" wiki script that builds successfully with gcc on both of my machines. 
> It doesn't have the 'sudo dpkg --add-architecture i386' line you added, so 
> you might need to put that in (though it might no longer be an issue with the 
> different runtime). Also, the script has libxft-dev uncapitalized, unlike 
> yours where it's libXft-dev (didn't work on Ubuntu/Mint), so you might need 
> to change it back for your machine.
> 
> 
>   Regarding the crashes, here's what I've figured out so far:
> 
> - The crash is from trying to send an objc message to a non-object.
> - The crash happens inside +[NSGraphicsContext setCurrentContext:] the first 
> time it's called.
> - Before crashing, setCurrentContext:'s local var, (NSThread *) th, is set to 
> the current thread (return value of GSCurrentThread()), which is a valid 
> object.
> - setCurrentContext:'s passed parameter value, (NSGraphicsContext *) context, 
> is also a valid object.
> - th's instance var, (id) _gcontext (pointer to the current graphics 
> context), however, contains a garbage value: 32.
> - The crash happens inside the macro, ASSIGN(th->_gcontext, context) - after 
> context is sent a retain message and stored in _gcontext, _gcontext's old 
> value (32, non-object) is sent a release message.
> 
>   * Where did the 32 come from?
> 
> - Looking at NSThread.h, the instance var immediately before _gcontext is 
> _autorelease_vars, an autorelease_thread_vars struct (5-member struct, 
> defined in NSAutoreleasePool.h).
> - When the [NSAutoreleasePool dealloc] method (NSAutoreleasePool.m:561) is 
> called (every time an autorelease pool drains), a pointer to the current 
> thread object's _autorelease_vars ivar struct is stored in dealloc's local 
> var, (struct autorelease_thread_vars *) tv.
> - dealloc passes tv to the local function, push_pool_to_cache() 
> (NSAutoreleasePool.m:106), where - if the struct needs initialization - tv is 
> then passed to another local function, init_pool_cache().
> - init_pool_cache() (NSAutoreleasePool.m:98) sets the value of one of tv's 
> struct members, (int) pool_cache_size, to the value 32.
> 
>   * How does the 32 move from _autorelease_vars to _gcontext?
> 
> - Looking at the autorelease_thread_vars definition in NSAutoreleasePool.h, 
> pool_cache_size is the second-to-last member in the struct, so it's quite 
> close in memory to its neighboring instance var, _gcontext: 8 bytes away, 
> assuming no extra padding.
> 
>   * How does an address pointer lose/gain 8 bytes?
> 
>   Somehow NSAutoreleasePool.m (in base) and NSGraphicsContext.m (in gui) are 
> in disagreement about the offsets to an NSThread object's instance vars: In 
> NSAutoreleasePool.m, the statement 
> (&((GSCurrentThread())->_autorelease_vars)) results in a memory address that 
> is less than sizeof(struct autorelease_thread_vars) away from the memory 
> address NSGraphicsContext.m calculates as the location of 
> GSCurrentThread()->_gcontext; When init_pool_cache() sets the current 
> thread's _autorelease_vars' pool_cache_size member near the end of the 
> struct, it's writing the value 32 to the same address later used by 
> setCurrentContext: as the current thread's _gcontext. (I verified this with a 
> gdb memory watchpoint).
> 
>   The crash in +[NSGraphicsContext setCurrentContext:] also goes away if you 
> add some extra padding bytes in the NSThread struct between _autorelease_vars 
> & _gcontext (not that that's a solution - it just postpones the crash to a 
> later point, in GSWindowDecorationView.m).
> 
>   So I think the ivar offsets disagreement is the condition that causes the 
> crash - any ideas what's causing the condition? Possibly a config issue 
> that's causing clang to use different struct padding settings between base & 
> gui?
> 
> Cheers,
> 
> Josh
> 
> 
> <install-current-gnustep-with-gcc.sh>
> 
> 
> 
> 
> On Apr 22, 2017, at 11:03 PM, Bertrand Gmail wrote:
> 
>> Preamble : sorry for the noise on gnustep-dev mailing list. I've reposted 
>> the messages here.
>> 
>> And...finally, it still doesn't work.
>> 
>> I thought that the problem had disappeared because I could compile and run a 
>> sample program given on the ubuntu installation notes on the gnustep wiki.
>> 
>> This is this program : guitest.m
>> 
>> #import <AppKit/AppKit.h> int main() { NSApplication *app; // Without these 
>> 2 lines, seg fault may occur app = [NSApplication sharedApplication]; 
>> NSAlert * alert = [[NSAlert alloc] init]; [alert setMessageText:@"Hello 
>> alert"]; [alert addButtonWithTitle:@"All done"]; int result = [alert 
>> runModal]; if (result == NSAlertFirstButtonReturn) { NSLog(@"First button 
>> pressed"); } }
>> 
>> 
>> This compiles and run fine it i use this command :
>> 
>> clang `gnustep-config --objc-flags` `gnustep-config --objc-libs` 
>> -fobjc-runtime=gnustep -fblocks -lobjc -fobjc-arc -ldispatch -lgnustep-base 
>> -lgnustep-gui guitest.m
>> 
>> But iif I use the following makefile to compile it (given in the wiki also), 
>> running GUItest.app will segfault :
>> 
>> GNUmakefile :
>> include \$(GNUSTEP_MAKEFILES)/common.make
>> 
>> APP_NAME = GUITest
>> GUITest_OBJC_FILES = guitest.m
>> 
>> include \$(GNUSTEP_MAKEFILES)/application.make
>> 
>> 
>> GUItest.app segfaults with this :
>> 
>> Program received signal SIGSEGV, Segmentation fault.
>> 
>> 0x00007ffff63cc500 in objc_msgSend_fpret ()
>> 
>> Backtrace attached.
>> 
>> Then every compilation of a program (projectcenter, gorm etc) fails.
>> 
>> I'm stuck.
>> 
>> I've attached my installation scripts again and the backtrace to this mail.
>> 
>> There seems to be some problem with the compilation options in my setup. 
>> This is way beyond my skills.
>> 
>> Cheers, Bertrand Dekoninck.
>> 
>> <my_install_gnustep_first_stage.sh><my_install_gnustep_second_stage.sh><backtrace.txt>_______________________________________________
>> Discuss-gnustep mailing list
>> address@hidden
>> https://lists.gnu.org/mailman/listinfo/discuss-gnustep
> 
> _______________________________________________
> Gnustep-dev mailing list
> address@hidden
> https://lists.gnu.org/mailman/listinfo/gnustep-dev




reply via email to

[Prev in Thread] Current Thread [Next in Thread]