Kirk Job Sluder <kirk-nospam@jobsluder.net> wrote:
+---------------
| ... if I pipe the output into less, and then quit less midway
| through the file. The program hangs, then gives me:
|
| Unhandled exception 11 at 0x410be24, context->regs at #xbff9eee8
| Write operation to unmapped address 0x75ff8
...
| I know that what is happening when I quit less, OpenMCL still tries to
| write to an output buffer. My question is (after a modest amount of
| searching) primarily for future reference. How can I make this output
| function "safe" so that if *standard-input* closes, the script exits
| gracefully.
+---------------
I had exactly the same problem when writing a CMUCL-based web
application server, when the browser user hit "Stop" or "Back"
or "Close" before a large request has been completely sent.
Under Unix/Linux, this causes a SIGPIPE signal to be sent to
the CMUCL process, which I tried to catch using CMUCL's signal-
handling code... which is unfortunately not completely reliable.
But Dan Barlow [thanks, Dan!!] pointed out a much simpler way:
Simply set the Lisp process to *ignore* SIGPIPE, and then you'll
get ordinary system call errors (with EPIPE) from any writes after
the pipe [or socket] is closed. In CMUCL, you can do that this way:
;;; 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)
(cond
((eql unix:unix-errno unix:EPIPE)
;; Log it locally if you want to & can, then...
(ignore-errors (close stream :abort t)))
;; <== Maybe insert other error cases here.
(t ; catch-all
;; Log it locally if you want to & can, then...
;; If the stream is still open, try to print the error
;; onto the output stream, too.
(when (open-stream-p stream)
(ignore-errors ; But might EPIPE here, too, so protect.
(progn
(format stream "Internal server error!~%~a~%" condition)
(finish-output stream) ; Either of these might EPIPE,
(close stream)))))))) ; which is why the IGNORE-ERRORS.
As I said, this works fine for CMUCL. You'll need to find out how
to do the same SIGPIPE ignoring in OpenMCL, and also translate the
other UNIX package code above appropriately...
-Rob
-----
Rob Warnock <rpw3@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607