1. How to handle crashes?

Greetings,

It's been a while since I visited this list. Here I am almost 4 years 
later still working on perfecting my mud. Because of the help of so many 
of you (so long ago) I've built myself a nice little home.

Now the question. I've searched through as many of the posts and 
documentation as I could for the answer, but never found the right thing.

In my game if there are errors the entire world crashes and I lose all 
data since the last save. (Usually only about 10-15 minutes, but players 
get so grumpy!) Has there been a way developed that if a certain action 
they try to perform calls a procedure that perhaps has a bug in it I had 
yet to find that I could indeed point euphoria to a routine I devise?

It would be nice to point errors like that to a routine that simply says 
"Hey, don't do that again, it's broken" and resumes the main loop of the 
game.

Any chance my 4 year old wish has finally come true?

new topic     » topic index » view message » categorize

2. Re: How to handle crashes?

Nope!  How about for 2.5, Rob?

>>> draegur at comcast.net 05/28/03 11:46AM >>>
It would be nice to point errors like that to a routine that simply
says 
"Hey, don't do that again, it's broken" and resumes the main loop of
the 
game.

Any chance my 4 year old wish has finally come true?

new topic     » goto parent     » topic index » view message » categorize

3. Re: How to handle crashes?

On 28 May 2003, at 11:46, draegur at comcast.net wrote:

> 
> 
> Greetings,
> 
> It's been a while since I visited this list. Here I am almost 4 years 
> later still working on perfecting my mud. Because of the help of so many 
> of you (so long ago) I've built myself a nice little home.
> 
> Now the question. I've searched through as many of the posts and 
> documentation as I could for the answer, but never found the right thing.
> 
> In my game if there are errors the entire world crashes and I lose all 
> data since the last save. (Usually only about 10-15 minutes, but players 
> get so grumpy!) Has there been a way developed that if a certain action 
> they try to perform calls a procedure that perhaps has a bug in it I had 
> yet to find that I could indeed point euphoria to a routine I devise?
> 
> It would be nice to point errors like that to a routine that simply says 
> "Hey, don't do that again, it's broken" and resumes the main loop of the 
> game.
> 
> Any chance my 4 year old wish has finally come true?

Didn't someone find a way to do that using types?

Kat

new topic     » goto parent     » topic index » view message » categorize

4. Re: How to handle crashes?

Its not builtin. I am working on a library that, when properly used, will
trap nearly all run-time errors w/o causing the program to end. The catch is
that using the lib with an existing program means considerable (and tedious)
rewriting, tho I suppose it'd be possible to write a short program to convert
all the code.

The bigger issue, is that by using my lib, the program itself is likely to
be slowed down considerably ... the library works by checking arguments in its
replacement routines (you use the lib's routines instead of the normal operators
or normal builtin routines) and making sure that they are correct .. if they
aren't then it sets a flag and returns. In essence, the lib is a pre-written
version of all the checking code that you'd normally have to write on your own.

So, in short, your 4 year old wish has not come true, but I've helped bring
it a little bit closer ...

If you really want that sort of error checking tho, you might wanna check out
OpenEuphoria (at OpenEU at topica.com).

jbrown

On Wed, May 28, 2003 at 11:46:59AM -0400, draegur at comcast.net wrote:
> 
> 
> Greetings,
> 
> It's been a while since I visited this list. Here I am almost 4 years 
> later still working on perfecting my mud. Because of the help of so many 
> of you (so long ago) I've built myself a nice little home.
> 
> Now the question. I've searched through as many of the posts and 
> documentation as I could for the answer, but never found the right thing.
> 
> In my game if there are errors the entire world crashes and I lose all 
> data since the last save. (Usually only about 10-15 minutes, but players 
> get so grumpy!) Has there been a way developed that if a certain action 
> they try to perform calls a procedure that perhaps has a bug in it I had 
> yet to find that I could indeed point euphoria to a routine I devise?
> 
> It would be nice to point errors like that to a routine that simply says 
> "Hey, don't do that again, it's broken" and resumes the main loop of the 
> game.
> 
> Any chance my 4 year old wish has finally come true?
> 
> 
> 
> TOPICA - Start your own email discussion group. FREE!
> 
> 

