Kirk Job Sluder <kirk-nospam@jobsluder.net> wrote:
+---------------
| rpw3@rpw3.org (Rob Warnock) wrote:
| > ;;; Somewhere in your init code:
| > (defvar *old-sigpipe-handler* (system:enable-interrupt :sigpipe :ignore))
| > Then wrap the following around your outputting code:
| > (handler-case
| > (send-output stream) ; the main work
| > (error (condition)....;
...
| It turns out I didn't have a problem with openmcl SIGPIPE (at least not
| in this case. This simplifies the problem, giving at least one desired
| result, a graceful exit to the program.
|
| (defun main ()
| "Main entry point for program."
| (handler-case (validate-chat-summary-file)
| (error (condition) ;see question below.
| (progn
| (format *error-output* "~a~%" condition) ;this fails to produce
| output.
| ;(force-output *error-output*) ;this hangs
| (quit))))
| (quit))
|
|
| Still, I have some questions. Why would the write to *error-output*
| here hang?
+---------------
Hmmm... You might want to try running the OpenMCL equivalent of the
following and see what you get. In particular, see if *ERROR-OUTPUT*
is bound to your terminal or if by default *ERROR-OUTPUT* is bound
to the same thing as *STANDARD-OUTPUT*, which would explain the behavior
you're seeing. That is, what I guessing might be happening is that
by default OpenMCL maps *both* *ERROR-OUTPUT* & *STANDARD-OUTPUT* to
the process's standard output, so that when you pipe it into "less"
(say) and the pipe break, *both* *ERROR-OUTPUT* & *STANDARD-OUTPUT*
get jammed up. [If this is correct, there might be a different OpenMCL
stream variable you can use to get your error output, maybe *DEBUG-IO*
or *TERMINAL-IO*, see below.]
Start with just the "standardized stream variables" [CLHS 21.1.2
"Stream Variables"] listed just above the first comment below, and
then add more as you discover any implementation-dependent variables
they map to [are "synonym streams" for -- the ones below the comment].
Then when you get to "ground" stream objects, run DESCRIBE on them,
and see what the bottommost things pointed to by *STANDARD-OUTPUT*
and *ERROR-OUTPUT* really are. Here's what I ended up with for CMUCL:
$ cat ./describe-streams
#!/usr/local/bin/cmucl -script
(dolist (name '(*debug-io*
*error-output*
*query-io*
*standard-input*
*standard-output*
*terminal-io*
*trace-output*
;; The following added after looking
;; at the output from the above set.
system:*stdin*
system:*stdout*
system:*stderr*
system:*tty*
))
(format t "~s ==> ~s~%" name (symbol-value name)))
(dolist (name '(system:*stdin*
system:*stdout*
system:*stderr*
system:*tty*
))
(format t "~%~%(describe '~s) ==>~%" name)
(describe name))
$
When run, this gives [trimmed for brevity] the following:
$ ./describe-streams | cat
*DEBUG-IO* ==> #<Synonym Stream to *TERMINAL-IO*>
*ERROR-OUTPUT* ==> #<Synonym Stream to SYSTEM:*STDERR*>
*QUERY-IO* ==> #<Synonym Stream to *TERMINAL-IO*>
*STANDARD-INPUT* ==> #<Two-Way Stream, Input = #<Synonym Stream
to SYSTEM:*STDIN*>, Output = #<Synonym Stream to SYSTEM:*STDOUT*>>
*STANDARD-OUTPUT* ==> #<Synonym Stream to SYSTEM:*STDOUT*>
*TERMINAL-IO* ==> #<Synonym Stream to SYSTEM:*TTY*>
*TRACE-OUTPUT* ==> #<Synonym Stream to SYSTEM:*STDOUT*>
SYSTEM:*STDIN* ==> #<Stream for Standard Input>
SYSTEM:*STDOUT* ==> #<Stream for Standard Output>
SYSTEM:*STDERR* ==> #<Stream for Standard Error>
SYSTEM:*TTY* ==> #<Stream for the Terminal>
(describe 'SYSTEM:*STDIN*) ==>
*STDIN* is an external symbol in the SYSTEM package.
It is a special variable; its value is #<Stream for Standard Input>.
#<Stream for Standard Input> is a structure of type FD-STREAM.
...
FD: 0.
...
PATHNAME: NIL.
Special documentation:
The stream connected to the standard input (file descriptor 0).
It is defined in:
target:code/fd-stream.lisp
(describe 'SYSTEM:*STDOUT*) ==>
*STDOUT* is an external symbol in the SYSTEM package.
It is a special variable; its value is #<Stream for Standard Output>.
#<Stream for Standard Output> is a structure of type FD-STREAM.
...
FD: 1.
...
PATHNAME: NIL.
Special documentation:
The stream connected to the standard output (file descriptor 1).
It is defined in:
target:code/fd-stream.lisp
(describe 'SYSTEM:*STDERR*) ==>
*STDERR* is an external symbol in the SYSTEM package.
It is a special variable; its value is #<Stream for Standard Error>.
#<Stream for Standard Error> is a structure of type FD-STREAM.
...
FD: 2.
...
PATHNAME: NIL.
Special documentation:
The stream connected to the standard error output (file descriptor 2).
It is defined in:
target:code/fd-stream.lisp
(describe 'SYSTEM:*TTY*) ==>
*TTY* is an external symbol in the SYSTEM package.
It is a special variable; its value is #<Stream for the Terminal>.
#<Stream for the Terminal> is a structure of type FD-STREAM.
...
FD: 4.
...
PATHNAME: NIL.
Special documentation:
The stream connected to the controlling terminal or NIL if there is none.
It is defined in:
Here the "ground" objects are the values of SYSTEM:*STDIN*,
SYSTEM:*STDOUT*, SYSTEM:*STDERR*, and SYSTEM:*TTY*, and they're
"FD-STREAMS" for the Unix file descriptors (FDs) 0, 1, 2, & 4,
respectively. [The latter is a CMUCL-specific thing, and is a
bi-directional stream opened on "/dev/tty" iff the image was
*not* started in "batch mode".]
+---------------
| And since the big problem seems to be due to my ignorance of lisp
| error handling, does anyone know of a good tutorial to muddle my
| way through it?
+---------------
You might want to read this one:
http://www.nhplace.com/kent/Papers/Condition-Handling-2001.html
+---------------
| Also, why would the following NOT work? (Hangs on exit from less.)
| (defun main2 ()
| (ignore-errors
| (validate-chat-summary-file)
| (quit)))
+---------------
See above. If OpenMCL maps both *ERROR-OUTPUT* & *STANDARD-OUTPUT*
to the process's standard output, that might be your problem.
-Rob
-----
Rob Warnock <rpw3@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607