Revision 33912

Date:
2008/12/15 06:11:01
Author:
tene
Revision Log:
[exceptions]
* Nonfatal exceptions are automatically resumed, after printing the message
* Default exception severity is EXCEPT_ERROR
Files:

Legend:

 
Added
 
Removed
 
Modified
  • trunk/docs/pdds/pdd23_exceptions.pod

     
    166 166 execution). Whether to resume or die when an exception isn't handled is
    167 167 determined by the severity of the exception.
    168 168
    169 {{NOTE: Not yet implemented, but should be easy}}
    170
    171 169 =item 6
    172 170 Otherwise terminate the program like C<die>.
    173 171
  • trunk/src/exceptions.c

     
    42 42
    43 43 PARROT_WARN_UNUSED_RESULT
    44 44 PARROT_CAN_RETURN_NULL
    45 static PMC * find_exception_handler(PARROT_INTERP, ARGIN(PMC *exception))
    45 static PMC * die_from_exception(PARROT_INTERP, ARGIN(PMC *exception))
    46 46 __attribute__nonnull__(1)
    47 47 __attribute__nonnull__(2);
    48 48
     
    89 89
    90 90 /*
    91 91
    92 =item C<static PMC * find_exception_handler>
    92 =item C<static PMC * die_from_exception>
    93 93
    94 Find the exception handler for C<exception>.
    94 Print a stack trace for C<exception>, a message if there is one, and then exit.
    95 95
    96 96 =cut
    97 97
     
    100 100 PARROT_WARN_UNUSED_RESULT
    101 101 PARROT_CAN_RETURN_NULL
    102 102 static PMC *
    103 find_exception_handler(PARROT_INTERP, ARGIN(PMC *exception))
    103 die_from_exception(PARROT_INTERP, ARGIN(PMC *exception))
    104 104 {
    105 PMC * const handler = Parrot_cx_find_handler_local(interp, exception);
    106 if (!PMC_IS_NULL(handler)) {
    107 return handler;
    108 }
    109 else {
    110 STRING * const message = VTABLE_get_string(interp, exception);
    111 INTVAL exit_status = 1;
    112 const INTVAL severity = VTABLE_get_integer_keyed_str(interp, exception, CONST_STRING(interp, "severity"));
    105 STRING * const message = VTABLE_get_string(interp, exception);
    106 INTVAL exit_status = 1;
    107 const INTVAL severity = VTABLE_get_integer_keyed_str(interp, exception, CONST_STRING(interp, "severity"));
    113 108
    114 /* flush interpreter output to get things printed in order */
    115 Parrot_io_flush(interp, Parrot_io_STDOUT(interp));
    116 Parrot_io_flush(interp, Parrot_io_STDERR(interp));
    109 /* flush interpreter output to get things printed in order */
    110 Parrot_io_flush(interp, Parrot_io_STDOUT(interp));
    111 Parrot_io_flush(interp, Parrot_io_STDERR(interp));
    117 112
    118 if (interp->debugger) {
    119 Parrot_io_flush(interp->debugger, Parrot_io_STDOUT(interp->debugger));
    120 Parrot_io_flush(interp->debugger, Parrot_io_STDERR(interp->debugger));
    121 }
    113 if (interp->debugger) {
    114 Parrot_io_flush(interp->debugger, Parrot_io_STDOUT(interp->debugger));
    115 Parrot_io_flush(interp->debugger, Parrot_io_STDERR(interp->debugger));
    116 }
    122 117
    123 if (string_equal(interp, message, CONST_STRING(interp, "")) == 1) {
    124 Parrot_io_eprintf(interp, "%S\n", message);
    118 if (string_equal(interp, message, CONST_STRING(interp, "")) == 1) {
    119 Parrot_io_eprintf(interp, "%S\n", message);
    125 120
    126 /* caution against output swap (with PDB_backtrace) */
    127 fflush(stderr);
    128 PDB_backtrace(interp);
    129 }
    130 else if (severity == EXCEPT_exit) {
    131 /* TODO: get exit status based on type */
    132 exit_status = VTABLE_get_integer_keyed_str(interp, exception, CONST_STRING(interp, "exit_code"));
    133 }
    134 else {
    135 Parrot_io_eprintf(interp, "No exception handler and no message\n");
    136 /* caution against output swap (with PDB_backtrace) */
    137 fflush(stderr);
    138 PDB_backtrace(interp);
    139 }
    121 /* caution against output swap (with PDB_backtrace) */
    122 fflush(stderr);
    123 PDB_backtrace(interp);
    124 }
    125 else if (severity == EXCEPT_exit) {
    126 /* TODO: get exit status based on type */
    127 exit_status = VTABLE_get_integer_keyed_str(interp, exception, CONST_STRING(interp, "exit_code"));
    128 }
    129 else {
    130 Parrot_io_eprintf(interp, "No exception handler and no message\n");
    131 /* caution against output swap (with PDB_backtrace) */
    132 fflush(stderr);
    133 PDB_backtrace(interp);
    134 }
    140 135
    141 /*
    142 * returning NULL from here returns resume address NULL to the
    143 * runloop, which will terminate the thread function finally
    144 *
    145 * RT #45917 this check should better be in Parrot_exit
    146 */
    136 /*
    137 * returning NULL from here returns resume address NULL to the
    138 * runloop, which will terminate the thread function finally
    139 *
    140 * RT #45917 this check should better be in Parrot_exit
    141 */
    147 142
    148 /* no exception handler, but this is not the main thread */
    149 if (interp->thread_data && interp->thread_data->tid)
    150 pt_thread_detach(interp->thread_data->tid);
    143 /* no exception handler, but this is not the main thread */
    144 if (interp->thread_data && interp->thread_data->tid)
    145 pt_thread_detach(interp->thread_data->tid);
    151 146
    152 /*
    153 * only main should run the destroy functions - exit handler chain
    154 * is freed during Parrot_exit
    155 */
    156 Parrot_exit(interp, exit_status);
    157 }
    158
    147 /*
    148 * only main should run the destroy functions - exit handler chain
    149 * is freed during Parrot_exit
    150 */
    151 Parrot_exit(interp, exit_status);
    159 152 }
    160 153
    161 154 /*
     
    197 190 Parrot_ex_throw_from_op(PARROT_INTERP, ARGIN(PMC *exception), ARGIN_NULLOK(void *dest))
    198 191 {
    199 192 opcode_t *address;
    200 PMC * const handler = find_exception_handler(interp, exception);
    193 PMC * const handler = Parrot_cx_find_handler_local(interp, exception);
    194 if (PMC_IS_NULL(handler)) {
    195 STRING * const message = VTABLE_get_string(interp, exception);
    196 const INTVAL severity = VTABLE_get_integer_keyed_str(interp, exception, CONST_STRING(interp, "severity"));
    197 if (severity < EXCEPT_error) {
    198 PMC *resume = VTABLE_get_attr_str(interp, exception,
    199 CONST_STRING(interp, "resume"));
    200 if (string_equal(interp, message, CONST_STRING(interp, "")) == 1) {
    201 Parrot_io_eprintf(interp, "%S\n", message);
    202 }
    203 else {
    204 Parrot_io_eprintf(interp, "%S\n", CONST_STRING(interp,"Warning"));
    205 }
    201 206
    202 if (!handler)
    203 return NULL;
    207 /* caution against output swap (with PDB_backtrace) */
    208 fflush(stderr);
    209 //PDB_backtrace(interp);
    204 210
    211 if (!PMC_IS_NULL(resume)) {
    212 return VTABLE_invoke(interp, resume, NULL);
    213 }
    214 }
    215 die_from_exception(interp, exception);
    216 }
    217
    205 218 address = VTABLE_invoke(interp, handler, dest);
    206 219
    207 220 /* Set up the continuation context of the handler in the interpreter. */
     
    275 288 void
    276 289 Parrot_ex_throw_from_c(PARROT_INTERP, ARGIN(PMC *exception))
    277 290 {
    278 PMC * const handler = find_exception_handler(interp, exception);
    291 PMC * const handler = Parrot_cx_find_handler_local(interp, exception);
    279 292 RunProfile * const profile = interp->profile;
    280 293 Parrot_runloop *return_point = interp->current_runloop;
    294 if (PMC_IS_NULL(handler)) {
    295 die_from_exception(interp, exception);
    296 }
    281 297
    282 298 /* If profiling, remember end time of lastop and generate entry for
    283 299 * exception. */
  • trunk/src/pmc/exception.pmc

     
    50 50 */
    51 51
    52 52 #include "parrot/parrot.h"
    53 #include "parrot/exceptions.h"
    53 54
    54 55 pmclass Exception {
    55 56
     
    90 91
    91 92 /* Set up the core struct and default values for the exception object. */
    92 93 PMC_data(SELF) = core_struct;
    93 core_struct->severity = 0;
    94 core_struct->severity = EXCEPT_error;
    94 95 core_struct->handled = 0;
    95 96 core_struct->message = CONST_STRING(interp, "");
    96 97 core_struct->payload = PMCNULL;
     
    122 123 PMC_data(SELF) = core_struct;
    123 124 core_struct->severity = ishash ?
    124 125 VTABLE_get_integer_keyed_str(interp, values, CONST_STRING(interp, 'severity')) :
    125 0;
    126 EXCEPT_error;
    126 127 core_struct->handled = 0;
    127 128 core_struct->message = ishash ?
    128 129 VTABLE_get_string_keyed_str(interp, values, CONST_STRING(interp, 'message')) :