-- 
 /"\  ASCII ribbon              | http://www.geocities.com/jbrown1050/
 \ /  campain against           | Linux User:190064
  X   HTML in e-mail and        | Linux Machine:84163
 /*\  news, and unneeded MIME   |

new topic     » goto parent     » topic index » view message » categorize

5. Re: How to handle crashes?

On Fri, May 30, 2003 at 03:14:04PM +0700, aku saya wrote:
> 
> 
> How about an option to make euphoria still run after a run-time error
> happens? Like "On Error Resume Next" in VB.
> 
> I suggest using "without error", with an option to call user
> procedures.
> And when a runtime error happens, just continue it and fill the
> function result into a default value, such as:
> 
> ? length(123) -- returns 0
> a = {1, 2, 3}
> b = 5
> ? a[2..100] -- returns {2, 3}
> ? 1/0 -- returns inf
> ? b[1] -- returns 5
> if {1, 2, 3} = 2 then -- returns 0
> integer c
> c = 1.25 -- make c = 1
> 
> etc. It can make user confused, but maybe useful for use in the
> released programs, to prevent end-user confused by the fatal-error.
> 
> so
> - develop a program carefully without this option until finished
> - add "without error" to the first line
> - publish the program.
> 
> Just a suggestion,

<snip>

It's an interesting suggestion. I'd think, that 1/0 should return nan, that
invalid assignments to variables would simply be ignored, and that invalid
slices of a sequence would return {} ... but those are just the details.

The basic concept, looks ok to me, tho it seems to be not the best way. My lib
will just flatly return -1 on error, and then you have to check the variable
eu_errno to see what the error was (you'd have to check eu_errno every time
if -1 is a valid return value btw). That way, at least the code actually
_KNOWS_ that there was an error.

jbrown

-- 
 /"\  ASCII ribbon              | http://www.geocities.com/jbrown1050/
 \ /  campain against           | Linux User:190064
  X   HTML in e-mail and        | Linux Machine:84163
 /*\  news, and unneeded MIME   |

new topic     » goto parent     » topic index » view message » categorize

6. Re: How to handle crashes?

On Fri, 30 May 2003 12:58:55 -0400, jbrown105 at speedymail.org wrote:

>It's an interesting suggestion. I'd think, that 1/0 should return nan,

If you want to use nan, define a constant and use that constant,
whatever that may be, do *NOT* calculate it !!

Lots of code that I have written (and lots inherited) use ?9/0 to
force a fatal error.

<slight rant>
In some situations, (I'm talking MEditor here, where there may be
several open documents containing lots of work the user might lose),
it is up to me to do some sensible thing such as prompt the user, save
all the files (others first, preferably in another [new] directory,
before the one that seems to have an error (and, erm, write something
which will cause the editor to re-explain the situation to the user
when the editor is next re-started and offer a directory compare...)
It does not do that at the moment but I've added that suggestion).

But then I still need to force a crash. I might, scratch that, will
need the ex.err file to track the bug down.

Plus, of course, I don't code ?9/0 unless I really have to give up. If
the error was just ignored, let's say it rewrites all open files with
garbage. Would you prefer that to a crash?
</slight rant>

The way I would see this working, if at all, is:

main.exw:
global ...
global ...
global ...
procedure intercept_fatal()
	,,,
end procedure
set_fatal_routine(routine_id("intercept_fatal"))

Notes:
1) No include statements, initialisation, or any other routines are
allowed before set_fatal_routine(). Just global data.
2) A second call to set_fatal_routine() in the same program is an
irrecoverable fatal error (see 7).
3) This feature is not available in compiled code, only when using the
interpreter (which covers bound/shrouded/standalone stuff, just not C)
4)The call to set_fatal_routine() generates no code; instead it makes
a checkpoint of the memory/symbol table currently in use.=20
5) When a fatal error occurs it reloads reference counts (eeek!) based
on that and performs a full garbage collection, discards the rest of
memory and the rest of the symbol table, and resumes interpretation at
the first line of the procedure.[see postscript]
6) intercept_fatal() may not have any parameters or any local
variables, the end procedure has no "clean up" requirement.
7) contrary to 2) set_fatal_routine() will be called again, but via 5)
the interpreter will have managed to forget it was ever called. In a
correct implementation, this will simply happen, no explicit check for
this should be required.

and last, but not least:

8) I don't subscribe to the theory that you can release crud code and
the user can be blissfully unaware that it is crud code. Some apps it
is a good idea and not very dangerous (eg games), some it might help
if wisely used (eg editors), some it really is very very wrong (cgi).

The problem with cgi-like programs, of course, is they are not
interactive, so unless there is judicious use of rand(), recovering
from a fatal error will just run splat into the self same problem,
time and time again.

Pete

PS One perfectly acceptable method, in my eyes, would be to write a
(massive) ex.err file and then re-invoke the interpreter to parse that
file to initialise those global variables. I would not want or expect
it to be fast.

PPS Phew! I enjoyed that little rant blink

new topic     » goto parent     » topic index » view message » categorize

7. Re: How to handle crashes?

On Fri, May 30, 2003 at 10:03:48PM +0100, Pete Lomax wrote:
> 
> 
> On Fri, 30 May 2003 12:58:55 -0400, jbrown105 at speedymail.org wrote:
> 
> >It's an interesting suggestion. I'd think, that 1/0 should return nan,
> 
> If you want to use nan, define a constant and use that constant,
> whatever that may be, do *NOT* calculate it !!

I meant I'd prefer it returning nan over inf.

> 
> Lots of code that I have written (and lots inherited) use ?9/0 to
> force a fatal error.
> 

With my lib, you have to explicitly code (using op_divide(0,0) instead of
0/0 for example, or e_puts() instead of puts()) in order to avoid an error.

If needed, you can always force an error.

> <slight rant>
> In some situations, (I'm talking MEditor here, where there may be
> several open documents containing lots of work the user might lose),
> it is up to me to do some sensible thing such as prompt the user, save
> all the files (others first, preferably in another [new] directory,
> before the one that seems to have an error (and, erm, write something
> which will cause the editor to re-explain the situation to the user
> when the editor is next re-started and offer a directory compare...)
> It does not do that at the moment but I've added that suggestion).

My lib lets you do that exactly, tho the MEditor code would need a major
rewrite .. and use of the lib will slow it significantly.

> 
> But then I still need to force a crash. I might, scratch that, will
> need the ex.err file to track the bug down.

You still code, with my lib.

> 
> Plus, of course, I don't code ?9/0 unless I really have to give up. If
> the error was just ignored, let's say it rewrites all open files with
> garbage. Would you prefer that to a crash?
> </slight rant>
> 

> The way I would see this working, if at all, is:
> 
> main.exw:
> global ...
> global ...
> global ...
> procedure intercept_fatal()
> 	,,,
> end procedure
> set_fatal_routine(routine_id("intercept_fatal"))
> 

Basicly, the same as crash_routine() that was in peu and Matt Lewis's
interpreter.

> Notes:
> 1) No include statements, initialisation, or any other routines are
> allowed before set_fatal_routine(). Just global data.

Why?

> 2) A second call to set_fatal_routine() in the same program is an
> irrecoverable fatal error (see 7).

Why? Whats wrong with chains of error handlers?

> 3) This feature is not available in compiled code, only when using the
> interpreter (which covers bound/shrouded/standalone stuff, just not C)

I agree with this one, since I don't see how it'd be possible to catch the
C stuff.

> 4)The call to set_fatal_routine() generates no code; instead it makes
> a checkpoint of the memory/symbol table currently in use. 

> 5) When a fatal error occurs it reloads reference counts (eeek!) based
> on that and performs a full garbage collection, discards the rest of
> memory and the rest of the symbol table, and resumes interpretation at
> the first line of the procedure.[see postscript]

Why? That seems like overkill to me.

> 6) intercept_fatal() may not have any parameters or any local
> variables, the end procedure has no "clean up" requirement.

Why? Might wanna pass error info thru the parameters, and local variables
are very useful for the procedure.

> 7) contrary to 2) set_fatal_routine() will be called again, but via 5)
> the interpreter will have managed to forget it was ever called. In a
> correct implementation, this will simply happen, no explicit check for
> this should be required.

I don't understand what you mean by this.

> 
> and last, but not least:
> 
> 8) I don't subscribe to the theory that you can release crud code and
> the user can be blissfully unaware that it is crud code. Some apps it
> is a good idea and not very dangerous (eg games), some it might help
> if wisely used (eg editors), some it really is very very wrong (cgi).
> 

I also agree. But no one is asking for the ability to release crud code,
what is being asked for is the ability to save data, give the user a little
message box explaining the error, and go down quietly. We don't want to ignore
errors silently, we just want to look as professional as possible when an
error does occur.

> The problem with cgi-like programs, of course, is they are not
> interactive, so unless there is judicious use of rand(), recovering
> from a fatal error will just run splat into the self same problem,
> time and time again.

Agreed.

> 
> Pete
> 
> PS One perfectly acceptable method, in my eyes, would be to write a
> (massive) ex.err file and then re-invoke the interpreter to parse that
> file to initialise those global variables. I would not want or expect
> it to be fast.

I find it not acceptable or needed. This is definately overkill.

> 
> PPS Phew! I enjoyed that little rant blink
> 

jbrown

> 
> 
> TOPICA - Start your own email discussion group. FREE!
> 
> 

-- 
 /"\  ASCII ribbon              | http://www.geocities.com/jbrown1050/
 \ /  campain against           | Linux User:190064
  X   HTML in e-mail and        | Linux Machine:84163
 /*\  news, and unneeded MIME   |

new topic     » goto parent     » topic index » view message » categorize

8. Re: How to handle crashes?

On 30 May 2003, at 17:45, jbrown105 at speedymail.org wrote:

> 
> 
> On Fri, May 30, 2003 at 10:03:48PM +0100, Pete Lomax wrote:
> > 
> > 
<snip>
> > 
> > Pete
> > 
> > PS One perfectly acceptable method, in my eyes, would be to write a
> > (massive) ex.err file and then re-invoke the interpreter to parse that
> > file to initialise those global variables. I would not want or expect
> > it to be fast.
> 
> I find it not acceptable or needed. This is definately overkill.

It's rather acceptable, somewhat needed, and overkill for your purposes. 
What if you have a crash every other month, and you can't find the bug? Like 
this new bug in mirc 6.03:

 set -u0 %walkcolor1 
$gettok(%colors1,$rand(1,$len(%colors1)),$asc(%comma))
 

Those functions return at different times, and occasionally %walkcolor1 will 
be $null. But a stepper ide like Eu won't catch it, even if mirc had one. But 
storing the vars did catch it, leading to code like this:

  :regetwalkcolor1
  set -u0 %walkcolor1 
$gettok(%colors1,$rand(1,$len(%colors1)),$asc(%comma))
  if ( %walkcolor1 == $null ) { goto regetwalkcolor1 }

If you have a cgi box that crashes once a month, you could rebuild to the 
moment before the crash, possibly stepping back in time thru the execution.

Kat

new topic     » goto parent     » topic index » view message » categorize

9. Re: How to handle crashes?

No, restoring the variables and context is overkill.

I see that saving the current variables (in full) and context (i.e. which
statements were executed) into an error file, is a good idea. It would be a
great aid to debugging. But I fail to see the need to RESTORE the variables.

jbrown

On Fri, May 30, 2003 at 06:52:57PM -0500, gertie at visionsix.com wrote:
<snip> 
> It's rather acceptable, somewhat needed, and overkill for your purposes. 
> What if you have a crash every other month, and you can't find the bug? Like 
> this new bug in mirc 6.03:
> 
>  set -u0 %walkcolor1 
> $gettok(%colors1,$rand(1,$len(%colors1)),$asc(%comma))
>  
> 
> Those functions return at different times, and occasionally %walkcolor1 will 
> be $null. But a stepper ide like Eu won't catch it, even if mirc had one. But 
> storing the vars did catch it, leading to code like this:
> 
>   :regetwalkcolor1
>   set -u0 %walkcolor1 
> $gettok(%colors1,$rand(1,$len(%colors1)),$asc(%comma))
>   if ( %walkcolor1 == $null ) { goto regetwalkcolor1 }
> 
> If you have a cgi box that crashes once a month, you could rebuild to the 
> moment before the crash, possibly stepping back in time thru the execution.
> 
> Kat
> 
> 
> 
> TOPICA - Start your own email discussion group. FREE!
> 
> 

-- 
 /"\  ASCII ribbon              | http://www.geocities.com/jbrown1050/
 \ /  campain against           | Linux User:190064
  X   HTML in e-mail and        | Linux Machine:84163
 /*\  news, and unneeded MIME   |

new topic     » goto parent     » topic index » view message » categorize

10. Re: How to handle crashes?

On Fri, 30 May 2003 17:45:13 -0400, jbrown105 at speedymail.org wrote:

>> Notes:
>> 1) No include statements, initialisation, or any other routines are
>> allowed before set_fatal_routine(). Just global data.
>
>Why?
My (naive) view of a workable system / I want to keep it simple.
>
>> 2) A second call to set_fatal_routine() in the same program is an
>> irrecoverable fatal error (see 7).
>
>Why? Whats wrong with chains of error handlers?
What exactly would you achieve by trapping bad code within bad code?
This is not exception handling, this is buggy, crud code (see my
comments below). This is not a programming methodology, this is a
safety net for the end user.

Code it and test it, but be embarrassed if it ever happens live.

I think it is a totally different topic if you want a local try catch
doobrie, or a safe_mul() or safe_div() routine.

>> 5) When a fatal error occurs it reloads reference counts (eeek!) based
>> on that and performs a full garbage collection, discards the rest of
>> memory and the rest of the symbol table, and resumes interpretation at
>> the first line of the procedure.[see postscript]
>
>Why? That seems like overkill to me.
An absolutely unambiguous restart point. It also forces you to specify
the absolutely unambiguous data set needed for recovery. How otherwise
would you reference data which is not in scope at the point (which
could be anywhere) that the fatal error occurs?

>
>> 6) intercept_fatal() may not have any parameters or any local
>> variables, the end procedure has no "clean up" requirement.
>
>Why? Might wanna pass error info thru the parameters,=20
What would a top level routine ever know about low-level parameters
and variables? Or are you suggesting the top level routine would have
to be more intelligent and complicated than the code it is guarding?
"Hello, this is routine number 73, I was passed a single integer
which was 478, and my local variables are {4,7,"Simon",5}"
Does it really help you to recover if I also pass you "appendThing",
"Id", "i", "j", "text", "void"?

>and local variables are very useful for the procedure.
The important thing I felt about the "no clean up" is that on
resumption the code could "fall through" the end procedure statement
without causing any, even minor niggles. That means no parameters and
no local variables to discard.
>
>> 7) contrary to 2) set_fatal_routine() will be called again, but via 5)
>> the interpreter will have managed to forget it was ever called. In a
>> correct implementation, this will simply happen, no explicit check for
>> this should be required.
>
>I don't understand what you mean by this.
Just dotting the i's
>
>>=20
>> and last, but not least:
>>=20
>> 8) I don't subscribe to the theory that you can release crud code and
>> the user can be blissfully unaware that it is crud code. Some apps it
>> is a good idea and not very dangerous (eg games), some it might help
>> if wisely used (eg editors), some it really is very very wrong (cgi).
>>=20
>
>I also agree. But no one is asking for the ability to release crud code,
Well, actually we are asking for the ability to release crud code. Not
deliberately, but just simply inevitably. Something like MEditor is
some 15,000 lines of code (and win32lib what, 30,000?). It is highly
unlikely there will ever be a release that really has zero (fatal)
bugs, the best we can hope for is it will be several years between
finding one for the average user. But as I say, this is no way to make
bad code good, and that point needs to be said, loudly.

>what is being asked for is the ability to save data, give the user a =
little
>message box explaining the error, and go down quietly. We don't want to =
ignore
>errors silently, we just want to look as professional as possible when =
an
>error does occur.
Exactly.

>> PS One perfectly acceptable method, in my eyes, would be to write a
>> (massive) ex.err file and then re-invoke the interpreter to parse that
>> file to initialise those global variables. I would not want or expect
>> it to be fast.
>
>I find it not acceptable or needed. This is definately overkill.
Sure, there may be a better, or more to the point, easier way.
What I was trying to illustrate is that the overhead should be on
programs recovering from a fatal error, and virtually no overhead on
well-behaved programs.

I'll add that if with profile or with profile_time is in force it
should report the error with some message such as=20
"A (recoverable) fatal error occurred. You need to fix that before
profiling the program."

Likewise, if with trace is in force, the interpreter should probably
assume you are in development mode and crash instead of recovering.

Pete

new topic     » goto parent     » topic index » view message » categorize

11. Re: How to handle crashes?

On Sat, May 31, 2003 at 12:52:59AM +0100, Pete Lomax wrote:
> 
> 
> On Fri, 30 May 2003 17:45:13 -0400, jbrown105 at speedymail.org wrote:
> 
> >> Notes:
> >> 1) No include statements, initialisation, or any other routines are
> >> allowed before set_fatal_routine(). Just global data.
> >
> >Why?
> My (naive) view of a workable system / I want to keep it simple.

Ah I see. Shouldn't need to be that simple tho.

> >
> >> 2) A second call to set_fatal_routine() in the same program is an
> >> irrecoverable fatal error (see 7).
> >
> >Why? Whats wrong with chains of error handlers?
> What exactly would you achieve by trapping bad code within bad code?

I mean more like, one handler looks at the error and does it stuff, then
another handler can also do its stuff, and so on.

> This is not exception handling, this is buggy, crud code (see my
> comments below). This is not a programming methodology, this is a
> safety net for the end user.
> 
> Code it and test it, but be embarrassed if it ever happens live.
> 
> I think it is a totally different topic if you want a local try catch
> doobrie, or a safe_mul() or safe_div() routine.

I don't.

> 
> >> 5) When a fatal error occurs it reloads reference counts (eeek!) based
> >> on that and performs a full garbage collection, discards the rest of
> >> memory and the rest of the symbol table, and resumes interpretation at
> >> the first line of the procedure.[see postscript]
> >
> >Why? That seems like overkill to me.
> An absolutely unambiguous restart point. It also forces you to specify
> the absolutely unambiguous data set needed for recovery. How otherwise
> would you reference data which is not in scope at the point (which
> could be anywhere) that the fatal error occurs?
> 

My answer, in the openeu forum, was that the list of variables, and their scope,
and the file they were in (as well as routine, if applicable, and also it should
mark being a for loop var) and value, and etc. would be passed as a large
sequence,
to the crash routine.

> >
> >> 6) intercept_fatal() may not have any parameters or any local
> >> variables, the end procedure has no "clean up" requirement.
> >
> >Why? Might wanna pass error info thru the parameters, 
> What would a top level routine ever know about low-level parameters
> and variables? Or are you suggesting the top level routine would have
> to be more intelligent and complicated than the code it is guarding?
> "Hello, this is routine number 73, I was passed a single integer
> which was 478, and my local variables are {4,7,"Simon",5}"
> Does it really help you to recover if I also pass you "appendThing",
> "Id", "i", "j", "text", "void"?

No, but a more useful sequence (having all routine names, scopes, variables
(names, scope, value, etc), file name and line number where error occured,
error message as a string, etc) might be in order.

> 
> >and local variables are very useful for the procedure.
> The important thing I felt about the "no clean up" is that on
> resumption the code could "fall through" the end procedure statement
> without causing any, even minor niggles. That means no parameters and
> no local variables to discard.

Hmm. I can see your point there. But, if the program is going to abort as
soon as the procedure ends, why does it matter?

> >
> >> 7) contrary to 2) set_fatal_routine() will be called again, but via 5)
> >> the interpreter will have managed to forget it was ever called. In a
> >> correct implementation, this will simply happen, no explicit check for
> >> this should be required.
> >
> >I don't understand what you mean by this.
> Just dotting the i's

> >
> >> 
> >> and last, but not least:
> >> 
> >> 8) I don't subscribe to the theory that you can release crud code and
> >> the user can be blissfully unaware that it is crud code. Some apps it
> >> is a good idea and not very dangerous (eg games), some it might help
> >> if wisely used (eg editors), some it really is very very wrong (cgi).
> >> 
> >
> >I also agree. But no one is asking for the ability to release crud code,
> Well, actually we are asking for the ability to release crud code. Not
> deliberately, but just simply inevitably. Something like MEditor is
> some 15,000 lines of code (and win32lib what, 30,000?). It is highly
> unlikely there will ever be a release that really has zero (fatal)
> bugs, the best we can hope for is it will be several years between
> finding one for the average user. But as I say, this is no way to make
> bad code good, and that point needs to be said, loudly.

Ah, very true. The idea is that the error handler doesn't try to fix things
so the program can keep on going, but simply to do the stuff it needs to do
(show a little "oppsies" msgbox, backup data, etc) and then abort gracefully.

> 
> >what is being asked for is the ability to save data, give the user a little
> >message box explaining the error, and go down quietly. We don't want to
> >ignore
> >errors silently, we just want to look as professional as possible when an
> >error does occur.
> Exactly.

> 
> >> PS One perfectly acceptable method, in my eyes, would be to write a
> >> (massive) ex.err file and then re-invoke the interpreter to parse that
> >> file to initialise those global variables. I would not want or expect
> >> it to be fast.
> >
> >I find it not acceptable or needed. This is definately overkill.
> Sure, there may be a better, or more to the point, easier way.
> What I was trying to illustrate is that the overhead should be on
> programs recovering from a fatal error, and virtually no overhead on
> well-behaved programs.

Ah.. I agree, with the overhead part.

> 
> I'll add that if with profile or with profile_time is in force it
> should report the error with some message such as 
> "A (recoverable) fatal error occurred. You need to fix that before
> profiling the program."

Don't see why you can't have profile data up to the point of the error (tho
beyond there, no data, obviously).

> 
> Likewise, if with trace is in force, the interpreter should probably
> assume you are in development mode and crash instead of recovering.

Unless you are tracing the error handler itself.

> 
> Pete
> 

also, If an error handler has an error itself, it should crash.

jbrown

-- 
 /"\  ASCII ribbon              | http://www.geocities.com/jbrown1050/
 \ /  campain against           | Linux User:190064
  X   HTML in e-mail and        | Linux Machine:84163
 /*\  news, and unneeded MIME   |

new topic     » goto parent     » topic index » view message » categorize

12. Re: How to handle crashes?

----- Original Message -----
From: [lots of people]
To: "EUforum" <EUforum at topica.com>
Subject: Re: How to handle crashes?

Why do we want a crash handler? In other words, what can't Euphoria do that
you need to be able to do?


For me, the primary answer to this question is to be able to handle things
that Euphoria knows nothing about. For example, saving the current database
transaction, or anything that would make the next restart easier for the
program's user.

I don't regard being able to automatically restart as being a priority
issue. I would be quite contented if the crash handler could not return
control to the program.

I don't regard being able to know what caused the crash handler to be
invoked as a high priority. It would be nice but not essential.


--
Derek

new topic     » goto parent     » topic index » view message » categorize

13. Re: How to handle crashes?

Yes, I agree.

Two things that could be gained by handling crashes better.

1. A more professional look to your software.
         A dialog box telling the user a problem has occured, and what will 
happen is far more appealing
         than a screen dump of what sequence was where, and the error type 
that occured. That sort
         of information is invaluable to the programmer, but the user is not 
going to know what "invalid
         slice" is going to mean, or know what to do about it. A crash 
routine will not in this case
         reduce the number of errors that the user experiences, but it will 
be much more palatable than
         the current system.

2. More user 'safety'
        Nothing is worse than typing up a large document, and then losing it 
because the application
        crashed before you could save it. This sort of thing is more 
frustrating to a user than any other
        kind of error - where their effort and time was wasted. An 
application that experiences an error
        *should* close, because (like was said before) it is even worse for 
a rogue application to corrupt
        an entire document / system by continuing in such a fashion. What 
the user would like to do,
        after this error occured, is to salvage their work, and continue. As 
programmers, we can code
        defensively: for example store the users work in a temporary file 
every $period, and when the
        application starts up, check for that file, and give the option to 
restore from it. This is not always
        possible, for some types of application, doing this would mean too 
much overhead. A crash
        routine in this case will give the programmer the opportunity to 
backup the user's work into a file
        (example) and have the application start-up sequence give an option 
to restore. This would
        remove the overhead required to do that continuously, "just in case" 
there's an error.


The ability to dodge fatal errors is not what should be advocated... there 
is no excuse for "crud" programming. During development, fatal errors are 
par for the course, and it is appropriate for the application to go haywire 
if there is a problem, because it tells the programmer what he needs to know 
(hopefully). However, once it has been released, a user doesn't care about 
whether there has been a math error, or a sequencing error, or a 
segmentation fault. What they care about is:

a) The frequency of errors. The less the better, of course, and something 
telling them what has just happened.

b) Where their work just went. Loss of data is painful, and if your 
application can (in the unlikely event of an error) bring that data back the 
next time it starts up, then that is good from a user's perspective.

c) Whether the application behaves correctly. If an application occasionally 
dies with an error message, then it happens, and as long as it is not too 
often, then that's permissable. If an application behaves unpredictably 
(because your app dodged the fatal error and continued) then it can no 
longer be trusted. Imagine you were using an email client, and on sending a 
torrid letter to your loved one, found that instead your unpredictable 
program sent it to everyone in your addressbook, including boss, friends, 
and grandparents!


Crashing is good, as long as it's a crash "you can walk away from", so to 
speak.

That's my rant, anyway.
=====================================================
.______<-------------------\__
/ _____<--------------------__|===
||_    <-------------------/
\__| Mr Trick





>From: Derek Parnell <ddparnell at bigpond.com>
>Reply-To: EUforum at topica.com
>To: EUforum <EUforum at topica.com>
>Subject: Re: How to handle crashes?
>Date: Sat, 31 May 2003 13:23:51 +1000
>
>
>----- Original Message -----
>From: [lots of people]
>To: "EUforum" <EUforum at topica.com>
>Subject: Re: How to handle crashes?
>
>Why do we want a crash handler? In other words, what can't Euphoria do that
>you need to be able to do?
>
>
>For me, the primary answer to this question is to be able to handle things
>that Euphoria knows nothing about. For example, saving the current database
>transaction, or anything that would make the next restart easier for the
>program's user.
>
>I don't regard being able to automatically restart as being a priority
>issue. I would be quite contented if the crash handler could not return
>control to the program.
>
>I don't regard being able to know what caused the crash handler to be
>invoked as a high priority. It would be nice but not essential.
>
>
>--
>Derek
>
>
>
>TOPICA - Start your own email discussion group. FREE!
>
>

new topic     » goto parent     » topic index » view message » categorize

14. Re: How to handle crashes?

I have seen many people here comment on my original question about crash 
handling/error trapping. Several of you have said there is no excuse for 
"crud" programming. Now, everyone is entitled to their opinion, but why 
should it matter to you how I program? The smallest file I have in my 
mud is 15,000 lines of code. There are many ways that new code I add 
interacts with old code that perhaps I wasn't expecting and *poof*, 
there goes anything they've done since the last backup of the database.

Why is it so wrong for a language like euphoria to allow me flexibility 
in programming? Perhaps someones program to keep track of bank accounts 
might not benefit from being able to keep their programs running, but 
for someone doing a project like I am it's almost a nessessity.

You've all had your chance to rant about how it should be handled like 
this so as not to encourage "crud" programming, or how it should not be 
done at all because it will encourage "sloppy" programming. My rant in 
response is, why do you care how I code? If using the print() command 
could lead to people being lazy, would you not include it because of 
that? So what if you don't need something to handle errors as I do? 
Unless, of course, the only reason why you do not write "sloppy" or 
"crud" code is because you cannot?

There. I feel a little better now.

(These comments were not directed at everyone, just those few on their 
personal little soap boxes)

new topic     » goto parent     » topic index » view message » categorize

15. Re: How to handle crashes?

On Sat, May 31, 2003 at 01:32:37PM -0400, draegur at comcast.net wrote:
> 
> 
> I have seen many people here comment on my original question about crash 
> handling/error trapping. Several of you have said there is no excuse for 
> "crud" programming. Now, everyone is entitled to their opinion, but why 
> should it matter to you how I program? The smallest file I have in my 
> mud is 15,000 lines of code. There are many ways that new code I add 
> interacts with old code that perhaps I wasn't expecting and *poof*, 
> there goes anything they've done since the last backup of the database.
> 

I hereby define crud programming as this:

To continue execution of a program, after what should be a fatal error,
at the risk of corrupting the data that the program works with.

Under that definition, what you want to do is not crud programming.
(Even if you want to back up the db and restart (or resume) the mud server,
its still not crud programming since you aren't risking any corruption.)

> Why is it so wrong for a language like euphoria to allow me flexibility 
> in programming? Perhaps someones program to keep track of bank accounts 
> might not benefit from being able to keep their programs running, but 
> for someone doing a project like I am it's almost a nessessity.

Agreed. I believe that for games, especially multi-user ones, that sort
of ability is a great advantage. (I also believe someone else who argued
against crud programming said that ignoring errors in games is basicly OK.)

> 
> You've all had your chance to rant about how it should be handled like 
> this so as not to encourage "crud" programming, or how it should not be 
> done at all because it will encourage "sloppy" programming. My rant in 
> response is, why do you care how I code? If using the print() command 
> could lead to people being lazy, would you not include it because of 
> that? So what if you don't need something to handle errors as I do? 
> Unless, of course, the only reason why you do not write "sloppy" or 
> "crud" code is because you cannot?

That was one of the arguements against goto, you know. ;]

try-catch for euphoria is a must, i feel....

> 
> There. I feel a little better now.

Good for you. ;]

> 
> (These comments were not directed at everyone, just those few on their 
> personal little soap boxes)

HA!

> 
> 
> 
> TOPICA - Start your own email discussion group. FREE!
> 

j. brown

> 
> 

-- 
 /"\  ASCII ribbon              | http://www.geocities.com/jbrown1050/
 \ /  campain against           | Linux User:190064
  X   HTML in e-mail and        | Linux Machine:84163
 /*\  news, and unneeded MIME   |

new topic     » goto parent     » topic index » view message » categorize

16. Re: How to handle crashes?

Hi Jim, you wrote:

<snip>

> It's an interesting suggestion. I'd think, that 1/0 should return nan, that
> invalid assignments to variables would simply be ignored, and that invalid
> slices of a sequence would return {} ... but those are just the details.
>
> The basic concept, looks ok to me, tho it seems to be not the best way. My lib
> will just flatly return -1 on error, and then you have to check the variable
> eu_errno to see what the error was (you'd have to check eu_errno every time
> if -1 is a valid return value btw).

That's exactly the reason, why I'd prefer using a value as a flag for an
invalid result, that never can be a valid number or sequence (such as
NIL/NAN/UNKNOWN/UNDEFINED), rather than -1. This is especially important
for writing generic routines.
That's why I was happy when I discovered, that NAN can be returned from
user defined functions. And that's why I was unhappy, when I recently
read on this list, that this self-defined NAN can't be used reliable.

> That way, at least the code actually _KNOWS_ that there was an error.

I also regard this as important.

> jbrown

Best regards,
   Juergen

-- 
 /"\  ASCII ribbon campain  |
 \ /  against HTML in       |  Money is the root of all evil.
  X   e-mail and news,      |  Send 20 Dollars for more info.
 / \  and unneeded MIME     |

new topic     » goto parent     » topic index » view message » categorize

17. Re: How to handle crashes?

On Sat, May 31, 2003 at 08:25:41PM +0200, Juergen Luethje wrote:
> 
> 
> Hi Jim, you wrote:
> 
> <snip>
> 
> > It's an interesting suggestion. I'd think, that 1/0 should return nan, that
> > invalid assignments to variables would simply be ignored, and that invalid
> > slices of a sequence would return {} ... but those are just the details.
> >
> > The basic concept, looks ok to me, tho it seems to be not the best way. My
> > lib
> > will just flatly return -1 on error, and then you have to check the variable
> > eu_errno to see what the error was (you'd have to check eu_errno every time
> > if -1 is a valid return value btw).
> 
> That's exactly the reason, why I'd prefer using a value as a flag for an
> invalid result, that never can be a valid number or sequence (such as
> NIL/NAN/UNKNOWN/UNDEFINED), rather than -1. This is especially important
> for writing generic routines.

Yes, but its very hard to find one like that.

I used to like to do what DC did in Py:

global constant UNDEFINED = {-102354, -102354}

He called it PyUndef and used different numbers tho, but the general concept
(use an ugly looking sequence that is unlikely to every be a valid result)
still works.

> That's why I was happy when I discovered, that NAN can be returned from
> user defined functions.

Shouldn't have, since NAN can be a perfectly valid return value.

> And that's why I was unhappy, when I recently
> read on this list, that this self-defined NAN can't be used reliable.

The reason behind that, is that there is more than one NAN.

You can get a NAN from tan(), power(), -inf/inf, ...

And, each way of calculating NAN gives a different NAN.

What should be done, is to do this.

global constant
divNAN = -inf/inf,
powNAN = power(2, inf),
tanNAN = --however you get a NAN from tan()

...etc for every possible way of calculating NAN.

So, that, divNAN is reliable when using NANs from division, but not with
comparisons
to tanNANs, for example.

Then, you can choose one NAN, to use as the return value ... as long as its
always the same NAN there is no problem. (Except of course, that NAN could be
a valid return value ... but so could {-102354, -102354}, so theres no good
way of getting around that.)

> 
> > That way, at least the code actually _KNOWS_ that there was an error.
> 
> I also regard this as important.

I based my errhandle.e lib, on how C stdlib functions use a global errno to
return errors.

jbrown

> 
> > jbrown
> 
> Best regards,
>    Juergen
> 
> -- 
>  /"\  ASCII ribbon campain  |
>  \ /  against HTML in       |  Money is the root of all evil.
>   X   e-mail and news,      |  Send 20 Dollars for more info.
>  / \  and unneeded MIME     |
> 
> 
> 
> TOPICA - Start your own email discussion group. FREE!
> 
> 

-- 
 /"\  ASCII ribbon              | http://www.geocities.com/jbrown1050/
 \ /  campain against           | Linux User:190064
  X   HTML in e-mail and        | Linux Machine:84163
 /*\  news, and unneeded MIME   |

new topic     » goto parent     » topic index » view message » categorize

18. Re: How to handle crashes?

Hi Jim, you wrote:

> On Sat, May 31, 2003 at 08:25:41PM +0200, Juergen Luethje wrote:
>>
>>
>> Hi Jim, you wrote:
>>
>> <snip>
>>
>>> It's an interesting suggestion. I'd think, that 1/0 should return nan, that
>>> invalid assignments to variables would simply be ignored, and that invalid
>>> slices of a sequence would return {} ... but those are just the details.
>>>
>>> The basic concept, looks ok to me, tho it seems to be not the best way. My
>>> lib
>>> will just flatly return -1 on error, and then you have to check the variable
>>> eu_errno to see what the error was (you'd have to check eu_errno every time
>>> if -1 is a valid return value btw).
>>
>> That's exactly the reason, why I'd prefer using a value as a flag for an
>> invalid result, that never can be a valid number or sequence (such as
>> NIL/NAN/UNKNOWN/UNDEFINED), rather than -1. This is especially important
>> for writing generic routines.
>
> Yes, but its very hard to find one like that.
>
> I used to like to do what DC did in Py:
>
> global constant UNDEFINED = {-102354, -102354}
>
> He called it PyUndef and used different numbers tho, but the general concept
> (use an ugly looking sequence that is unlikely to every be a valid result)
> still works.

Yes. Some time ago, I had the idea of using
   global constant UNKNOWN = {"UnkNOWn"}

>> That's why I was happy when I discovered, that NAN can be returned from
>> user defined functions.
>
> Shouldn't have, since NAN can be a perfectly valid return value.
>
>> And that's why I was unhappy, when I recently
>> read on this list, that this self-defined NAN can't be used reliable.
>
> The reason behind that, is that there is more than one NAN.
>
> You can get a NAN from tan(), power(), -inf/inf, ...
>
> And, each way of calculating NAN gives a different NAN.

Interesting, thank you!
Now I know, that I didn't know too much about NAN.

> What should be done, is to do this.
>
> global constant
> divNAN = -inf/inf,
> powNAN = power(2, inf),
> tanNAN = --however you get a NAN from tan()

Because of tan(x) = sin(x)/cos(x),
tan(x) is undefined, if cos(x) = 0 (i.e. for x = .., -PI/2, PI/2, 3*PI/2, ..).
BTW: With Euphoria, 'cos(PI/2)' does *not* return 0.

> ...etc for every possible way of calculating NAN.

I also found the following smile

   addNAN = inf + (-inf)
   mulNAN = 0 * inf
   remNAN = remainder(inf, 1)

> So, that, divNAN is reliable when using NANs from division, but not with
> comparisons
> to tanNANs, for example.
>
> Then, you can choose one NAN, to use as the return value ... as long as its
> always the same NAN there is no problem. (Except of course, that NAN could be
> a valid return value ... but so could {-102354, -102354}, so theres no good
> way of getting around that.)

In "What Every Computer Scientist Should Know About Floating-Point Arithmetic"
<http://docs.sun.com/source/806-3568/ncg_goldberg.html>, David Goldberg
writes, that the IEEE recommends a function Isnan(). In my imagination,
this function would return TRUE for *any* NAN, and so help with this
issue, right?

Best regards,
   Juergen

-- 
 /"\  ASCII ribbon campain  |
 \ /  against HTML in       |  This message has been ROT-13 encrypted
  X   e-mail and news,      |  twice for higher security.
 / \  and unneeded MIME     |

new topic     » goto parent     » topic index » view message » categorize

19. Re: How to handle crashes?

On Sat, Jun 07, 2003 at 07:33:52PM +0200, Juergen Luethje wrote:
> 
> 
> Hi Jim, you wrote:
> 
> > On Sat, May 31, 2003 at 08:25:41PM +0200, Juergen Luethje wrote:
> >>
> >>
> >> Hi Jim, you wrote:
> >>
> >> <snip>
> >>
> >>> It's an interesting suggestion. I'd think, that 1/0 should return nan,
> >>> that
> >>> invalid assignments to variables would simply be ignored, and that invalid
> >>> slices of a sequence would return {} ... but those are just the details.
> >>>
> >>> The basic concept, looks ok to me, tho it seems to be not the best way. My
> >>> lib
> >>> will just flatly return -1 on error, and then you have to check the
> >>> variable
> >>> eu_errno to see what the error was (you'd have to check eu_errno every
> >>> time
> >>> if -1 is a valid return value btw).
> >>
> >> That's exactly the reason, why I'd prefer using a value as a flag for an
> >> invalid result, that never can be a valid number or sequence (such as
> >> NIL/NAN/UNKNOWN/UNDEFINED), rather than -1. This is especially important
> >> for writing generic routines.
> >
> > Yes, but its very hard to find one like that.
> >
> > I used to like to do what DC did in Py:
> >
> > global constant UNDEFINED = {-102354, -102354}
> >
> > He called it PyUndef and used different numbers tho, but the general concept
> > (use an ugly looking sequence that is unlikely to every be a valid result)
> > still works.
> 
> Yes. Some time ago, I had the idea of using
>    global constant UNKNOWN = {"UnkNOWn"}
> 

That'd work too (tho I think it might be slightly more likely to be a
program's valid data).

> >> That's why I was happy when I discovered, that NAN can be returned from
> >> user defined functions.
> >
> > Shouldn't have, since NAN can be a perfectly valid return value.
> >
> >> And that's why I was unhappy, when I recently
> >> read on this list, that this self-defined NAN can't be used reliable.
> >
> > The reason behind that, is that there is more than one NAN.
> >
> > You can get a NAN from tan(), power(), -inf/inf, ...
> >
> > And, each way of calculating NAN gives a different NAN.
> 
> Interesting, thank you!
> Now I know, that I didn't know too much about NAN.

LOL!

> 
> > What should be done, is to do this.
> >
> > global constant
> > divNAN = -inf/inf,
> > powNAN = power(2, inf),
> > tanNAN = --however you get a NAN from tan()
> 
> Because of tan(x) = sin(x)/cos(x),
> tan(x) is undefined, if cos(x) = 0 (i.e. for x = .., -PI/2, PI/2, 3*PI/2, ..).
> BTW: With Euphoria, 'cos(PI/2)' does *not* return 0.

Perhaps its cuz the PI constant isnt accurate enough?

> 
> > ...etc for every possible way of calculating NAN.
> 
> I also found the following smile
> 
>    addNAN = inf + (-inf)

Why isnt this zero?

x + (-x) == 0, and if x == inf, that should still hold true, or am I overlooking
something? (Like, how 2 sets can be of inf size (i.e. are infinite sets) but
still have one set larger than the other?)

>    mulNAN = 0 * inf

You'd think that'd be 0 too ... (or maybe it has to do with the 1/inf == 0 and
1/0 != inf sort of thing?) /me faintly remembers reading somewhere that 0*inf
== 1

>    remNAN = remainder(inf, 1)

This one I can understand (barely).

> 
> > So, that, divNAN is reliable when using NANs from division, but not with
> > comparisons
> > to tanNANs, for example.
> >
> > Then, you can choose one NAN, to use as the return value ... as long as its
> > always the same NAN there is no problem. (Except of course, that NAN could
> > be
> > a valid return value ... but so could {-102354, -102354}, so theres no good
> > way of getting around that.)
> 
> In "What Every Computer Scientist Should Know About Floating-Point Arithmetic"
> <http://docs.sun.com/source/806-3568/ncg_goldberg.html>, David Goldberg
> writes, that the IEEE recommends a function Isnan(). In my imagination,
> this function would return TRUE for *any* NAN, and so help with this
> issue, right?
> 

Yes. But we'd have to write our own (unless Rob wants to make such a beast
builtin, or some wise human decides to wrap a C version via define_c_func).

> Best regards,
>    Juergen
> 

Of course, if we used nan, then the error lib would NOT be as usable for, say,
a program which did complex floating point math (in which cases NAN might be a
valid return value). In that case, that program would still have to do the
checks anyways.

IOW, since no user-defined value will always be an invalid result or
value, some programs will still have to do costly checks to be sure that
no error occurred.

At least my way (using -1), it becomes more of a habit.

Besides, you'd still have to check for procedures (which return no
value).

jbrown

> -- 
>  /"\  ASCII ribbon campain  |
>  \ /  against HTML in       |  This message has been ROT-13 encrypted
>   X   e-mail and news,      |  twice for higher security.
>  / \  and unneeded MIME     |
> 

-- 
 /"\  ASCII ribbon              | http://www.geocities.com/jbrown1050/
 \ /  campain against           | Linux User:190064
  X   HTML in e-mail and        | Linux Machine:84163
 /*\  news, and unneeded MIME   |

new topic     » goto parent     » topic index » view message » categorize

20. Re: How to handle crashes?

Hi Jim, you wrote:

> On Sat, Jun 07, 2003 at 07:33:52PM +0200, Juergen Luethje wrote:
>>
>>
>> Hi Jim, you wrote:

<snip>

>>> What should be done, is to do this.
>>>
>>> global constant
>>> divNAN = -inf/inf,
>>> powNAN = power(2, inf),
>>> tanNAN = --however you get a NAN from tan()
>>
>> Because of tan(x) = sin(x)/cos(x),
>> tan(x) is undefined, if cos(x) = 0 (i.e. for x = .., -PI/2, PI/2, 3*PI/2,
>> ..).
>> BTW: With Euphoria, 'cos(PI/2)' does *not* return 0.
>
> Perhaps its cuz the PI constant isnt accurate enough?

And also an IEEE double precision floating point number (8 bytes) isn't
accurate enough. Even in another language, which provides IEEE
*extended* precision floating point numbers (10 bytes), and using a PI
constant with 30 digits after the decimal point, I got for cos(PI/2) the
result 4.22838847269347E-18, but not 0.
I just mentioned that in order to say, that I don't see any possibility
for actually generating a 'tanNAN' with Eu. Well, I think we can live
with this fact ... blink

>>> ...etc for every possible way of calculating NAN.
>>
>> I also found the following smile
>>
>>    addNAN = inf + (-inf)
>
> Why isnt this zero?
>
> x + (-x) == 0, and if x == inf, that should still hold true, or am I
> overlooking
> something?

In arithmetic, there is no "number" inf, which can be used like x
for normal calculations. Calculating with such a "number" would lead to
strange results, e.g.:

Say   inf + (-inf) = 0.

Also  2*inf        = inf + inf.         But 2*inf = inf, so:
        inf        = inf + inf.         Now subtract inf from each side:
      inf - inf    = inf + inf - inf.   Or:
      inf + (-inf) = inf.

But didn't we say "inf + (-inf) = 0" ?  blink

> (Like, how 2 sets can be of inf size (i.e. are infinite sets) but
> still have one set larger than the other?)

Matt answered that better than I could have done. blink

>>    mulNAN = 0 * inf
>
> You'd think that'd be 0 too ... (or maybe it has to do with the 1/inf == 0 and
> 1/0 != inf sort of thing?) /me faintly remembers reading somewhere that 0*inf
> == 1

I found these addNAN, mulNAN, and remNAN in Goldberg's article cited
below, and tested them with Eu. But I think I'd better not claim that
I've fully understood that tricky concept of infinity. getlost

>>    remNAN = remainder(inf, 1)
>
> This one I can understand (barely).

I had tested this with the (2.4 beta) interpreter, and in the meantime I
realized, that using the (2.4 beta) translator and the Borland compiler,
remainder(inf, 1) is not NAN, but 0 ...

>>> So, that, divNAN is reliable when using NANs from division, but not with
>>> comparisons
>>> to tanNANs, for example.
>>>
>>> Then, you can choose one NAN, to use as the return value ... as long as its
>>> always the same NAN there is no problem. (Except of course, that NAN could
>>> be
>>> a valid return value ... but so could {-102354, -102354}, so theres no good
>>> way of getting around that.)
>>
>> In "What Every Computer Scientist Should Know About Floating-Point
>> Arithmetic"
>> <http://docs.sun.com/source/806-3568/ncg_goldberg.html>, David Goldberg
>> writes, that the IEEE recommends a function Isnan(). In my imagination,
>> this function would return TRUE for *any* NAN, and so help with this
>> issue, right?
>>
>
> Yes. But we'd have to write our own (unless Rob wants to make such a beast
> builtin, or some wise human decides to wrap a C version via define_c_func).

I've done so. Any improvements and corrections, if necessary, are of
course appreciated.

-----------------------------[ Begin Code ]-----------------------------
include machine.e

constant zero52 = repeat(0, 52)

global function isnan (object x)
   -- return TRUE, if and only if x is an IEEE 754 NaN value;
   -- tested with: o Eu 2.4 beta interpreter for Windows
   --              o Eu 2.4 beta translator and the Borland compiler
   sequence s, bits, mantissa
   integer exponent

   if sequence(x) then return 0 end if

   -- get the bit representation of an IEEE
   -- double precision floating point number
   s = atom_to_float64(x)
   bits = {}
   for i = 1 to 8 do
      bits &= int_to_bits(s[i], 8)
   end for

   -- check exponent and mantissa
   exponent = bits_to_int(bits[53..63]) - 1023
   if exponent = 1024 then
      mantissa = bits[1..52]
      if not equal(mantissa, zero52) then
         return 1
      end if
   end if
   return 0
end function


-- Demo
global constant
   POS_INF = 1.8e+307 * 10,
   NEG_INF = -POS_INF,
   addNAN  = -(POS_INF+NEG_INF),
   mulNAN  = -(0*POS_INF),
   divNAN  = -(POS_INF/POS_INF)

print(1, isnan("Hi!"))
print(1, isnan(0))
print(1, isnan(-3))
print(1, isnan(167.25))
print(1, isnan(POS_INF))
       ? isnan(NEG_INF)
print(1, isnan(addNAN))
print(1, isnan(mulNAN))
print(1, isnan(divNAN))
print(1, isnan(5/addNAN))
print(1, isnan(7+mulNAN))
       ? isnan(3*divNAN)
if getc(0) then end if
------------------------------[ End Code ]------------------------------

>> Best regards,
>>    Juergen
>>
>
> Of course, if we used nan, then the error lib would NOT be as usable for, say,
> a program which did complex floating point math (in which cases NAN might be a
> valid return value). In that case, that program would still have to do the
> checks anyways.

I can't imagine, in which situation NAN might be a valid return value.
Could you give me an example?

> IOW, since no user-defined value will always be an invalid result or
> value, some programs will still have to do costly checks to be sure that
> no error occurred.

BTW: My isnan() function is not without cost, too.

> At least my way (using -1), it becomes more of a habit.

I normally also use -1, if possible.

> Besides, you'd still have to check for procedures (which return no
> value).
>
> jbrown

Best regards,
   Juergen

-- 
 /"\  ASCII ribbon campain  |    |\      _,,,---,,_
 \ /  against HTML in       |    /,`.-'`'    -.  ;-;;,_
  X   e-mail and news,      |   |,4-  ) )-,_..;\ (  `'-'
 / \  and unneeded MIME     |  '---''(_/--'  `-'\_)

new topic     » goto parent     » topic index » view message » categorize

21. Re: How to handle crashes?

On Mon, Jun 09, 2003 at 03:53:38PM +0200, Juergen Luethje wrote:
> 
> 
> Hi Jim, you wrote:
> 
> > On Sat, Jun 07, 2003 at 07:33:52PM +0200, Juergen Luethje wrote:
> >>
> >>
> >> Hi Jim, you wrote:
> 
> <snip>
> 
> >>> What should be done, is to do this.
> >>>
> >>> global constant
> >>> divNAN = -inf/inf,
> >>> powNAN = power(2, inf),
> >>> tanNAN = --however you get a NAN from tan()
> >>
> >> Because of tan(x) = sin(x)/cos(x),
> >> tan(x) is undefined, if cos(x) = 0 (i.e. for x = .., -PI/2, PI/2, 3*PI/2,
> >> ..).
> >> BTW: With Euphoria, 'cos(PI/2)' does *not* return 0.
> >
> > Perhaps its cuz the PI constant isnt accurate enough?
> 
> And also an IEEE double precision floating point number (8 bytes) isn't
> accurate enough. Even in another language, which provides IEEE
> *extended* precision floating point numbers (10 bytes), and using a PI
> constant with 30 digits after the decimal point, I got for cos(PI/2) the
> result 4.22838847269347E-18, but not 0.

In my fraction lib, I considers implementing "special" values, which would be
interpreted as common "irrational" constants (such as PI, tho apparently PI
isn't irrational iirc).

Perhaps the IEEE specs should be updated for this idea as well? Then again,
maybe not.

> I just mentioned that in order to say, that I don't see any possibility
> for actually generating a 'tanNAN' with Eu. Well, I think we can live
> with this fact ... blink

lol

> 
> >>> ...etc for every possible way of calculating NAN.
> >>
> >> I also found the following smile
> >>
> >>    addNAN = inf + (-inf)
> >
> > Why isnt this zero?
> >
> > x + (-x) == 0, and if x == inf, that should still hold true, or am I
> > overlooking
> > something?
> 
> In arithmetic, there is no "number" inf, which can be used like x
> for normal calculations. Calculating with such a "number" would lead to
> strange results, e.g.:
> 
> Say   inf + (-inf) = 0.
> 
> Also  2*inf        = inf + inf.         But 2*inf = inf, so:
>         inf        = inf + inf.         Now subtract inf from each side:
>       inf - inf    = inf + inf - inf.   Or:
>       inf + (-inf) = inf.
> 
> But didn't we say "inf + (-inf) = 0" ?  blink

Oh.

> 
> > (Like, how 2 sets can be of inf size (i.e. are infinite sets) but
> > still have one set larger than the other?)
> 
> Matt answered that better than I could have done. blink
> 

> >>    mulNAN = 0 * inf
> >
> > You'd think that'd be 0 too ... (or maybe it has to do with the 1/inf == 0
> > and
> > 1/0 != inf sort of thing?) /me faintly remembers reading somewhere that
> > 0*inf
> > == 1
> 
> I found these addNAN, mulNAN, and remNAN in Goldberg's article cited
> below, and tested them with Eu. But I think I'd better not claim that
> I've fully understood that tricky concept of infinity. getlost
> 

Oh.

> >>    remNAN = remainder(inf, 1)
> >
> > This one I can understand (barely).
> 
> I had tested this with the (2.4 beta) interpreter, and in the meantime I
> realized, that using the (2.4 beta) translator and the Borland compiler,
> remainder(inf, 1) is not NAN, but 0 ...

Oh. Weird.

> 
> >>> So, that, divNAN is reliable when using NANs from division, but not with
> >>> comparisons
> >>> to tanNANs, for example.
> >>>
> >>> Then, you can choose one NAN, to use as the return value ... as long as
> >>> its
> >>> always the same NAN there is no problem. (Except of course, that NAN could
> >>> be
> >>> a valid return value ... but so could {-102354, -102354}, so theres no
> >>> good
> >>> way of getting around that.)
> >>
> >> In "What Every Computer Scientist Should Know About Floating-Point
> >> Arithmetic"
> >> <http://docs.sun.com/source/806-3568/ncg_goldberg.html>, David Goldberg
> >> writes, that the IEEE recommends a function Isnan(). In my imagination,
> >> this function would return TRUE for *any* NAN, and so help with this
> >> issue, right?
> >>
> >
> > Yes. But we'd have to write our own (unless Rob wants to make such a beast
> > builtin, or some wise human decides to wrap a C version via define_c_func).
> 
> I've done so. Any improvements and corrections, if necessary, are of
> course appreciated.
> 
<snip code>

Interesting. I'll test it out.

> 
> >> Best regards,
> >>    Juergen
> >>
> >
> > Of course, if we used nan, then the error lib would NOT be as usable for,
> > say,
> > a program which did complex floating point math (in which cases NAN might be
> > a
> > valid return value). In that case, that program would still have to do the
> > checks anyways.
> 
> I can't imagine, in which situation NAN might be a valid return value.
> Could you give me an example?

Experimental math programs, when doing complex math calculations (the meaning
of which is likely beyond my head ): may encounter NAN as a result, and not
necessarily as an invalid one.

For the average program tho, NAN (and perhaps INF as well) are likely to be
invalid return values... (one plus of using -1, is with the way Eu works,
-1 takes up 4 bytes while NAN/INF take up 8 bytes ... but thats mostly
a non issue these days).

> 
> > IOW, since no user-defined value will always be an invalid result or
> > value, some programs will still have to do costly checks to be sure that
> > no error occurred.
> 
> BTW: My isnan() function is not without cost, too.

No method of checking really is. (Although some do indeed cost less, all have
some cost.)

> 
> > At least my way (using -1), it becomes more of a habit.
> 
> I normally also use -1, if possible.

As do the libc functions. Like (I think) I said, I borrowed this practice
from C programming in Linux.

jbrown

> 
> > Besides, you'd still have to check for procedures (which return no
> > value).
> >
> > jbrown
> 
> Best regards,
>    Juergen
> 
> -- 
>  /"\  ASCII ribbon campain  |    |\      _,,,---,,_
>  \ /  against HTML in       |    /,`.-'`'    -.  ;-;;,_
>   X   e-mail and news,      |   |,4-  ) )-,_..;\ (  `'-'
>  / \  and unneeded MIME     |  '---''(_/--'  `-'\_)
> 
> 
> 
> TOPICA - Start your own email discussion group. FREE!
> 
> 

-- 
 /"\  ASCII ribbon              | http://www.geocities.com/jbrown1050/
 \ /  campain against           | Linux User:190064
  X   HTML in e-mail and        | Linux Machine:84163
 /*\  news, and unneeded MIME   |

new topic     » goto parent     » topic index » view message » categorize

22. Re: How to handle crashes?

Hi Jim, you wrote:

> On Mon, Jun 09, 2003 at 03:53:38PM +0200, Juergen Luethje wrote:
>>
>>
>> Hi Jim, you wrote:
>>
>>> On Sat, Jun 07, 2003 at 07:33:52PM +0200, Juergen Luethje wrote:
>>>>
>>>>
>>>> Hi Jim, you wrote:
>>
>> <snip>
>>
>>>>> What should be done, is to do this.
>>>>>
>>>>> global constant
>>>>> divNAN = -inf/inf,
>>>>> powNAN = power(2, inf),
>>>>> tanNAN = --however you get a NAN from tan()
>>>>
>>>> Because of tan(x) = sin(x)/cos(x),
>>>> tan(x) is undefined, if cos(x) = 0 (i.e. for x = .., -PI/2, PI/2, 3*PI/2,
>>>> ..).
>>>> BTW: With Euphoria, 'cos(PI/2)' does *not* return 0.
>>>
>>> Perhaps its cuz the PI constant isnt accurate enough?
>>
>> And also an IEEE double precision floating point number (8 bytes) isn't
>> accurate enough. Even in another language, which provides IEEE
>> *extended* precision floating point numbers (10 bytes), and using a PI
>> constant with 30 digits after the decimal point, I got for cos(PI/2) the
>> result 4.22838847269347E-18, but not 0.

Small correction for the record:
Although that language generally provides IEEE *extended* precision
floating point numbers, in the meantime I realized, that it's cos()
function only returns *double* precision floating point numbers.

> In my fraction lib, I considers implementing "special" values, which would be
> interpreted as common "irrational" constants

Does this mean, that your lib can handle symbols? I mean, for instance,
can your lib cancel an expression such as "PI*7/PI" to get the exact
result "7" directly? That would be cool. smile

> (such as PI, tho apparently PI isn't irrational iirc).

PI *is* irrational, that means it cannot be expressed as a fraction p/q
for any integers p and q.
However, there are rational approximations for PI, of course.
My favourite is the following, which also is easy to memorize:
     355/113 = 3.14159292...
Althogh this "formula" is very simple, it gives a correct value for PI
to 6 decimal places!

<snip>

[Eu function isnan()]

> Interesting. I'll test it out.

Very nice, thank you!

<snip>

>>> At least my way (using -1), it becomes more of a habit.
>>
>> I normally also use -1, if possible.
>
> As do the libc functions. Like (I think) I said, I borrowed this practice
> from C programming in Linux.

AFAIR I borrowed it from Euphoria and/or from you. blink

Unfortunately, Euphoria is somewhat inconsistent in this regard.
The following text is from the Euphoria 2.3 docs:

* "i1 = define_c_func(a, s1, s2, i2)
  -1 will be returned if the function can't be found."
* "i1 = define_c_proc(a, s1, s2)
  -1 will be returned if the function can't be found."
* "x = dir(st)
  If there is no file or directory with the name st then -1 is
  returned."
* "i = get_key()
  Return -1 if no key was pressed."
* "x1 = get_mouse()
  Return -1 if there has not been a mouse event since the last
  time get_mouse() was called."
* "i = getc(fn)
  -1 is returned at end of file."
* "x = getenv(s)
  If the variable is undefined return -1."
* "x = gets(fn)
  -1 is returned on end of file."
* "fn = open(st1, st2)
  -1 is returned if the open fails."
* "i = routine_id(st)
  -1 is returned if the named routine can't be found."
* "i1 = system_exec(st, i2)
  If it is not possible to run the program, system_exec() will
  return -1."

  ---=-------------=---

* "a = allocate(i)
  Return 0 if the memory can't be allocated."
* "i2 = allocate_low(i1)
  Return 0 if the memory can't be allocated."
* "a = allocate_string(s)
  If there is not enough memory available, 0 will be returned."
* "a = open_dll(st)
  0 will be returned if the .dll (or .so) can't be found."


IMHO it would be more elegant, if
   allocate()
   allocate_low()
   allocate_string()
   open_dll()

also would return -1, rather than 0.


Best regards,
   Juergen

-- 
 /"\  ASCII ribbon campain  |  while not asleep do
 \ /  against HTML in       |     sheep += 1
  X   e-mail and news,      |  end while
 / \  and unneeded MIME     |

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu