When serving large files from Clack/Hunchentoot with Slime connected, I sometimes see error messages like SB-IMPL::SIMPLE-STREAM-PERROR "Couldn't write to ~s"... Those are caused by the browser prematurely dropping connections (which is totally OK). The problem is that each time it happens, SLDB pops up. Which is annoying.
Is there a way I can inhibit certain errors in SLDB such as the above? I still would like to see them in an error log, but definitely not in SLDB.
You can subclass PROCESS-CONNECTION for your acceptor and do your own error handling for this error.
Let's start by defining a custom acceptor:
(defclass no-error-acceptor (hunchentoot:acceptor)
())
Then we can create a wrapper around PROCESS-CONNECTION that inhibits printing of a message for this specific error:
(defmethod hunchentoot:process-connection ((acceptor no-error-acceptor) (socket t))
(handler-case
(call-next-method)
(sb-impl::simple-stream-perror (condition)
;; Perhaps log the error here?
nil)))
Make sure you actually start the server using this acceptor in order for it to be used.
UPDATED
Since your system uses Hunchentoot, you could set the global variable HUNCHENTOOT:*CATCH-ERRORS-P* to T. This should guarantee that the all the conditions arising in code managed by Hunchentoot are catched by Hanchentoot itself and not passed to the debugger.
To disable the debugger in any Common Lisp implementation (both inside a shell REPL as well as the Slime REPL inside Emacs) you could use the predefined global variable *debugger-hook*, by assigning to it a two argument function. The function will receive the condition and the current value of *debugger-hook* when it is called, and can handle the condition or return normally, and in this case the debugger is invoked. For instance, you could simply print the condition:
* (defun my-debug(condition hook)
(declare (ignore hook))
(print condition)
(abort))
DEBUG-IGNORE
* (setf *debugger-hook* #'my-debug)
#<FUNCTION MY-DEBUG>
This second method however cannot work when using Hunchentoot together with Slime, due to the way the two packages interact with respect to the debugging strategies.
In this case one could adopt the solution found by Mike Ivanov, that redefines the swank-debugger-hook function before starting Swank:
(in-package swank)
(setq swank-debugger-hook-orig #'swank-debugger-hook)
(defun swank-debugger-hook (condition hook)
(etypecase condition
(sb-int:simple-stream-error
(progn
(princ "*** Stream error" *error-output*)
(abort)))
(t (funcall swank-debugger-hook-orig condition hook))))
(in-package cl-user)
(swank:create-server :port 4008 :dont-close t)
Related
In my .emacs file, I have:
(defadvice narrow-to-region (around test activate)
(message "advice")
ad-do-it)
When I call narrow-to-region, the advice runs and prints 'advice' before narrowing.
When I call narrow-to-defun, it does not.
I found where narrow-to-defun is defined - in lisp.el, and re-evaluated the function. At this point, the advice started running.
What could cause this?
The problem is, apparently, due to byte-compilation and therefore the inability to advise the narrowing primitives (narrow-to-region is the primitive, narrow-to-defun calls narrow-to-region).
The following post on Null Program ("The Limits of Emacs Advice") goes into detail about this problem. Here's the shortish version from deep in the post:
It turns out narrow-to-region is so special -- probably because it's used very frequently -- that it gets its own bytecode. The primitive function call is being compiled away into a single instruction. This means my advice will not be considered in byte-compiled code. Darnit. The same is true for widen (code 126).
As to why the advice started working after you re-evaluated narrow-to-defun: I'm guessing it's because you ended up replacing the byte-compiled version when you re-evaluated.
#Dan described the problem well. Here is some info that might help you work around it.
What you can do is to advise (or to redefine) also narrow-to-defun (and perhaps narrow-to-page), so it acts similarly.
FWIW, I do something similar in library wide-n.el (see Multiple Narrowings).
I advise narrow-to-region. But I also redefine narrow-to-defun and narrow-to-page. In all 3 cases I make the same change, to record the details of each narrowing so you can return to them later. Here is the advice, for example:
(defadvice narrow-to-region (before push-wide-n-restrictions activate)
"Push the region limits to `wide-n-restrictions'.
You can use `C-x n x...' to widen to previous buffer restrictions."
(when (or (interactive-p) wide-n-push-anyway-p)
(wide-n-push (ad-get-arg 0) (ad-get-arg 1)))) ; Args START and END.
And here is the relevant part of the narrow-to-defun redefinition:
...
(goto-char end)
(re-search-backward "^\n" (- (point) 1) t)
(when (or (interactive-p) wide-n-push-anyway-p) (wide-n-push beg end)) ; <=====
(narrow-to-region beg end))))
I would like emacs to process some time-consuming tasks, without blocking input. For this purpose, I tried (where the insert is meant to be replaced by the time-consuming task)
(call-process "emacs" nil 0 nil "--eval=(insert \"a\")")
This works. However, when I want to pass a frame parameter, it doesn't work:
(call-process "emacs" nil 0 nil "--geometry 30x5")
Emacs says "Unknown option `--geometry 30x5".
Any ideas to use call-process to start another emacs session with refined frame size? Thanks!
It sounds like you might want async.el, which does indeed run additional instances of Emacs to carry out the specified processing.
(although I'm unsure of your requirement for a visible frame.)
Follow the link for details of all the other functionality on offer, but the simplest usage example given (which seemed like it might be applicable) is:
(async-start
;; What to do in the child process
(lambda ()
(message "This is a test")
(sleep-for 3)
222)
;; What to do when it finishes
(lambda (result)
(message "Async process done, result should be 222: %s" result)))
When using call-process, each argument to the program being started must be in a separate string - spaces don't count as separators. Your first example works, because it's a single argument, but the second example requires two parameters and should be written like this:
(call-process "emacs" nil 0 nil "--geometry" "30x5")
I have emacs + sbcl + slime installed. I have this function defined
(defun jugar ()
(let* ((nodoActual *nodo-inicial*)
(estadoActual (nodo-estado nodoActual))
(timeStart nil)
(timeEnd nil)
)
(loop while (not (es-estado-final estadoActual)) do
(setf *hojas* 0)
(setf timeStart (get-universal-time))
(setf nodoActual (decision-minimax nodoActual *profundidad* timeStart))
(setf timeEnd (get-universal-time))
(setf estadoActual (nodo-estado nodoActual))
(imprime-en-fichero estadoActual)
(format t "Hojas analizadas: ~a ~%" *hojas*)
(format t "Tiempo empleado: ~a ~%~%" time))
))
that makes a series of calls and print some variables in a loop.
The problem is when I call (jugar) from the *slime-repl sbcl* buffer, the prompt waits until (jugar) execution ends for showing all the (format …) together. I tried the same from a terminal (running sbcl) and it works well, so I guess it is something related to emacs or slime. How can I fix it?
proksid's answer mentions force-output, which is on the right track, but there are actually a few related possibilities. The documentation for force-output also describes finish-output (and clear-output, which isn't relevant for us):
finish-output, force-output, and clear-output exercise control over
the internal handling of buffered stream output.
finish-output attempts to ensure that any buffered output sent to
output-stream has reached its destination, and then returns.
force-output initiates the emptying of any internal buffers but does
not wait for completion or acknowledgment to return.
clear-output attempts to abort any outstanding output operation in
progress in order to allow as little output as possible to continue to
the destination.
If you want to guarantee that the output from the different iterations doesn't get interleaved (I don't know whether this is likely or not), you might want to consider finish-output instead of force-output. In either case, at least be aware of both options.
Add (force-output) after last (format ) call.
I'm trying to augment the etags-select functions so it will fall-back to a normal find-tag if find-tag at point failed. The code I've tried is:
(defun my-etags-find-tag ()
"Find at point or fall back"
(interactive)
(unless (etags-select-find-tag-at-point)
(etags-select-find-tag)))
(global-set-key (kbd "C-f") 'my-etags-find-tag)
However this fails when point is not at a valid tag. Instead I get a error thrown by etags-select-find-tag-at-point:
etags-select-find-tag-at-point: Wrong type argument: char-or-string-p, nil
In this case I just have to repeat the test done by etags-select-find-tag-at-point:
(defun my-etags-find-tag ()
"Find at point or fall back"
(interactive)
(if (find-tag-default)
(etags-select-find-tag-at-point)
(etags-select-find-tag)))
But it does seem a little redundant. Is it possible to trap exceptions and do alternate processing in elisp?
Try ignore-errors; eg,
(unless (ignore-errors (etags-select-find-tag-at-point))
(etags-select-find-tag))
Normally, (ignore-errors body) returns whatever body returns; when there's error, it returns nil.
Also look at condition-case for more general condition handling.
If you have Elisp info manual installed, you can get more details from
C-hSignore-errors.
Edit:
I failed to consider the possibility that the function may return nil on success; so we probably need
(unless (ignore-errors (or (etags-select-find-tag-at-point) t))
(etags-select-find-tag))
Without modifying the original source code of etags-select.el, I see it the more reasonable option, even when it calls twice to find-tag-default. You can cheat the dynamic environment within the call to avoid the repetition of the call by memoizing it with something like:
(defun my-etags-find-tag ()
"Find at point or fall back"
(interactive)
(let ((ftd (find-tag-default)))
(flet ((find-tag-default () ftd))
(if (find-tag-default)
(etags-select-find-tag-at-point)
(etags-select-find-tag)))))
EDIT: OK, as per your request, an explanation of the code. First, note that this code achieves both questions:
It does not fail
It is more efficient than the code you show (the one you say it is redundant).
Why is it more efficient? The problem with your redundant code is that you call find-tag-default to see if it is nil, and, if it is, you call etags-select-find-tag-at-point. This function calls again to find-tag-default to obtain a default value. What my code does is to cache the value of find-tag-default by redefining the function by being just the value you calculated. The flet does that, so when etags-select-find-tag-at-point calls find-tag-default, the calculated value is returned without any further processing.
I've done a bit of research on this subject and am turning up blanks. There seem to be implementation-dependent ways of doing Unix signal handling in Common Lisp, but is there a package that gives a cross-implementation way of doing signal handling?
I would mainly like to listen for SIGINT and do a graceful shutdown in my app. I'm using Clozure CL 1.7 on linux...like mentioned, it would be great for a package for this, but if I have to resort to implementation-specific code, that's fine.
I'm also not completely married to using SIGINT (although it's ideal). I can use another signal if needed.
If this is going to be messy, does anyone have any other suggestions for gracefully shutting down a lisp app from outside the app? One idea I had is to create a file the app monitors for, and if it detects the file, it shuts down...kind of hacky, though.
Thanks!
Although out of ignorance I was originally skeptical of Daimrod's comment (first comment under the question) about using CFFI, I looked around a bit more and found http://clozure.com/pipermail/openmcl-devel/2010-July/011675.html. I adapted it to use CFFI and have confirmed this works on SBCL/CCL/clisp (probably others) on linux pretty damn well:
(defmacro set-signal-handler (signo &body body)
(let ((handler (gensym "HANDLER")))
`(progn
(cffi:defcallback ,handler :void ((signo :int))
(declare (ignore signo))
,#body)
(cffi:foreign-funcall "signal" :int ,signo :pointer (cffi:callback ,handler)))))
(set-signal-handler 2
(format t "Quitting lol!!!11~%")
;; fictional function that lets the app know to quit cleanly (don't quit from callback)
(signal-app-to-quit))
Note that from what I understand, whatever is in the body of the callback must be short and sweet! No lengthy processing. In the linked article, the macro actually creates a separate thread just for handling the signal, which is overkill for my purposes, since I'm just setting a global variable from nil to t and returning.
Anyway, hopefully this is helpful to others!
I can't find a general library for signal handling either. However, Slime implements "create a custom SIGINT handler" for most Lisp implementations. By looking at the CCL case of that code, I found ccl:*break-hook*. ccl:*break-hook* is not in the documentation, but the commit it was introduced in is located here.
This trivial example code works on my system (CCL 1.8, linux x86):
(setf ccl:*break-hook*
(lambda (cond hook)
(declare (ignore cond hook))
(format t "Cleaning up ...")
(ccl:quit)))
After this code is entered into a non-Slime REPL, sending SIGINT will cause the program to print "Cleaning up ..." and exit.
This is a late answer, but for anybody else searching for this, have a look at trivial-signal, available on Quicklisp. This is based on CFFI.
Example
(signal-handler-bind ((:int (lambda (signo)
(declare (ignorable signo))
...handler...)))
...body...)
If you use SBCL, you cannot change the signal mask without causing SBCL to crash. Ask nyef about his tips on how to fix SBCL...
So there is trivial-signal as mentioned. Here's how I catch a C-c in my code:
(handler-case
(my-app-main-function)
;; AFAIK trivial-signal is supposed to handle the implementation differences.
(#+sbcl sb-sys:interactive-interrupt
#+ccl ccl:interrupt-signal-condition
#+clisp system::simple-interrupt-condition
#+ecl ext:interactive-interrupt
#+allegro excl:interrupt-signal
() (progn
(format *error-output* "Aborting.~&")
(exit)))
(error (c) (format t "Woops, an unknown error occured:~&~a~&" c)))