From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Neil Jerram Newsgroups: gmane.lisp.guile.devel Subject: Backtrace and enhanced catch Date: Wed, 04 Jan 2006 21:13:55 +0000 Message-ID: <87acebhf1o.fsf@ossau.uklinux.net> References: <200511301616.22258.bkorb@gnu.org> <87wthpkyan.fsf@ossau.uklinux.net> <43B69F41.6030509@xs4all.nl> <87hd8pb8o7.fsf@ossau.uklinux.net> <87lkxy3abo.fsf@ossau.uklinux.net> <877j9i31gc.fsf@ossau.uklinux.net> NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: sea.gmane.org 1136409387 12539 80.91.229.2 (4 Jan 2006 21:16:27 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Wed, 4 Jan 2006 21:16:27 +0000 (UTC) Cc: guile-devel@gnu.org Original-X-From: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Wed Jan 04 22:16:25 2006 Return-path: Envelope-to: guile-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by ciao.gmane.org with esmtp (Exim 4.43) id 1EuFzN-0002eW-OG for guile-devel@m.gmane.org; Wed, 04 Jan 2006 22:16:10 +0100 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1EuG13-0003jr-Ux for guile-devel@m.gmane.org; Wed, 04 Jan 2006 16:17:54 -0500 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1EuG0y-0003jE-QR for guile-devel@gnu.org; Wed, 04 Jan 2006 16:17:48 -0500 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1EuG0w-0003i2-1J for guile-devel@gnu.org; Wed, 04 Jan 2006 16:17:48 -0500 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1EuG0v-0003hw-Tu for guile-devel@gnu.org; Wed, 04 Jan 2006 16:17:45 -0500 Original-Received: from [80.84.72.33] (helo=mail3.uklinux.net) by monty-python.gnu.org with esmtp (Exim 4.34) id 1EuG2N-0000gg-OK for guile-devel@gnu.org; Wed, 04 Jan 2006 16:19:16 -0500 Original-Received: from laruns (host86-129-132-201.range86-129.btcentralplus.com [86.129.132.201]) by mail3.uklinux.net (Postfix) with ESMTP id DF998409FB4; Wed, 4 Jan 2006 21:15:56 +0000 (UTC) Original-Received: from laruns (laruns [127.0.0.1]) by laruns (Postfix) with ESMTP id B5D906F658; Wed, 4 Jan 2006 21:13:55 +0000 (GMT) Original-To: hanwen@xs4all.nl User-Agent: Gnus/5.1007 (Gnus v5.10.7) Emacs/21.4 (gnu/linux) X-BeenThere: guile-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Developers list for Guile, the GNU extensibility library" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Errors-To: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.lisp.guile.devel:5578 Archived-At: Neil Jerram writes: > I think the only really good fix for this would be to implement an > exception handling mechanism that doesn't rely on lazy catch, along > the lines of SRFI-34. On second thoughts, after rereading SRFI-34, I don't think that's the solution. SRFI-34's with-exception-handler is so similar to Guile's existing lazy-catch that it doesn't give us anything better than we have already. I have a solution in mind, however, which is to add an optional fourth arg ("lazy-handler") to `catch' (and corresponding C APIs, such as scm_internal_catch), whose effect is the same as what we currently use lazy-catch for. For the specific problem that motivated this investigation - getting a backtrace out of "guile --debug g.scm" - we can then use this lazy-handler arg to display a backtrace and full error information. The following text explains how I've reached this conclusion. Overall there are two approaches for capturing or displaying the stack when an error occurs. Either you have an enclosing call like lazy-catch or with-exception-handler somewhere up the call stack, which specifies a handler to run in the case that an error escapes back up to that point. Or you add a throw-hook or error-hook to the implementation of throw or error, and add the stack handling code to that hook. The difference is that the enclosing call approach allows code inbetween the lazy-catch and the error point to decide on a different, more local strategy for handling the error, whereas the hook approach doesn't. I think it's clear that the enclosing call approach is better, so will focus on that from here on, but in principle we could provide both in Guile. My proposal here doesn't rule out adding a hook as well in future. There is a problem, though, with both lazy-catch and with-exception-handler (which are the current Guile and SRFI-34 implementations of the enclosing call approach). On the one hand they require the handler to execute a non-local jump: the lazy-catch doc says that its handler must not return, and SRFI-34 says that the handler's continuation is not defined; on the other hand they need to ensure that this jump is not handled by the same handler again. In the SRFI-34 case this leads to a strange rule: the handler must be executed in the dynamic context of the error, except with the current with-exception-handler handler removed; and it is not clear what happens in odd but possible cases where, for example, the jump is to a location that is still inside the dynamic scope of the relevant with-exception-handler expression. In the lazy-catch case the implementation avoids the possibility of the jump being caught by the same handler by unwinding the dynamic context - all except for the call stack - back to the lazy-catch expression before it calls the handler. So the lazy-catch handler isn't in fact consistently lazy: fluid values, for example, are not those in the context of the error, but those back in the context of the lazy-catch expression. Another (lesser) problem with lazy-catch and with-exception-handler is that they are always used in practice in a particular pattern. For lazy-catch the pattern is (catch tag (lambda () (lazy-catch tag thunk lazy-handler)) catch-handler) For with-exception-handler the pattern (as shown by all the examples in SRFI-34) is (call/cc (lambda (k) (with-exception-handler (lambda (obj) ... (k 'exception)) thunk))) Why is this a problem? Because it strongly suggests that these forms are more general than is useful. And there is a cost to this: a bit more typing in Scheme, and in the case of Guile a lot more complexity in the C code needed to set up a catch and lazy catch pair (which is relevant to the backtrace problem). We can solve both problems by merging the semantics of catch and lazy-catch into a single form, an enhanced catch: -- Scheme Procedure: catch key thunk handler [lazy-handler] ... [existing documentation] ... If a LAZY-HANDLER is given and THUNK throws an exception that matches KEY, Guile calls the LAZY-HANDLER before unwinding the dynamic state and invoking the main HANDLER. LAZY-HANDLER should be a procedure with the same signature as HANDLER, that is `(lambda (key . args))', and must return normally, in other words not call `throw' or a continuation. It is typically used to save the stack at the point where the exception occurred, but can also query other parts of the dynamic state at that point, such as fluid values. We would add the same facility to C APIs for setting up catches (with regard for backward compatibility, of course), and then finally we can use the modified API to set up a lazy-handler inside scm_c_with_continuation_barrier() that will save the stack so that a backtrace can be displayed (or just to display the backtrace directly, perhaps). We will also be able to provide a standard lazy-handler for displaying a backtrace, in both Scheme and C, which I think will give us a nicer answer to the recurring "how do I get error information" questions on the mailing list than what we have now. lazy-catch itself can be deprecated and eventually removed. All the lazy-catch uses in Guile's own code follow the pattern above and so can be rewritten as an enhanced catch, except for one (in ice-9/emacs.scm) which is incorrect anyway because it can return normally. Comments? If no one objects I will implement this (and fix the backtrace problem) over the next few weeks. Regards, Neil _______________________________________________ Guile-devel mailing list Guile-devel@gnu.org http://lists.gnu.org/mailman/listinfo/guile-devel