From: Robert P. G. <rpg...@si...> - 2010-11-05 02:36:13
|
I'm sorry ---- I seem to be having a big collection of oddball problems right about now. I have some testing code that works correctly when it is invoked at the repl prompt. Or, more specifically, this testing code is invoked by a high level script, unit-test.lisp, and it works correctly when I do (load "unit-test.lisp"). This same code does /not/ work when it is invoked using --load, as in --load unit-test.lisp The code gets to an error handler, which seems to operate correctly, and then it drops me back to the REPL prompt. And indeed, when I type the load form at exactly this repl prompt, it works fine. The manual states that: --eval After executing any initialization file, but before starting the read-eval-print loop on standard input, read and evaluate the command given. More than one --eval option can be used, and all will be read and executed, in the order they appear on the command line. I was wondering what precisely it meant for the repl not to have been started on standard input, and whether this might somehow account for my problems. Are there any limits to the I/O that can be performed inside --eval or --load? Is there any special error-handling established? This occurs to me both on Mac OS X and Linux (both x86_64). Thanks! r |
From: Robert P. G. <rpg...@si...> - 2010-11-05 14:14:44
|
On 11/5/10 Nov 5 -4:30 AM, james anderson wrote: > > must be something special about to your unit-test code. > > i have run simple loops with handlers from loaded files no problem. > > > > ? command line argument order? There's a --no-userinit --load SBCLRC then --load unit-test The SBCLRC is a common (user-independent) configuration for the entire project. > > > > ? what's on the stack when the repl gets you. I don't know --- the system drops me to the repl and, as far as I can tell, that's it. > > > > ? which conditions could have been signaled? I have artificially injected an ERROR signal (the unit test tests error logging). The relevant surrounding code is this (sorry about the odd formatting --- gmane insists that I stick to 80-char lines): (handler-bind ((error #'(lambda (e) (unless (debug-error-p *world*) (log-message *world* :error "Attempting to continue from error ~a encountered during ASSESS-SUBGRAPH" e) #+sbcl (when (log-stream *world*) ;; don't let the backtrace printing blow up (ignore-errors (sb-debug:backtrace MOST-POSITIVE-FIXNUM (log-stream *world*)))) (continue e)))) (error #'(lambda (e) (unless (debug-error-p *world*) (log-message *world* :error "Failed to successfully continue from error ~a. Simply failing the call to ASSESS-SUBGRAPH." e) (return-from ASSESS-SUBGRAPH nil))))) ...) What happens is that the first ERROR handler fires, dumping the backtrace, tries to continue, and that fails. It falls through to the second error handler, which prints its log-message, and then we're dropped back into the REPL. Note that this is run inside the NST test library, which establishes its own error handlers. On the other hand, I don't see why that should matter --- when I run this at the REPL it works fine. I would have guessed that the backtrace might be a problem if the REPL isn't fully set up, but the fact that the second log message is printed tends to disconfirm that. I have determined that this is the location of the failure. I traced the function from which this snippet is drawn (ASSESS-SUBGRAPH). That function is entered (as we know), the second log-message is printed, and then we drop into the REPL. Despite the RETURN-FROM, the exit message from TRACE is never printed. This actually seems like it might be a bug... Cheers, r |
From: Nikodemus S. <nik...@ra...> - 2010-11-05 18:34:05
|
On 5 November 2010 16:14, Robert P. Goldman <rpg...@si...> wrote: > There's a --no-userinit --load SBCLRC then --load unit-test > > The SBCLRC is a common (user-independent) configuration for > the entire project. Try sbcl --userinit SBCLRC --load unit-test and sbcl --no-userinit --load SBCLRC followed by (load unit-test) in the REPL. . I would assume second the behave fail identically to the --load unit-test one, and the first to succeed. Userinit files are processed as if entered directly in the REPL (they're READ and EVAL'd, pretty much): so things like DECLAIM and IN-PACKAGE -- for example -- can have a different effect. --load and LOAD on the other hand should be identical. If my hypothesis is incorrect, then this does indeed sound like an SBCL bug. Cheers, -- Nikodemus |
From: Robert P. G. <rpg...@si...> - 2010-11-05 19:54:12
|
Nikodemus Siivola <nikodemus <at> random-state.net> writes: > > On 5 November 2010 16:14, Robert P. Goldman <rpgoldman <at> sift.info> wrote: > > > There's a --no-userinit --load SBCLRC then --load unit-test > > > > The SBCLRC is a common (user-independent) configuration for > > the entire project. > > Try > > sbcl --userinit SBCLRC --load unit-test This fails in the same way as before. > > and > > sbcl --no-userinit --load SBCLRC > followed by > (load unit-test) > in the REPL. This succeeds. > > . I would assume second the behave fail identically to the --load > unit-test one, and the first to succeed. Looks like I got exactly the opposite of what you expected. ... > If my hypothesis is incorrect, then this does indeed sound like an SBCL bug. If this is indeed a bug, please let me know what I can do to help track it down. Alas, I fear it's going to be very difficult to get a minimal test case, because of the cascading layers of error-handling.... I will answer some more of James A's questions; maybe these will help. Thank you very much for your help, Robert |
From: Robert P. G. <rpg...@si...> - 2010-11-05 20:04:54
|
On 11/5/10 Nov 5 -11:33 AM, james anderson wrote: > > naive questions: [James --- I hope you don't mind my responding through the mailing list --- I'm hoping that this stuff will be helpful to have in the googlable record.] > > does your process _ever_ successfully continue from the initial signaled > error? Yes. There are a number of possible things that could go wrong in there. For the ones I have foreseen, and for which there's a reasonable recovery strategy, I have provided CONTINUE restarts. But there are others (like a TIMEOUT), where I just treat things as a terminal faiilure. > that is you have errors and you signal them with > continuation-wrapped-signal forms rather than a call to error? Well, I call ERROR in some cases with a specialized condition that's a subclass of ERROR. > if not, > how is it possible that the second clause not run and effect an > immediate return from your function. likely to the listener? I think the above answers the question. Note that in the case I'm writing about, things are VERY complicated. This is not run simply inside the listener. Instead, it is inside: 1. A top level RUN-ONLINE call that establishes its own error handlers. Those error-handlers simply write the error message to a log file and continue (there's a logical place in RUN-ONLINE to which we can recover, basically by throwing an input data item on the floor and continuing as if it had never been read. 2. Not only that, but RUN-ONLINE is being run inside John Maraist's NST unit test library, which has its own error-handlers established since you typically don't want your unit test run to be disrupted by drops into the debugger. So there are at least two layers of error handling around this.... It really shouldn't drop into the listener. > if there really is a continuation established here, what is the advantage of > this control structure to calling downwards? two identical type specification > in the same binding are a new idiom for me. why do it? First we try to handle the error by invoking the CONTINUE restart. If this fails (typically because no such restart is established), the first handler will decline to handle the condition, it will fall through to the second, and the second handler will handle it in the more crude way (just return NIL). I hope that clarifies things. |
From: Robert P. G. <rpg...@si...> - 2010-11-05 20:10:20
|
On 11/5/10 Nov 5 -12:42 PM, james anderson wrote: > > i continue to reread your accounts and puzzle to try to divine the context. > > a described "exit message from TRACE" is not evident. What I did was wrap a TRACE form around this function (ASSESS-SUBGRAPH) to see if the second error handler correctly handled the error (by returning NIL from the function). I never saw the trace message, indicating to me that something bad happened between the printing of the log message and the RETURN-FROM (or in the RETURN-FROM). Best, r P.S. Just want to say once again thanks to everyone, particularly Nikodemus and James, for spending the time to help on this. |
From: james a. <jam...@se...> - 2010-11-05 21:12:40
|
On 2010-11-05, at 21:04 , Robert P. Goldman wrote: > On 11/5/10 Nov 5 -11:33 AM, james anderson wrote: >> >> naive questions: > > [James --- I hope you don't mind my responding through the mailing > list --- I'm > hoping that this stuff will be helpful to have in the googlable > record.] you are free to forward anything which happens to help you to understand more than it confuses. > [ ...] > > First we try to handle the error by invoking the CONTINUE restart. > If this > fails (typically because no such restart is established), the first > handler will > decline to handle the condition, it will fall through to the > second, and the > second handler will handle it in the more crude way (just return NIL). nikodemus, a question for you: where might one find discussion about why a call from a handler to continue is understood as a declining to handle? thanks, |
From: Nikodemus S. <nik...@ra...> - 2010-11-06 01:27:30
|
On 5 November 2010 22:39, james anderson <jam...@se...> wrote: > nikodemus, a question for you: where might one find discussion about > why a call from a handler to continue is understood as a declining to > handle? Um, it's not -- assuming the restart exists. The function CONTINUE is specified to return NIL if no restart named CONTINUE exists. CLHS sats: "If no such restart exists, the functions continue, store-value, and use-value return nil..." If it returns you have to do something else or you will eventually return from the handler-- ie. decline to handle. Cheers, -- Nikodemus |
From: Nikodemus S. <nik...@ra...> - 2010-11-06 01:36:00
|
Robert, I think I know what your issue is. Both --eval and --load establish a CONTINUE restart around the call to EVAL/LOAD. (Well, ABORT too.) I'm thinking your handlers end up picking the wrong restart. Cheers, -- Nikodemus |
From: Robert P. G. <rpg...@si...> - 2010-11-08 17:27:41
|
Nikodemus Siivola <nikodemus <at> random-state.net> writes: > > Robert, I think I know what your issue is. > > Both --eval and --load establish a CONTINUE restart around the call to > EVAL/LOAD. (Well, ABORT too.) > > I'm thinking your handlers end up picking the wrong restart. Yes, that was the solution. BTW, Christophe suggests that if I want my code to run in the same way code run at the REPL runs, I can put (load "unit-test") into a here document in the script. Something like exec sbcl --userinit SBCLRC <<EOF (load "unit-test") EOF I hope that this helps someone else downstream. Thanks to both of you for guiding me to this solution. Best, R |