Author: tene
Date: Sun Dec 14 22:11:01 2008
New Revision: 33912
Modified:
trunk/src/exceptions.c
trunk/src/pmc/exception.pmc
Changes in other areas also in this revision:
Modified:
trunk/docs/pdds/pdd23_exceptions.pod
Log:
[exceptions]
* Nonfatal exceptions are automatically resumed, after printing the message
* Default exception severity is EXCEPT_ERROR
Modified: trunk/src/exceptions.c
==============================================================================
--- trunk/src/exceptions.c (original)
+++ trunk/src/exceptions.c Sun Dec 14 22:11:01 2008
@@ -42,7 +42,7 @@
PARROT_WARN_UNUSED_RESULT
PARROT_CAN_RETURN_NULL
-static PMC * find_exception_handler(PARROT_INTERP, ARGIN(PMC *exception))
+static PMC * die_from_exception(PARROT_INTERP, ARGIN(PMC *exception))
__attribute__nonnull__(1)
__attribute__nonnull__(2);
@@ -89,9 +89,9 @@
/*
-=item C<static PMC * find_exception_handler>
+=item C<static PMC * die_from_exception>
-Find the exception handler for C<exception>.
+Print a stack trace for C<exception>, a message if there is one, and then exit.
=cut
@@ -100,62 +100,55 @@
PARROT_WARN_UNUSED_RESULT
PARROT_CAN_RETURN_NULL
static PMC *
-find_exception_handler(PARROT_INTERP, ARGIN(PMC *exception))
+die_from_exception(PARROT_INTERP, ARGIN(PMC *exception))
{
- PMC * const handler = Parrot_cx_find_handler_local(interp, exception);
- if (!PMC_IS_NULL(handler)) {
- return handler;
+ STRING * const message = VTABLE_get_string(interp, exception);
+ INTVAL exit_status = 1;
+ const INTVAL severity = VTABLE_get_integer_keyed_str(interp,
exception, CONST_STRING(interp, "severity"));
+
+ /* flush interpreter output to get things printed in order */
+ Parrot_io_flush(interp, Parrot_io_STDOUT(interp));
+ Parrot_io_flush(interp, Parrot_io_STDERR(interp));
+
+ if (interp->debugger) {
+ Parrot_io_flush(interp->debugger, Parrot_io_STDOUT(interp->debugger));
+ Parrot_io_flush(interp->debugger, Parrot_io_STDERR(interp->debugger));
}
- else {
- STRING * const message = VTABLE_get_string(interp, exception);
- INTVAL exit_status = 1;
- const INTVAL severity = VTABLE_get_integer_keyed_str(interp,
exception, CONST_STRING(interp, "severity"));
- /* flush interpreter output to get things printed in order */
- Parrot_io_flush(interp, Parrot_io_STDOUT(interp));
- Parrot_io_flush(interp, Parrot_io_STDERR(interp));
-
- if (interp->debugger) {
- Parrot_io_flush(interp->debugger,
Parrot_io_STDOUT(interp->debugger));
- Parrot_io_flush(interp->debugger,
Parrot_io_STDERR(interp->debugger));
- }
-
- if (string_equal(interp, message, CONST_STRING(interp, "")) == 1) {
- Parrot_io_eprintf(interp, "%S\n", message);
+ if (string_equal(interp, message, CONST_STRING(interp, "")) == 1) {
+ Parrot_io_eprintf(interp, "%S\n", message);
- /* caution against output swap (with PDB_backtrace) */
- fflush(stderr);
- PDB_backtrace(interp);
- }
- else if (severity == EXCEPT_exit) {
- /* TODO: get exit status based on type */
- exit_status = VTABLE_get_integer_keyed_str(interp, exception,
CONST_STRING(interp, "exit_code"));
- }
- else {
- Parrot_io_eprintf(interp, "No exception handler and no message\n");
- /* caution against output swap (with PDB_backtrace) */
- fflush(stderr);
- PDB_backtrace(interp);
- }
-
- /*
- * returning NULL from here returns resume address NULL to the
- * runloop, which will terminate the thread function finally
- *
- * RT #45917 this check should better be in Parrot_exit
- */
-
- /* no exception handler, but this is not the main thread */
- if (interp->thread_data && interp->thread_data->tid)
- pt_thread_detach(interp->thread_data->tid);
-
- /*
- * only main should run the destroy functions - exit handler chain
- * is freed during Parrot_exit
- */
- Parrot_exit(interp, exit_status);
+ /* caution against output swap (with PDB_backtrace) */
+ fflush(stderr);
+ PDB_backtrace(interp);
+ }
+ else if (severity == EXCEPT_exit) {
+ /* TODO: get exit status based on type */
+ exit_status = VTABLE_get_integer_keyed_str(interp, exception,
CONST_STRING(interp, "exit_code"));
+ }
+ else {
+ Parrot_io_eprintf(interp, "No exception handler and no message\n");
+ /* caution against output swap (with PDB_backtrace) */
+ fflush(stderr);
+ PDB_backtrace(interp);
}
+ /*
+ * returning NULL from here returns resume address NULL to the
+ * runloop, which will terminate the thread function finally
+ *
+ * RT #45917 this check should better be in Parrot_exit
+ */
+
+ /* no exception handler, but this is not the main thread */
+ if (interp->thread_data && interp->thread_data->tid)
+ pt_thread_detach(interp->thread_data->tid);
+
+ /*
+ * only main should run the destroy functions - exit handler chain
+ * is freed during Parrot_exit
+ */
+ Parrot_exit(interp, exit_status);
}
/*
@@ -197,10 +190,30 @@
Parrot_ex_throw_from_op(PARROT_INTERP, ARGIN(PMC *exception),
ARGIN_NULLOK(void *dest))
{
opcode_t *address;
- PMC * const handler = find_exception_handler(interp, exception);
+ PMC * const handler = Parrot_cx_find_handler_local(interp, exception);
+ if (PMC_IS_NULL(handler)) {
+ STRING * const message = VTABLE_get_string(interp, exception);
+ const INTVAL severity = VTABLE_get_integer_keyed_str(interp,
exception, CONST_STRING(interp, "severity"));
+ if (severity < EXCEPT_error) {
+ PMC *resume = VTABLE_get_attr_str(interp, exception,
+ CONST_STRING(interp, "resume"));
+ if (string_equal(interp, message, CONST_STRING(interp, "")) == 1) {
+ Parrot_io_eprintf(interp, "%S\n", message);
+ }
+ else {
+ Parrot_io_eprintf(interp, "%S\n",
CONST_STRING(interp,"Warning"));
+ }
- if (!handler)
- return NULL;
+ /* caution against output swap (with PDB_backtrace) */
+ fflush(stderr);
+ //PDB_backtrace(interp);
+
+ if (!PMC_IS_NULL(resume)) {
+ return VTABLE_invoke(interp, resume, NULL);
+ }
+ }
+ die_from_exception(interp, exception);
+ }
address = VTABLE_invoke(interp, handler, dest);
@@ -275,9 +288,12 @@
void
Parrot_ex_throw_from_c(PARROT_INTERP, ARGIN(PMC *exception))
{
- PMC * const handler = find_exception_handler(interp,
exception);
+ PMC * const handler = Parrot_cx_find_handler_local(interp, exception);
RunProfile * const profile = interp->profile;
Parrot_runloop *return_point = interp->current_runloop;
+ if (PMC_IS_NULL(handler)) {
+ die_from_exception(interp, exception);
+ }
/* If profiling, remember end time of lastop and generate entry for
* exception. */
Modified: trunk/src/pmc/exception.pmc
==============================================================================
--- trunk/src/pmc/exception.pmc (original)
+++ trunk/src/pmc/exception.pmc Sun Dec 14 22:11:01 2008
@@ -50,6 +50,7 @@
*/
#include "parrot/parrot.h"
+#include "parrot/exceptions.h"
pmclass Exception {
@@ -90,7 +91,7 @@
/* Set up the core struct and default values for the exception object.
*/
PMC_data(SELF) = core_struct;
- core_struct->severity = 0;
+ core_struct->severity = EXCEPT_error;
core_struct->handled = 0;
core_struct->message = CONST_STRING(interp, "");
core_struct->payload = PMCNULL;
@@ -122,7 +123,7 @@
PMC_data(SELF) = core_struct;
core_struct->severity = ishash ?
VTABLE_get_integer_keyed_str(interp, values, CONST_STRING(interp,
'severity')) :
- 0;
+ EXCEPT_error;
core_struct->handled = 0;
core_struct->message = ishash ?
VTABLE_get_string_keyed_str(interp, values, CONST_STRING(interp,
'message')) :