Date: Sun, 28 Dec 1997 11:57:59 +0200 (IST) From: Eli Zaretskii To: Charles Sandmann cc: dj AT delorie DOT com, djgpp-workers AT delorie DOT com Subject: Re: `abort' with traceback In-Reply-To: <9712141924.AA15077@clio.rice.edu> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Precedence: bulk On Sun, 14 Dec 1997, Charles Sandmann wrote: > But it shouldn't be necessary to do a hw_exception to get a traceback - > just calling setjmp with a pointer to the exception structure and then > the call the traceback print routine. Even better yet, the raise() > routine should probably do this all for you, so someone can catch SIGABRT. The revised diffs are below. Please tell me if they seem about right. One place where I'm unsure if I did the right thing, is this: if (!__djgpp_exception_state_ptr) { /* This is a software signal, like SIGABRT or SIGKILL. Fill the exception structure, so we get the traceback. */ __djgpp_exception_state_ptr = &fake_exception; if (setjmp(__djgpp_exception_state)) { err("Bad longjmp to __djgpp_exception_state--aborting\r\n"); do_faulting_finish_message(0); /* does not return */ } *** src/libc/go32/dpmiexcp.c~1 Sun Dec 7 13:59:52 1997 --- src/libc/go32/dpmiexcp.c Sat Dec 27 14:14:24 1997 *************** dump_selector(const char *name, int sel) *** 163,169 **** } static void ! do_faulting_finish_message(void) { const char *en; unsigned long signum = __djgpp_exception_state->__signum; --- 163,169 ---- } static void ! do_faulting_finish_message(int fake_exception) { const char *en; unsigned long signum = __djgpp_exception_state->__signum; *************** do_faulting_finish_message(void) *** 177,205 **** exception_names[signum]; if (signum == 0x75) en = "Floating Point exception"; ! if (signum == 0x1b) en = "Control-Break Pressed"; ! if (signum == 0x79) en = "INTR key Pressed"; ! if (signum == 0x7a) en = "QUIT key Pressed"; if (en == 0) { ! err("Exception "); ! itox(signum, 2); ! err(" at eip="); ! itox(__djgpp_exception_state->__eip, 8); } else - { _write(STDERR_FILENO, en, strlen(en)); ! err(" at eip="); itox(__djgpp_exception_state->__eip, 8); - } if (signum == 0x79) { err("\r\n"); ! exit(-1); } if (signum <= EXCEPTION_COUNT && has_error[signum]) { --- 177,216 ---- exception_names[signum]; if (signum == 0x75) en = "Floating Point exception"; ! else if (signum == 0x1b) en = "Control-Break Pressed"; ! else if (signum == 0x79) en = "INTR key Pressed"; ! else if (signum == 0x7a) en = "QUIT key Pressed"; if (en == 0) { ! if (fake_exception) ! err("Raised"); ! else ! { ! err("Exception "); ! itox(signum, 2); ! } } else _write(STDERR_FILENO, en, strlen(en)); ! err(" at eip="); ! /* For fake exceptions like SIGABRT report where `raise' was called. */ ! if (fake_exception ! && __djgpp_exception_state->__cs == _my_cs() ! && (unsigned)__djgpp_exception_state->__ebp ! >= __djgpp_exception_state->__esp ! && (unsigned *)__djgpp_exception_state->__ebp >= &end ! && (unsigned *)__djgpp_exception_state->__ebp ! < (unsigned *)__djgpp_selector_limit) ! itox(*((unsigned *)__djgpp_exception_state->__ebp + 1), 8); ! else itox(__djgpp_exception_state->__eip, 8); if (signum == 0x79) { err("\r\n"); ! exit(-1); /* note: `exit', not `_exit' as for the rest of signals! */ } if (signum <= EXCEPTION_COUNT && has_error[signum]) { *************** do_faulting_finish_message(void) *** 230,236 **** err("\r\n"); if (__djgpp_exception_state->__cs == _my_cs()) show_call_frame(); ! exit(-1); } typedef void (*SignalHandler) (int); --- 241,247 ---- err("\r\n"); if (__djgpp_exception_state->__cs == _my_cs()) show_call_frame(); ! _exit(-1); } typedef void (*SignalHandler) (int); *************** int *** 257,262 **** --- 268,275 ---- raise(int sig) { SignalHandler temp; + jmp_buf fake_exception; + if(sig <= 0) return -1; if(sig > SIGMAX) *************** raise(int sig) *** 269,274 **** --- 282,303 ---- traceback_exit: if (sig >= SIGABRT && sig <= SIGTRAP) { + if (!__djgpp_exception_state_ptr) + { + /* This is a software signal, like SIGABRT or SIGKILL. + Fill the exception structure, so we get the traceback. */ + __djgpp_exception_state_ptr = &fake_exception; + if (setjmp(__djgpp_exception_state)) + { + err("Bad longjmp to __djgpp_exception_state--aborting\r\n"); + do_faulting_finish_message(0); /* does not return */ + } + else + /* Fake the exception number. 7Ah is the last one hardwired + inside exceptn.S, for SIGQUIT. */ + __djgpp_exception_state->__signum = 0x7a + 1 + sig - SIGABRT; + } + err("Exiting due to signal SIG"); _write(STDERR_FILENO, signames+(sig-SIGABRT)*4, 4); } *************** raise(int sig) *** 279,286 **** } err("\r\n"); if(__djgpp_exception_state_ptr) ! do_faulting_finish_message(); /* Exits, does not return */ ! exit(-1); } if((unsigned)temp < 4096 || temp > (SignalHandler)&end) { --- 308,316 ---- } err("\r\n"); if(__djgpp_exception_state_ptr) ! /* This exits, does not return. */ ! do_faulting_finish_message(__djgpp_exception_state == fake_exception); ! _exit(-1); } if((unsigned)temp < 4096 || temp > (SignalHandler)&end) { *************** __djgpp_exception_processor(void) *** 306,312 **** err("Cannot continue from exception, exiting due to signal "); itox(sig, 4); err("\r\n"); ! do_faulting_finish_message(); } static __dpmi_paddr except_ori[EXCEPTION_COUNT]; --- 336,342 ---- err("Cannot continue from exception, exiting due to signal "); itox(sig, 4); err("\r\n"); ! do_faulting_finish_message(0); } static __dpmi_paddr except_ori[EXCEPTION_COUNT]; *** src/libc/ansi/stdlib/abort.c~0 Sun Oct 6 00:33:20 1996 --- src/libc/ansi/stdlib/abort.c Sat Dec 27 12:25:02 1997 *************** *** 1,5 **** --- 1,6 ---- /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #include + #include #include #include *************** void *** 9,14 **** --- 10,16 ---- abort() { _write(STDERR_FILENO, msg, sizeof(msg)-1); + raise(SIGABRT); /* this will generate traceback and won't return */ _exit(1); } *** src/libc/go32/dpmiexcp.t~1 Sun Dec 7 13:49:46 1997 --- src/libc/go32/dpmiexcp.txh Sat Dec 27 14:33:48 1997 *************** given a mnemonic which you should use fo *** 42,57 **** The default handling for all the signals is to print a traceback (a stack dump which describes the sequence of function calls leading to the ! generation of the signal) and abort the program. (As an exception, the ! default handler for the signal @code{SIGINT} doesn't print the ! traceback when @kbd{Ctrl-C} is pressed.) ! ! This function allows you to change the default behavior for a specific ! signal. It registers @var{func} as a signal handler for signal number ! @var{sig}. After you register your function as the handler for a ! particular signal, it will be called when that signal occurs. The ! execution of the program will be suspended until the handler returns or ! calls @code{longjmp} (@pxref{longjmp}). You may pass @code{SIG_DFL} as the value of @var{func} to reset the signal handling for the signal @var{sig} to default (also --- 42,61 ---- The default handling for all the signals is to print a traceback (a stack dump which describes the sequence of function calls leading to the ! generation of the signal) and abort the program by calling @code{_exit} ! (@pxref{_exit}). As an exception, the default handler for the signal ! @code{SIGINT} doesn't print the traceback, and calls @code{exit} instead ! of @code{_exit}, when the INTR key (@kbd{Ctrl-C} by default) is pressed, ! so that programs could be shut down safely in this manner. ! @code{SIGINT} raised by @kbd{Ctrl- AT key{BREAK}} does generate the ! traceback. ! ! The function @code{signal} allows you to change the default behavior for ! a specific signal. It registers @var{func} as a signal handler for ! signal number @var{sig}. After you register your function as the ! handler for a particular signal, it will be called when that signal ! occurs. The execution of the program will be suspended until the ! handler returns or calls @code{longjmp} (@pxref{longjmp}). You may pass @code{SIG_DFL} as the value of @var{func} to reset the signal handling for the signal @var{sig} to default (also *************** The following signals are defined on @co *** 76,82 **** @item SIGABRT The Abort signal. Currently only used by the @code{assert} macro to ! terminate the program when an assertion fails (@pxref{assert}). @item SIGFPE --- 80,87 ---- @item SIGABRT The Abort signal. Currently only used by the @code{assert} macro to ! terminate the program when an assertion fails (@pxref{assert}), and by ! the @code{abort} function (@pxref{abort}). @item SIGFPE