qa-float crash

Started by newdep, September 22, 2009, 03:17:55 AM

Previous topic - Next topic

newdep

#30
this is what i mean, except in newlisp It stays on 1..it seems...

Is there extra memory management done somewhere?







#include <stdio>
#include <float>
#include <signal>
#include <math>
#include <setjmp>

/* testing NaN and Inf return */


/* store stack */
jmp_buf errorJump;

int errorReg = 0;

void signal_handler(int sig)
{
/* init */
signal(SIGFPE, signal_handler);

switch(sig)
{
case SIGFPE:
/* signal(SIGFPE,SIG_DFL); */
printf("%s", "SIGFPE!n");
longjmp(errorJump,errorReg);
break;
default: return;
}

}

int main ()
{
double nfloat;

printf("errorReg=%dn", errorReg);

errorReg = setjmp(errorJump);
signal(SIGFPE, signal_handler);
printf("errorReg=%dn", errorReg);

nfloat /= 0;
printf("div=%fn",  nfloat );

errorReg = setjmp(errorJump);
printf("errorReg=%dn", errorReg);

nfloat = (sqrt (-1));
printf("sqrt=%fn", nfloat );

errorReg = setjmp(errorJump);
printf("errorReg=%dn", errorReg);

nfloat = (log (0));
printf("log=%fn", nfloat );

}





outputs ->


[E:PROGNLnewlisp-10.1.6]f
errorReg=0
errorReg=0
SIGFPE!
errorReg=1
div=inf
errorReg=0
sqrt=nan
errorReg=0
log=-inf
-- (define? (Cornflakes))

Lutz

#31
this all doesn't make sense to me ;-)



The following



- longjmp() doesn't return anything is void longjmp()

- setjmp() returns whatever the second arg of longjmp() was

- errorReg is always set to the return value of setjmp()



I think yor are saying is, that SIGFPE when it occurs needs a longjmp() to restore the stack environment saved previously with setjmp() in errorJump. That would be then the newlisp-reset-entry-point. So SIGFPE would always cause a reset and take newLISP to the command line.



just send me the your changed newlisp.c, perhaps then it makes more sense to me.



EDITt: didn't see you last post while writing this, now I understand, how you think errorReg is set.



But here a totally different approach:

=======================



in setupAllSignals(void) all signals do:


#ifdef OS2
setupSignalHandler(SIGFPE, SIG_IGN);
#endif


this tells OS/2 to simply ignore this exception. It may not let you do this overwrite, but we can try. In this case you can remove all other OS/2 specific signal code.

newdep

#32
yes that would fit the GNU systems behaviour of SIGFPE.... let me try that...

btw I did try that previously but with the sigfpe stillinside the sigal_handler..(aaaggg)



lets see..
-- (define? (Cornflakes))

newdep

#33
No..its doesnt eat it...

the SIGFPE needs to be triggered to catch the NaN's and Inf's it seems..
-- (define? (Cornflakes))

newdep

#34
Quote from: "Lutz"


The following



- longjmp() doesn't return anything is void longjmp()

- setjmp() returns whatever the second arg of longjmp() was

- errorReg is always set to the return value of setjmp()




I make a correction to the above actualy..



Its correct because a longjmp doesnt return, but ! ->



setjmp always return != 0 when there was a previous longjmp,

not what longjmp had as second argument.
-- (define? (Cornflakes))

Lutz

#35
Nope! From the man page of longjmp():



"Returns 0 after saving the stack environment. If setjmp() returns as a result of a longjmp() call, it returns the value argument of longjmp(), or if the value argument of longjmp() is 0, setjmp() returns 1."



That means setjmp() does return the second arg of longjmp(), except when that arg was 0, then setjmp() returns 1.



For that reason I wanted you to try longjmp(errorJmp, 0) in the error handler earlier.



Also, when you do this:
Quote
if((errorReg = setjmp(errorJump)) != 0)
    {
    if(errorReg && (errorEvent != nilSymbol) )
        executeSymbol(errorEvent, NULL, NULL);
    else exit(-1);
    goto AFTER_ERROR_ENTRY;
    }

errorReg = setjmp(errorJump); <=== will suppress all error messages
setupAllSignals();


You effectively suppress all error messages, because the jump buffer is now set to that point with no error treatment when an error occured. It will then just drop into the command line without error messages.



That line has to go, we have to make OS/2 FP work without it.

newdep

#36
Quote from: "Lutz"Nope! From the man page of longjmp():



"Returns 0 after saving the stack environment. If setjmp() returns as a result of a longjmp() call, it returns the value argument of longjmp(), or if the value argument of longjmp() is 0, setjmp() returns 1."



That means setjmp() does return the second arg of longjmp(), except when that arg was 0, then setjmp() returns 1.



For that reason I wanted you to try longjmp(errorJmp, 0) in the error handler earlier.



Also, when you do this:
Quote
if((errorReg = setjmp(errorJump)) != 0)
    {
    if(errorReg && (errorEvent != nilSymbol) )
        executeSymbol(errorEvent, NULL, NULL);
    else exit(-1);
    goto AFTER_ERROR_ENTRY;
    }

