Subject: Re: Handling errors in standard output statements with openmcl
From: (Rob Warnock)
Date: Tue, 06 Dec 2005 07:10:19 -0600
Newsgroups: comp.lang.lisp
Message-ID: <>
Kirk Job Sluder  <> 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:

	(send-output stream)		; the main work
      (error (condition)
	  ((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.
                 (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 Warnock			<>
627 26th Avenue			<URL:>
San Mateo, CA 94403		(650)572-2607