View previous topic :: View next topic |
Author |
Message |
salamander
Joined: 24 May 2011 Posts: 11
|
Posted: Tue Dec 06, 2011 3:59 pm Post subject: Bug: DerelictSDL on Mac OS X 10.6.8 segfault upon exit |
|
|
Trying to got DerelictSDL working for Mac. I'm not sure what to do about this bug.
Mac OS X 10.6.8
Derelict2 (version... not sure.. downloaded ~Jun 2011)
dmd 2.052 (I don't think which dmd matters here, but anyway)
SDL version 1.2.14
I've narrowed my code (test.d) down to this:
Code: | import derelict.sdl.sdl;
//import derelict.sdl.macinit.SDLMain; // Might I need this???
import std.stdio;
int main(string[] args){
writeln("Test point number one");
DerelictSDL.load();
if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
throw new Exception("SDL initialization failed");
SDL_Surface* screen = SDL_SetVideoMode(/* height=*/64, /* width=*/480,
/* bitsPerPixel=*/32, SDL_SWSURFACE );
if (screen == null)
throw new Exception("Screen is null!");
// This screen flipping seems to cause the problem
if( SDL_Flip( screen ) == -1 )
throw new Exception("Didn't flip the screen!");
SDL_Quit();
writeln("Made it THIS far");
return 0;
} |
The program compiles fine and ALWAYS runs to the end. And SOMETIMES it finishes alright. But most of the times it actually finishes with a Segmentation fault or a Bus error, like so: (These are three consecutive runs on Terminal)
Code: | imac:zach$ ./test
Test point number one
Made it THIS far
Segmentation fault
imac:zach$ ./test
Test point number one
Made it THIS far
Bus error
imac:zd zach$ ./test
Test point number one
Made it THIS far
Segmentation fault |
The thread output is like so:
Code: |
Thread 0 Crashed: Dispatch queue: com.apple.main-thread
0 libobjc.A.dylib 0x93a12f8b objc_msgSend + 27
1 com.apple.AppKit 0x949bd4c6 -[NSCGSContext _invalidate] + 96
2 com.apple.AppKit 0x949bd43a -[NSCGSContext dealloc] + 39
3 com.apple.AppKit 0x949bd40b -[NSWindowGraphicsContext dealloc] + 78
4 com.apple.CoreFoundation 0x9a963eb8 CFRelease + 152
5 com.apple.CoreFoundation 0x9a990bcd _CFAutoreleasePoolPop + 253
6 com.apple.Foundation 0x98bc1976 NSPopAutoreleasePool + 76
7 com.apple.Foundation 0x98bc27d2 -[NSAutoreleasePool release] + 130
8 test 0x0000351f D8derelict3sdl7macinit17NSAutoreleasePool17NSAutoreleasePool7releaseMFZv + 55
9 test 0x00006a6f D8derelict3sdl7macinit7SDLMain12_staticDtor4FZv + 51
10 test 0x00004c8f _D8derelict3sdl7macinit7SDLMain9__moddtorFZv + 11
11 test 0x00011122 _moduleTlsDtor + 66
12 test 0x0001e8f4 D2rt6dmain24mainUiPPaZi6runAllMFZv + 76
13 test 0x0001e822 D2rt6dmain24mainUiPPaZi7tryExecMFMDFZvZv + 38
14 test 0x0001e7b3 main + 179
15 test 0x0000280d start + 53
|
Have you got any ideas what might be wrong here?
Thanks,
Zach |
|
Back to top |
|
|
aldacron
Joined: 05 May 2004 Posts: 1322 Location: Seoul, South Korea
|
|
Back to top |
|
|
aldacron
Joined: 05 May 2004 Posts: 1322 Location: Seoul, South Korea
|
Posted: Tue Dec 06, 2011 8:29 pm Post subject: |
|
|
Actually, looking at your code again I notice this:
Code: |
//import derelict.sdl.macinit.SDLMain; // Might I need this???
|
Yes, you do need this. If you uncomment that line, do you still get the bus error? _________________ The One With D | The One With Aldacron | D Bits |
|
Back to top |
|
|
salamander
Joined: 24 May 2011 Posts: 11
|
Posted: Wed Dec 07, 2011 1:30 pm Post subject: |
|
|
Yes, the Bus Error/Segmentation Fault continues to be interspersed with actually successful runs:
imac:zd zach$ ./test
Test point number one
Made it THIS far
imac:zd zach$ ./test
Test point number one
Made it THIS far
Segmentation fault
imac:zd zach$ ./test
Test point number one
Made it THIS far
Segmentation fault
imac:zd zach$ ./test
Test point number one
Made it THIS far
Bus error |
|
Back to top |
|
|
salamander
Joined: 24 May 2011 Posts: 11
|
Posted: Wed Dec 07, 2011 2:12 pm Post subject: |
|
|
Hey, aldacron! I found a solution, but I had to modify this file:
Derelict2/DerelictSDL/derelict/sdl/macinit/SDLMain.d
and remake Derelict2.
In the static destructor, (line ~111):
Code: | static ~this()
{
//The Bus Errors went away went I commented out
// one (or both) of these sets of lines:
// if(pool !is null)
// pool.release();
// if(sdlMain !is null)
// sdlMain.release;
DerelictSDLMac.unload();
}
|
Since the program is quitting anyway it doesn't seem like a crime to prevent the release of this memory. Plus, the type of is . I don't know much about programming Mac OSX, but it seems a little suspicious to be manually releasing something called NSAutorelease!
Anyway, my programs are running without a hitch since I recompiled. If this goes through it will be my first bug fix EVER!!!
Zach |
|
Back to top |
|
|
aldacron
Joined: 05 May 2004 Posts: 1322 Location: Seoul, South Korea
|
Posted: Thu Dec 08, 2011 6:55 am Post subject: |
|
|
Ah, that's great. Glad you found it. I don't have a Mac so I have no way to test this or anything. The Mac stuff was done by a regular contributor. On the surface, I don't see any problem with getting this fix in. But I do want to verify it won't cause anything to explode. _________________ The One With D | The One With Aldacron | D Bits |
|
Back to top |
|
|
aldacron
Joined: 05 May 2004 Posts: 1322 Location: Seoul, South Korea
|
Posted: Thu Dec 08, 2011 6:51 pm Post subject: |
|
|
Now I'm not so sure about this. I've dug around the original C source for SDLmain and read the docs for NSAutoRelease pool. Seems this is all right and proper. Plus, it's been working for a while now.
One thing I've noticed when binding with C libraries is that, sometimes, there are segfaults at program exit. I had a similar problem with the Allegro binding that I was never able to narrow down, but that went away just by moving some code around. I expect that was just a band aid and it will will pop up again later.
In this case, I think we need some more investigation. It's quite possible that the problem lies elsewhere and that commenting out those lines only hid it, rather than eliminating it. Unfortunately, since I don't have access to a Mac, there's nothing I can do about it myself.
Anyone? _________________ The One With D | The One With Aldacron | D Bits |
|
Back to top |
|
|
doob
Joined: 06 Jan 2007 Posts: 367
|
Posted: Mon Dec 12, 2011 4:15 am Post subject: |
|
|
I don't know if this will solve the problem or not but in D2 shouldn't the module constructors and destructors be shared, i.e.
Code: | shared static this () {}
shared static ~this () {}
|
|
|
Back to top |
|
|
aldacron
Joined: 05 May 2004 Posts: 1322 Location: Seoul, South Korea
|
|
Back to top |
|
|
salamander
Joined: 24 May 2011 Posts: 11
|
Posted: Sat Jan 07, 2012 11:04 pm Post subject: |
|
|
I tried:
shared static this(){...}
shared static ~this(){...}
They both segfault instantly - program doesn't even get started when ctor is shared.
This problem is pretty sucky. Everytime the app quits I have to click "Ignore - don't send a report to Apple". But it is fun using D and SDL together...
I'm not a good enough programmer yet to figure out how to approach this problem. |
|
Back to top |
|
|
aldacron
Joined: 05 May 2004 Posts: 1322 Location: Seoul, South Korea
|
|
Back to top |
|
|
salamander
Joined: 24 May 2011 Posts: 11
|
Posted: Sun Jan 08, 2012 4:19 pm Post subject: |
|
|
OK... new fix for this bug!
Go to DerelictSDL/derelict/sdl/macinit/SDLMain.d and search for all calls to any ".release" method and comment them out.
Searching the internet revealed that almost all errors of the NSAutoreleasePool.release type were due to trying to release previously released pointers. Since I'm having such problems with these bus errors I commented out every single call to .release in the file.
It's another fly-by-night answer, but I think it's getting closer. Someday I'll discover what's really going on here. Hopefully this fix won't break.
Zach |
|
Back to top |
|
|
aldacron
Joined: 05 May 2004 Posts: 1322 Location: Seoul, South Korea
|
Posted: Sun Jan 08, 2012 10:33 pm Post subject: |
|
|
Out of curiosity, in the module destructor of SDLMain.d (line 113) you see this:
Code: |
if(pool !is null)
pool.release();
if(sdlMain !is null)
sdlMain.release;
|
I'm wondering what would happen if you swap the order and release sdlMain before releasing the pool. Does that still result in the segfault? _________________ The One With D | The One With Aldacron | D Bits |
|
Back to top |
|
|
doob
Joined: 06 Jan 2007 Posts: 367
|
Posted: Mon Jan 09, 2012 3:03 pm Post subject: |
|
|
I've been trying quite a while now to find a solution for this problem but unfortunately I haven't.
Since the application will quit just after these "release" methods have been called and release any memory we might just as well skip the call to "release"? |
|
Back to top |
|
|
salamander
Joined: 24 May 2011 Posts: 11
|
Posted: Mon Jan 09, 2012 10:58 pm Post subject: |
|
|
Here's the thing. The docs for NSApplications say that the new Mac systems are garbage collected and that the release methods are supposed to be do-nothing operations. But obviously they are doing things here, otherwise they wouldn't crash the program.
Therefore it seems logical that SDLmain is linking to a legacy library which is set up to call release anyway. The one test I thought of for this would be to run a function 100,000 times which assigns but doesn't release and see if the program memory got permanently bigger, but I didn't want to go to such effort. But if it didn't get bigger you could do as much Mac-specific stuff knowing that it's all garbage-collected anyway.
I think it's all garbage collected anyway. So that would mean say goodbye to manual memory in both D AND MacOSX, which is pretty nifty if it's true. |
|
Back to top |
|
|
|