errorReg = setjmp(errorJump); <=== will suppress all error messages
setupAllSignals();


You effectively suppress all error messages, because the jump buffer is now set to that point with no error treatment when an error occured. It will then just drop into the command line without error messages.



That line has to go, we have to make OS/2 FP work without it.


Aha..That dusty UNIX programming book of mine will now go into the bin basket! (its from 1987...uhum...)

Ill stick with the manpages ;-)





I suspected that indeed with the extra setjmp, I dont like it that way eighter...

Yes lets stick with the code as it is now...



The odd thing that keeps me awake..is my C-example versus the newlisp code.



What I could do is extract the SIGFPE from the generic handler in newlisp?

perhpas that helps.. thats the only thing i did not do yet..

And newlisp has more longjmp's and setjmp's and an explicit check on 0 or 1 on the

setjmp..
-- (define? (Cornflakes))

Lutz

#37
QuoteWhat I could do is extract the SIGFPE from the generic handler in newlisp?


Yes, this is done for other signals on Sun OS, Tru64 and IBM Aix. E.g:


#ifdef OS2
void specialOS2_handler(int s)
{
/* Norman's OS/2 stuff */
}

setupSignalHandler(SIGFPE, specialOS2_handler);
#endif


Note that setupSignalHandler() is just setsig() with error checking.



Then there is also this:


setsig(SIGFPE, SIG_DFL)

its sets up some sort of OS-specific default handler.

newdep

#38
... I stripped a long story here.. and will make it short..



It seems I keep running into a mixup of setjmp longjmp errorReg values.

(tested this by printing all the errorRegs inside newlisp, see previous posts)



From the SIGFPE handler point of view there are 2 options,

* use a long jump, which works in my c-code example.

* Exit the application with a message, this works in both newlisp and c-code example..



From the setjmp point of view:

* Very first call to setjmp results in a 0 return.

* All longjmp calls after the first 'direct' setjmp call will have != 0.



From the longjmp point of view there:

* Return the stack state last set by setjmp based on env value.

* make sure the initial function isnt finshed befor jumping.



Conclusion as it now is in newlisp:

* C-code example works on linux and on OS/2 gcc compiled.

* Nan and Inf only happen when SIGFPE is set.

* I.e. (div 0) Does initialy not return anything.  the errorReg = 0.

* I.e. (div 0) Only returns the second time, as it seems the longjmp  errorReg = 1.





I tried it all...I give myself a SIGSEGV...
-- (define? (Cornflakes))

newdep

#39
oke fresh day fresh SIGHUP..



When starting newlisp freshly and entering (sqrt -1) i get the SIGNAL 8

the errorReg = 0 and returns to the code below where only E5=1 is displayed.



I found that the longjmp inside the SIGFPE handler always returns to this point ->

(which is the first setjmp call).


/* ======================= main entry on reset ====================== */
printf("E4=%dn", errorReg);
errorReg = setjmp(errorJump);
printf("E5=%dn", errorReg);
setupAllSignals();


So again from this test the SIGFPE has initialy (the very first time its called)

not the same set_buf content, only the second time they are in sync. Thats

why the result isnt displayed, at least thats what it looks like..



I have stripped down the signaling inside newlisp so it only does the C-code from my

exmaple. There is no signaling left else then SIGFPE.



because it never displays the E4= it directly jumps to the first setjmp from the longjmp.



If I enter a (/ 0 0) after newlisp initialy started the errorReg = 29 (div by zero integer)

then I enter the (sqrt -1) get the SIGNAL 8 errorReg = 29 and it returns to the same

code (see above) where the E5=29. The next (sqrt -1) (no signal trigger, its running already) is then working.



..Duke Nukem would say... "Where is it!..."
-- (define? (Cornflakes))

newdep

#40
This it will be in newlisp/2.



#ifdef OS2

     /*

        longjmp(errorJump,errorReg) and the signal handling of SIGFPE

        are unreliable, course cant be traced. could be Libc063 or gcc or ..??

        (NaN? (..)) (Inf? (..)) dont work, no returns regarding nan inf...

        Therefor ERR: is returned with an exit. not very charming.

     */

   case SIGFPE:

          printErrorMessage(ERR_MATH, NULL, 0);

      exit(-1);

      break;

#endif
-- (define? (Cornflakes))

newdep

#41
NaN and Inf are now returned by SIGFPE. Got it working. Finaly.

Lutz, I have posted you the code.
-- (define? (Cornflakes))

TedWalther

#42
Well, don't leave me hanging!  Can you paste the diff in here?
Cavemen in bearskins invaded the ivory towers of Artificial Intelligence.  Nine months later, they left with a baby named newLISP.  The women of the ivory towers wept and wailed.  \"Abomination!\" they cried.

Lutz

#43
I uploaded the current newlisp-10.1.6.tgz to your place.

newdep

#44
What kind of diff would you like? Just the changes? because I did it on the 10.1.6 release which isnt yet released yet..



But are you also building or do you only put it in a tree? Then you need the official diff, which is dont have from 10.1.5 to 10.1.6...
-- (define? (Cornflakes))