From: Richard M K. <kr...@pr...> - 2008-05-26 13:58:29
|
"=?ISO-8859-1?Q?Hans_H=FCbner?=" writes: > I have recently been annoyed by the fact the PROBE-FILE uses > HANDLER-CASE to catch conditions signaled by QUERY-FILE-SYSTEM in > conjunction with using *BREAK-ON-SIGNALS*. PROBE-FILE is frequently > called to determine whether a files does _not_ exist, and with the > HANDLER-CASE based implementation I am always sent to the debugger in > such cases. Oops I must've forgotten about *BREAK-ON-SIGNALS* at some point. I'll apply your change (or something like it) on Wednesday, unless somebody else does so first. Regards, Richard |
From: Richard M K. <kr...@pr...> - 2008-05-29 21:03:29
|
"Hans Hübner" writes: > I am looking at this from a practical perspective, and I have a > concrete application in mind: Hunchentoot used to have a private > mechanism to control whether errors in HTTP handler functions are > caught and reported to the client or left unhandled so that they can > be debugged. We thought that Common Lisp already has such as > mechanism with *BREAK-ON-SIGNALS*, but using that showed to be harder > than expected because Hunchentoot itself uses PROBE-FILE, which always > signals (and catches) an error in SBCL. I'm not entirely clear what Hunchentoot's requirements are, but does *DEBUGGER-HOOK* do what you want? It would let your code decide what to do with otherwise-unhandled conditions, but not get involved in conditions that are already handled. -- Richard |
From: Peter S. <pe...@gi...> - 2008-05-29 21:47:56
|
Richard M Kreuter wrote: > "Hans Hübner" writes: > >> I am looking at this from a practical perspective, and I have a >> concrete application in mind: Hunchentoot used to have a private >> mechanism to control whether errors in HTTP handler functions are >> caught and reported to the client or left unhandled so that they can >> be debugged. We thought that Common Lisp already has such as >> mechanism with *BREAK-ON-SIGNALS*, but using that showed to be harder >> than expected because Hunchentoot itself uses PROBE-FILE, which always >> signals (and catches) an error in SBCL. > > I'm not entirely clear what Hunchentoot's requirements are, but does > *DEBUGGER-HOOK* do what you want? It would let your code decide what to > do with otherwise-unhandled conditions, but not get involved in > conditions that are already handled. Hmmm. That sounds risky--what if the user is using *DEBUGGER-HOOK* for their own purposes. You need at least to be sure that you observe the old value of *DEBUGGER-HOOK* and call it (which probably goes without saying) but even that depends on being sure that the user will set it before you bind it. It seems to me that the normal condition handler system gives you all the power you need to determine if a condition has been (or will be) handled. (Recall the old, resignal and *then* handle trick if you're worried about a condition-handler higher up on the stack handling a condition you are considering handling. But I don't think that applies in this case because all the user-code runs below a well-known point on the call stack.) -Peter -- Peter Seibel : pe...@gi... A Billion Monkeys Can't be Wrong : http://www.gigamonkeys.com/blog/ Practical Common Lisp : http://www.gigamonkeys.com/book/ Coders at Work : http://www.codersatwork.com/ |
From: Richard M K. <kr...@pr...> - 2008-05-29 01:13:40
|
Richard M Kreuter writes: > ""Hans Hübner" writes: > > > I have recently been annoyed by the fact the PROBE-FILE uses > > HANDLER-CASE to catch conditions signaled by QUERY-FILE-SYSTEM in > > conjunction with using *BREAK-ON-SIGNALS*. PROBE-FILE is frequently > > called to determine whether a files does _not_ exist, and with the > > HANDLER-CASE based implementation I am always sent to the debugger in > > such cases. > > Oops I must've forgotten about *BREAK-ON-SIGNALS* at some point. I'll > apply your change (or something like it) on Wednesday, unless somebody > else does so first. Change applied in 1.0.17.5. (Hans Hübner: may I ask whether setting *BREAK-ON-SIGNALS* to (NOT FILE-ERROR) would have sufficed for whatever you were doing? ISTM that somebody could raise the objection you did whenever any routine is implemented with condition handlers. So I wonder if the burden should be on the user to find a sufficiently precise value for *BREAK-ON-SIGNALS*, or on library implementors to use conditions sparingly.) -- Richard |
From: H. H. <ha...@hu...> - 2008-05-29 06:44:52
|
On Thu, May 29, 2008 at 3:12 AM, Richard M Kreuter <kr...@pr...> wrote: > (Hans Hübner: may I ask whether setting *BREAK-ON-SIGNALS* to > (NOT FILE-ERROR) would have sufficed for whatever you were doing? > ISTM that somebody could raise the objection you did whenever any routine > is implemented with condition handlers. So I wonder if the burden > should be on the user to find a sufficiently precise value for > *BREAK-ON-SIGNALS*, or on library implementors to use conditions > sparingly.) >From a user perspective, it is preferable to have libraries use signals sparingly, as it makes debugging harder. Also, one may be interested in, say FILE-ERRORS, yet have to disable breaking for them because PROBE-FILE uses it (and in this case, for no pressing reason). User convenience set aside, I think that conditions should generally be used in exceptional circumstances, not as a non-local 'goto' style mechanism. That is more or less a stylistic preference and there are algorithms which can be expressed elegantly and efficiently using condition signaling as non-local control transfer mechanism. Having to support *BREAK-ON-SIGNALS* is a reason for library implementors to not use this style. Lastly, there may be additional costs for setting up the signal handler, but as I am just a user, I can only speculate here. When I was a C++ programmer, the additional costs of exception handling was one of the additional, non-stylistic reasons for not using exceptions in non-exceptional situations. -Hans |
From: Nikodemus S. <nik...@ra...> - 2008-05-29 09:15:11
|
On Thu, May 29, 2008 at 9:44 AM, Hans Hübner <ha...@hu...> wrote: > Lastly, there may be additional costs for setting up the signal > handler There is a cost, but it should be mostly noise if there are syscalls involved. Apropos, now that we have (whee!) dynamic extent structures, we should be able to stack-allocate handlers and restarts, making all sorts condition handling code quite a bit faster in the common case. Cheers, -- Nikodemus |
From: Samium G. <_de...@fe...> - 2008-05-29 13:17:49
|
From: "Hans_Hübner" <ha...@hu...> Subject: Re: [Sbcl-devel] Use of signals in PROBE-FILE Date: Thu, 29 May 2008 08:44:49 +0200 > On Thu, May 29, 2008 at 3:12 AM, Richard M Kreuter <kr...@pr...> wrote: > > (Hans Hübner: may I ask whether setting *BREAK-ON-SIGNALS* to > > (NOT FILE-ERROR) would have sufficed for whatever you were doing? > > ISTM that somebody could raise the objection you did whenever any routine > > is implemented with condition handlers. So I wonder if the burden > > should be on the user to find a sufficiently precise value for > > *BREAK-ON-SIGNALS*, or on library implementors to use conditions > > sparingly.) > > From a user perspective, it is preferable to have libraries use > signals sparingly, as it makes debugging harder. Also, one may be > interested in, say FILE-ERRORS, yet have to disable breaking for them > because PROBE-FILE uses it (and in this case, for no pressing reason). My take on it is that, at least, a part of the real problem is in the fact CLHS doesn't specify more specific condition types. In this case, having FILE-DOES-NOT-EXIST-ERROR, as a subtype of FILE-ERROR, would've doubtless helped. regards, Samium Gromoff |
From: Richard M K. <kr...@pr...> - 2008-05-29 20:13:04
|
"Hans Hübner" writes: (Note: I've excised your arguments against the stylistic and performance aspects of signaling errors, to focus only the point about debugging and *BREAK-ON-SIGNALS*.) > From a user perspective, it is preferable to have libraries use > signals sparingly, as it makes debugging harder. Well the other way of looking at it is that setting *BREAK-ON-SIGNALS* to a type too high in the hierarchy is the culprit. After all, the CLHS entry for *BREAK-ON-SIGNALS* does say | When setting ‘*break-on-signals*’, the user is encouraged to choose | the most restrictive specification that suffices. Setting | ‘*break-on-signals*’ effectively violates the modular handling of | condition signaling. So from my point of view, setting *BREAK-ON-SIGNALS* to something like T amounts to asking to be notified about everybody else's use of the condition system, even if the program calling the signaling code is prepared to handle the condition. But I think there's a way of using *BREAK-ON-SIGNALS* without running aground on incidental uses in library code: * first, define some base condition class for your application, * then set *BREAK-ON-SIGNALS* to that type (or a union including that type, if you're debugging more than one application at a time), * finally, have all the errors that your code signals be generalized instances of that class (possibly inheriting also from other condition classes, e.g., FILE-ERROR). This way, you get into a break loop when code you care about signals, but not when anybody else's does. Wouldn't a practice like this give you what you want, without you needing to care about what random library code does? -- Richard |
From: H. H. <ha...@hu...> - 2008-05-29 20:24:52
|
On Thu, May 29, 2008 at 10:12 PM, Richard M Kreuter <kr...@pr...> wrote: > "Hans Hübner" writes: > > (Note: I've excised your arguments against the stylistic and performance > aspects of signaling errors, to focus only the point about debugging and > *BREAK-ON-SIGNALS*.) > >> From a user perspective, it is preferable to have libraries use >> signals sparingly, as it makes debugging harder. > > Well the other way of looking at it is that setting *BREAK-ON-SIGNALS* > to a type too high in the hierarchy is the culprit. After all, the CLHS > entry for *BREAK-ON-SIGNALS* does say > > | When setting '*break-on-signals*', the user is encouraged to choose > | the most restrictive specification that suffices. Setting > | '*break-on-signals*' effectively violates the modular handling of > | condition signaling. I am looking at this from a practical perspective, and I have a concrete application in mind: Hunchentoot used to have a private mechanism to control whether errors in HTTP handler functions are caught and reported to the client or left unhandled so that they can be debugged. We thought that Common Lisp already has such as mechanism with *BREAK-ON-SIGNALS*, but using that showed to be harder than expected because Hunchentoot itself uses PROBE-FILE, which always signals (and catches) an error in SBCL. It may be that the lack of modularity in this mechanism makes it unsuitable for this purpose, and that it would be better to retain a private mechanism that has a well-defined meaning and does not require a lot of tuning and fiddling to make it usefully work. From this discussion, I would think so. I would still not use HANDLER-CASE in PROBE-FILE, but that remains only as a stylistic comment. -Hans > > So from my point of view, setting *BREAK-ON-SIGNALS* to something like T > amounts to asking to be notified about everybody else's use of the > condition system, even if the program calling the signaling code is > prepared to handle the condition. > > But I think there's a way of using *BREAK-ON-SIGNALS* without running > aground on incidental uses in library code: > > * first, define some base condition class for your application, > > * then set *BREAK-ON-SIGNALS* to that type (or a union including that > type, if you're debugging more than one application at a time), > > * finally, have all the errors that your code signals be generalized > instances of that class (possibly inheriting also from other condition > classes, e.g., FILE-ERROR). > > This way, you get into a break loop when code you care about signals, > but not when anybody else's does. Wouldn't a practice like this give > you what you want, without you needing to care about what random library > code does? > > -- > Richard > |
From: Travis C. <tc...@tr...> - 2008-05-29 22:04:46
|
Hans Hübner wrote: > On Thu, May 29, 2008 at 10:12 PM, Richard M Kreuter > <kr...@pr...> wrote: >> "Hans Hübner" writes: Well the other way of looking at it is that >> setting *BREAK-ON-SIGNALS* to a type too high in the hierarchy is >> the culprit. After all, the CLHS entry for *BREAK-ON-SIGNALS* does >> say >> >> | When setting '*break-on-signals*', the user is encouraged to >> choose | the most restrictive specification that suffices. Setting >> | '*break-on-signals*' effectively violates the modular handling >> of | condition signaling. > > I am looking at this from a practical perspective, and I have a > concrete application in mind: Hunchentoot used to have a private > mechanism to control whether errors in HTTP handler functions are > caught and reported to the client or left unhandled so that they can > be debugged. We thought that Common Lisp already has such as > mechanism with *BREAK-ON-SIGNALS*, but using that showed to be harder > than expected because Hunchentoot itself uses PROBE-FILE, which > always signals (and catches) an error in SBCL. Hunchentoot should keep its *catch-errors-p* mechanism. *catch-errors-p* does something subtly and practically different than *break-on-signals*. Per the CLHS: > *break-on-signals* is intended primarily for use in debugging code > that does signaling. While hunchentoot code 'does signaling,' the signaling path isn't usually what you're debugging when you set *catch-errors-p* to nil. Setting it to nil simply turns off the default error handling in most of hunchentoot, allowing hunchentoot errors and unhandled errors from a user's hunchentoot dispatchers to reach the toplevel. Importantly, setting *catch-errors-p* to nil does *not* cause the lisp to break whenever a dispatcher throws a signal that gets caught before reaching hunchentoot code. I believe this is the behavior that conforms to the principle of least surprise. Using *break-on-signals* would cause breaks whenever user code (or library code) caused signals, even if they were handled. > I would still not use HANDLER-CASE in PROBE-FILE, but that remains > only as a stylistic comment. Stylistically, I think the PROBE-FILE code prior to 1.0.17.5 was more idiomatic for lisp, though the code there now could certainly claim to be slightly more direct. Cheers, -- Travis |
From: Kevin R. <kp...@ma...> - 2008-05-30 00:15:39
|
On May 29, 2008, at 16:12, Richard M Kreuter wrote: > | When setting ‘*break-on-signals*’, the user is encouraged to choose > | the most restrictive specification that suffices. Setting > | ‘*break-on-signals*’ effectively violates the modular handling of > | condition signaling. > > So from my point of view, setting *BREAK-ON-SIGNALS* to something > like T > amounts to asking to be notified about everybody else's use of the > condition system, even if the program calling the signaling code is > prepared to handle the condition. > > But I think there's a way of using *BREAK-ON-SIGNALS* without running > aground on incidental uses in library code: > > * first, define some base condition class for your application, While not especially relevant to this use case, I'd like to point out that another way to restrict *BREAK-ON-SIGNALS* for particular debugging is to use a SATISFIES type specifier; e.g. (setf *break-on-signals* `(and type-error (satisfies ,(defun #:interestingp (c) (eql (type-error-expected-type c) 'integer))))) I used this technique to break on errors of interest in a system much like Hunchentoot as described (that is, in normal operation, errors should be logged and the application returns to its event loop rather than breaking or exiting), except that I didn't even want to break on all propagated-to-the-event-loop errors. On May 29, 2008, at 18:04, Travis Cross wrote: > ... set *catch-errors-p* to nil. Setting it to nil simply turns off > the default error handling in most of hunchentoot, allowing > hunchentoot errors and unhandled errors from a user's hunchentoot > dispatchers to reach the toplevel. Importantly, setting *catch- > errors-p* to nil does *not* cause the lisp to break whenever a > dispatcher throws a signal that gets caught before reaching > hunchentoot code. This seems to me to be a better approach than using *break-on-signals*. A variation on this would be to, rather than not catching errors, invoke the debugger explicitly; this would inhibit handlers enclosing the event loop/catcher. That is, with *catch-errors-p* as described, this handler will be invoked: (handler-case (event-loop) (error ...)) whereas it won't with the variation. Whether that's desired would depend on the application. For mine, it seems like the ideal thing would be "invoke debugger if there would otherwise be a nonlocal exit out of (event-loop)", but I don't think that's expressible in CL. -- Kevin Reid <http://homepage.mac.com/kpreid/> |
From: Travis C. <tc...@tr...> - 2008-05-30 07:40:58
|
Kevin Reid wrote: > On May 29, 2008, at 18:04, Travis Cross wrote: >> ... set *catch-errors-p* to nil. Setting it to nil simply turns off >> the default error handling in most of hunchentoot, allowing >> hunchentoot errors and unhandled errors from a user's hunchentoot >> dispatchers to reach the toplevel. Importantly, setting *catch- >> errors-p* to nil does *not* cause the lisp to break whenever a >> dispatcher throws a signal that gets caught before reaching >> hunchentoot code. > > This seems to me to be a better approach than using *break-on-signals*. > > A variation on this would be to, rather than not catching errors, > invoke the debugger explicitly; this would inhibit handlers enclosing > the event loop/catcher. Actually, that is exactly what it does [1]. A better name might be *invoke-debugger-p* or similar. Hunchentoot shadows handler-case and ignore-errors with code like this: (defvar *catch-errors-p* t) (defgeneric maybe-invoke-debugger (condition) (:method (condition) (unless *catch-errors-p* (invoke-debugger condition)))) (defmacro with-debugger (&body body) `(handler-bind ((error #'maybe-invoke-debugger)) ,@body)) (defmacro handler-case (expression &rest clauses) `(cl:handler-case (with-debugger ,expression) ,@clauses)) Cheers, -- Travis [1] I should have been more precise in my earlier wording. |