Interesting SDL Parachute problem

Hi everyone. I have a project I’m working on that’s using SDL as
(among other things) a front-end to another application. The SDL window
disappears when this other application is launched. I’ve been using
Java along with an SDL JNI binding that I wrote a little while back. To
make the SDL window go away temporarily, I simply quit SDL - then when I
need the window to open up again, I re-initialize SDL and reload all of
my graphics, etc.

The problem is that when SDL_Quit is called, it also calls

SDL_UninstallParachute, even though I initialize SDL with the
no-parachute flag. This is fine, since the code seems to attempt to put
back any signal handlers that were already installed (unless the
previous handler was SDL_Parachute).

However, from my experience with what I'm doing now, this doesn't

exactly…well…work. :slight_smile: It appears that the JVM is installing its own
signal handlers, in particular a seg fault handler. So the following
(very stupid) Java code will throw a NullPointerException:

int [][] dumbass = new int[32][];
int temp = dumbass[0][0];

If I run the above code prior to calling SDL_Quit(), it throws the

exception. However, if I run the code after calling SDL_Quit(), the JVM
explodes, throwing shrapnel in all directions.

If I comment out SDL_UninstallParachute() in the SDL sources and

recompile, then everything works fine. Note that if I make
SDL_UninstallParachute() set all of the signal handlers back to SIG_DFL,
then the JVM simply seg faults relatively quietly, rather than exploding
into little chunks. I’m not 100% sure what the difference might be -
but was hoping someone would have a theory.

Anyone have any thoughts on this?  I'm happy to write a simple sample

program or post code if it will help. I have an easy workaround for the
problem, which is to call SDL_QuitSubsystem(SDL_INIT_EVERYTHING) instead
of SDL_Quit in my JNI code - but I’m just really curious about this and
can’t figure it out.

Thanks!

Eric Wittmann
wittmann at snet.net

int [][] dumbass = new int[32][];
int temp = dumbass[0][0];

I’m surprise that the JVM is catching a segfault instead of range
checking. Have you tried disabling the JIT? Obviously, that’s not a good
solution, but I’m just curious.

Anyone have any thoughts on this? I’m happy to write a simple sample
program or post code if it will help. I have an easy workaround for the
problem, which is to call SDL_QuitSubsystem(SDL_INIT_EVERYTHING) instead
of SDL_Quit in my JNI code - but I’m just really curious about this and
can’t figure it out.

Probably doesn’t like others playing with its signal handlers. :slight_smile:

It might be worth adding an internal flag to SDL that is set if
SDL_INIT_NOPARACHUTE is used so that we know to not to call
SDL_UninstallParachute() in those cases. While the function looks kosher
at first glance, it seems like unnecessary work to determine something we
should already know.

Here’s the patch, if this is in fact a good idea. :slight_smile:

(It compiles here, but that’s as far as I’ve tested it.)

–ryan.

[icculus at gemini ~/projects/SDL12]$ cvs diff -u src/SDL_fatal.c
Index: src/SDL_fatal.c===================================================================
RCS file: /home/slouken/libsdl.org/cvs/SDL12/src/SDL_fatal.c,v
retrieving revision 1.3
diff -u -r1.3 SDL_fatal.c
— src/SDL_fatal.c 2001/12/14 12:37:57 1.3
+++ src/SDL_fatal.c 2002/02/08 07:03:20
@@ -125,11 +125,16 @@
0
};

+static int SDL_parachute_installed = 0;
+
void SDL_InstallParachute(void)
{
int i;
void (*ohandler)(int);

  • if (SDL_parachute_installed)
  •   return;
    
  • /* Set a handler for any fatal signal not already handled */
    for ( i=0; SDL_fatal_signals[i]; ++i ) {
    ohandler = signal(SDL_fatal_signals[i], SDL_Parachute);
    @@ -153,6 +158,8 @@
    }
    }
    #endif
  • SDL_parachute_installed = 1;
    return;
    }

@@ -161,6 +168,9 @@
int i;
void (*ohandler)(int);

  • if (!SDL_parachute_installed)
  •   return;
    
  • /* Remove a handler for any fatal signal handled */
    for ( i=0; SDL_fatal_signals[i]; ++i ) {
    ohandler = signal(SDL_fatal_signals[i], SIG_DFL);
    @@ -168,6 +178,8 @@
    signal(SDL_fatal_signals[i], ohandler);
    }
    }
  • SDL_parachute_installed = 0;
    }

#endif /* NO_SIGNAL_H */

I’m surprise that the JVM is catching a segfault instead of range
checking. Have you tried disabling the JIT? Obviously, that’s not a good
solution, but I’m just curious.

Well, it DOES do range checking when the array is actually defined.  

However, when you have an array defined as in the example…

int [][] blah = new int[32][];

...then presumably the JVM has allocated an array of 32 int pointers (I 

don’t know, but it seems a good guess). (Actually, it’s more likely that the
JVM allocates an array of size 33 and puts the length of the array either at
the beginning or the end, for use in range checking) In the case that you then
try to access the 2D array using blah[0][0], it probably tries to figure out
the length of the array blah[0], but blah[0] is a NULL pointer. Wham - seg
fault. :slight_smile: Just a guess, but it seems reasonable.

Probably doesn’t like others playing with its signal handlers. :slight_smile:

So it would seem.  :)  Still, one would think that putting them back should 

make everything ok again. In any case, I’d definitely agree with your idea of
simply remembering whether the SDL parachute was installed. That way should
always work. In any case, the workaround is simple, so I’m no rush for a fix -
just thought I’d mention it on the list anyway.

thanks!

Eric Wittmann
ericw at mirrorworlds.com