I did something similar on one of my first tries to find out what was going on and to fix this. I looked at the call stack and if there wasn't a ".cgi" file in the list then assumed I was in the "compile" stage and just returned. Not as elegent as using $^S but it worked. If I had to do something like this, I like the $^S way better now that I know about it.
In the end, I'd really like to know why I had to do anything like this. If we have code like:
package X;
BEGIN { whatever; }
$main::SIG{__DIE__} = \&some_function; # when does this get run?
sub new { ... }
In what phase is that SIG handler assigned? I would have thought it was in an implied INIT, but the code acts like it's in an implied BEGIN. I ended up solving the entire issue by putting that line in an explicit INIT block, but why did I have to do that?