Browse Source

Add duk_fatal_exception for C++ uncaught/fatal

pull/1915/head
Sami Vaarala 7 years ago
parent
commit
7b1223d1da
  1. 15
      src-input/duk_error_longjmp.c
  2. 12
      src-input/duk_error_macros.c
  3. 20
      src-input/duk_exception.h
  4. 5
      src-input/duk_js_call.c
  5. 5
      src-input/duk_js_executor.c

15
src-input/duk_error_longjmp.c

@ -76,14 +76,9 @@ DUK_INTERNAL void duk_err_longjmp(duk_hthread *thr) {
DUK_DD(DUK_DDPRINT("about to longjmp, pf_prevent_count=%ld", (long) thr->heap->pf_prevent_count));
#if !defined(DUK_USE_CPP_EXCEPTIONS)
/* If we don't have a jmpbuf_ptr, there is little we can do except
* cause a fatal error. The caller's expectation is that we never
* return.
*
* With C++ exceptions we now just propagate an uncaught error
* instead of invoking the fatal error handler. Because there's
* a dummy jmpbuf for C++ exceptions now, this could be changed.
*/
if (!thr->heap->lj.jmpbuf_ptr) {
DUK_D(DUK_DPRINT("uncaught error: type=%d iserror=%d value1=%!T value2=%!T",
@ -97,16 +92,12 @@ DUK_INTERNAL void duk_err_longjmp(duk_hthread *thr) {
#endif
DUK_UNREACHABLE();
}
#endif /* DUK_USE_CPP_EXCEPTIONS */
#if defined(DUK_USE_CPP_EXCEPTIONS)
{
duk_internal_exception exc; /* dummy */
throw exc;
}
#else /* DUK_USE_CPP_EXCEPTIONS */
throw duk_internal_exception(); /* dummy */
#else
DUK_LONGJMP(thr->heap->lj.jmpbuf_ptr->jb);
#endif /* DUK_USE_CPP_EXCEPTIONS */
#endif
DUK_UNREACHABLE();
}

12
src-input/duk_error_macros.c

@ -113,10 +113,18 @@ DUK_INTERNAL DUK_COLD void duk_default_fatal_handler(void *udata, const char *ms
DUK_UNREF(udata);
DUK_UNREF(msg);
msg = msg ? msg : "NULL";
#if defined(DUK_USE_FATAL_HANDLER)
/* duk_config.h provided a custom default fatal handler. */
DUK_D(DUK_DPRINT("custom default fatal error handler called: %s", msg ? msg : "NULL"));
DUK_D(DUK_DPRINT("custom default fatal error handler called: %s", msg));
DUK_USE_FATAL_HANDLER(udata, msg);
#elif defined(DUK_USE_CPP_EXCEPTIONS)
/* With C++ use a duk_fatal_exception which user code can catch in
* a natural way.
*/
DUK_D(DUK_DPRINT("built-in default C++ fatal error handler called: %s", msg));
throw duk_fatal_exception(msg);
#else
/* Default behavior is to abort() on error. There's no printout
* which makes this awkward, so it's always recommended to use an
@ -133,7 +141,7 @@ DUK_INTERNAL DUK_COLD void duk_default_fatal_handler(void *udata, const char *ms
* - http://duktape.org/api.html#taglist-protected
* ====================================================================
*/
DUK_D(DUK_DPRINT("built-in default fatal error handler called: %s", msg ? msg : "NULL"));
DUK_D(DUK_DPRINT("built-in default fatal error handler called: %s", msg));
DUK_ABORT();
#endif

20
src-input/duk_exception.h

@ -1,18 +1,30 @@
/*
* Exception for Duktape internal throws when C++ exceptions are used
* Exceptions for Duktape internal throws when C++ exceptions are used
* for long control transfers.
*
* Doesn't inherit from any exception base class to minimize the chance
* that user code would accidentally catch this exception.
*/
#if !defined(DUK_EXCEPTION_H_INCLUDED)
#define DUK_EXCEPTION_H_INCLUDED
#if defined(DUK_USE_CPP_EXCEPTIONS)
/* Internal exception used as a setjmp-longjmp replacement. User code should
* NEVER see or catch this exception, so it doesn't inherit from any base
* class which should minimize the chance of user code accidentally catching
* the exception.
*/
class duk_internal_exception {
/* intentionally empty */
};
/* Fatal error, thrown as a specific C++ exception with C++ exceptions
* enabled. It is unsafe to continue; doing so may cause crashes or memory
* leaks. This is intended to be either uncaught, or caught by user code
* aware of the "unsafe to continue" semantics.
*/
class duk_fatal_exception : public virtual std::runtime_error {
public:
duk_fatal_exception(const char *message) : std::runtime_error(message) {}
};
#endif
#endif /* DUK_EXCEPTION_H_INCLUDED */

5
src-input/duk_js_call.c

@ -2724,7 +2724,10 @@ DUK_INTERNAL duk_int_t duk_handle_safe_call(duk_hthread *thr,
retval = DUK_EXEC_ERROR;
}
#if defined(DUK_USE_CPP_EXCEPTIONS)
catch (std::exception &exc) {
catch (duk_fatal_exception &exc) {
DUK_D(DUK_DPRINT("rethrow duk_fatal_exception"));
throw;
} catch (std::exception &exc) {
const char *what = exc.what();
DUK_ASSERT((duk_size_t) ((duk_uint8_t *) thr->valstack_end - (duk_uint8_t *) thr->valstack) >= entry_valstack_end_byteoff);
DUK_STATS_INC(thr->heap, stats_safecall_throw);

5
src-input/duk_js_executor.c

@ -2937,7 +2937,10 @@ DUK_INTERNAL void duk_js_execute_bytecode(duk_hthread *exec_thr) {
entry_jmpbuf_ptr);
}
#if defined(DUK_USE_CPP_EXCEPTIONS)
catch (std::exception &exc) {
catch (duk_fatal_exception &exc) {
DUK_D(DUK_DPRINT("rethrow duk_fatal_exception"));
throw;
} catch (std::exception &exc) {
const char *what = exc.what();
if (!what) {
what = "unknown";

Loading…
Cancel
Save