Author Topic: [DISMISSED] Setjmp/Longjmp as O2 Exception Handler  (Read 4773 times)

0 Members and 1 Guest are viewing this topic.

Mike Lobanovsky

  • Guest
[DISMISSED] Setjmp/Longjmp as O2 Exception Handler
« on: October 04, 2014, 12:30:12 PM »
Charles,

nanoscheme, as well as many other LISP interpreters, uses the setjmp/longjmp facility to recover from error states and failures at run time. I think it can also be used as a rudimentary first aid in making OxygenBasic fool-proof against access denial errors that currently crash faulty O2 applications irreversibly. setjmp/longjmp enable the program to restore the entire CPU state to what it was before the actual crash occured.

setjmp/longjmp is not recommended by MS for use in Windows applications, presumably in an attempt to promote their own, more versatile SEH schemes. Nonetheless _setjmp() and longjmp() are included in the msvcrt runtimes on all Windows platforms as CDECL functions.

Since O2 isn't currently coded in C, it can't enjoy SEH for app recovery but there's nothing prevents the use of setjmp/longjmp in it for similar, albeit simpler, purposes.

The definition of setjmp/longjmp paraphernalia is presented in MinGW GCC's public domain header file setjmp.h:

Code: [Select]
/*
 * setjmp.h
 * This file has no copyright assigned and is placed in the Public Domain.
 * This file is a part of the mingw-runtime package.
 * No warranty is given; refer to the file DISCLAIMER within the package.
 *
 * Declarations supporting setjmp and longjump, a method for avoiding
 * the normal function call return sequence. (Bleah!)
 *
 */

#ifndef _SETJMP_H_
#define _SETJMP_H_

/* All the headers include this file. */
#include <_mingw.h>

#ifndef RC_INVOKED

#ifdef __cplusplus
extern "C" {
#endif

/*
 * The buffer used by setjmp to store the information used by longjmp
 * to perform it's evil goto-like work. The size of this buffer was
 * determined through experimentation; it's contents are a mystery.
 * NOTE: This was determined on an i386 (actually a Pentium). The
 *       contents could be different on an Alpha or something else.
 */
#define _JBLEN 16
#define _JBTYPE int
typedef _JBTYPE jmp_buf[_JBLEN];

/*
 * The function provided by CRTDLL which appears to do the actual work
 * of setjmp.
 */
_CRTIMP int __cdecl __MINGW_NOTHROW _setjmp (jmp_buf);

#define setjmp(x) _setjmp(x)

/*
 * Return to the last setjmp call and act as if setjmp had returned
 * nVal (which had better be non-zero!).
 */
_CRTIMP void __cdecl __MINGW_NOTHROW longjmp (jmp_buf, int) __MINGW_ATTRIB_NORETURN;

#ifdef __cplusplus
}
#endif

#endif /* Not RC_INVOKED */

#endif /* Not _SETJMP_H_ */


Would it be of any use to OxygenBasic, do you think?
« Last Edit: October 04, 2014, 03:26:33 PM by Mike Lobanovsky »

Charles Pegge

  • Guest
Re: Setjmp/Longjmp as O2 Exception Handler
« Reply #1 on: October 04, 2014, 02:15:41 PM »
Mike,

It is easy to jump out and restore the stackpointer, but that leaves behind, potentially, lots of strings & buffers on the heap, which need to pass through the GC with local references for every function. However, it is an effective way of terminating a process. - but what about shutting down threads?

Mike Lobanovsky

  • Guest
Re: Setjmp/Longjmp as O2 Exception Handler
« Reply #2 on: October 04, 2014, 02:33:36 PM »
Charles,

jmp_buf[_JBLEN] stores/restores all of the CPU registers, not just its esp pointer. You're right about orphaned strings and threads (it's only SEH that enables you to unwind the call stack anyway), but setjmp/longjmp will at least enable you to display an intelligent message to the user as to why the program has to shut down, and will then call ExitProcess(-1) to terminate the program gracefully without the notorious app crash system message that leaves a very bad impression on the unfortunate user.

I didn't say it'll resolve all problems related to the crash and full recovery. I just called it a "rudimentary first aid" for saving the developer's face in an abnormal situation, didn't I? :)

Charles Pegge

  • Guest
Re: Setjmp/Longjmp as O2 Exception Handler
« Reply #3 on: October 04, 2014, 03:12:44 PM »
The basics, restoring critical registers:

sys ecxval,espval,ebpval
espval=esp
ebpVal=ebp


'ecx=888 : jmp fwd exception

function f(sys a,b,c)
sys i
do
  i++
  if i>100
    ecx=999 : jmp fwd exception
  end if
end do
end function

f 1,2,3


jmp fwd nexception:
exception:
call _mem 'restore the vital ebx register for all globals system calls
esp=espval
ebp=ebpval
ecxval=ecx
print "Error: " ecxval
nexception:

Mike Lobanovsky

  • Guest
Re: [DISMISSED] Setjmp/Longjmp as O2 Exception Handler
« Reply #4 on: October 04, 2014, 03:25:53 PM »
Pressing you I am not. Good and rewarding to find own ways always is.

May brighter sides of the Force be with you, jedi!

Charles Pegge

  • Guest
Re: [DISMISSED] Setjmp/Longjmp as O2 Exception Handler
« Reply #5 on: October 04, 2014, 03:44:59 PM »
Welsh syntax speak you?

Mike Lobanovsky

  • Guest
Re: [DISMISSED] Setjmp/Longjmp as O2 Exception Handler
« Reply #6 on: October 04, 2014, 03:51:50 PM »
Welsh it is not, Dagobahn it is.  ;D