Hi folks,
I'm experiencing some issues with slime HEAD and CCL trunk. There are a couple of `must-haves' for us when using slime with our multi- threaded application that work in SBCL but not in CCL:
SWANK:*GLOBALLY-REDIRECT-IO* does not globally redirect io when set to T in ~/.swank.lisp. Output remains in the *inferior-lisp* buffer.
SWANK:*GLOBAL-DEBUGGER* does not invoke SLDB when cond- itions are raised outside of the REPL thread when set to T in ~/.swank.lisp. I see the following in *inferior-lisp*:
Break: URL: #1="/tests/1" CMD: (:GRID #1# :GRID) While executing: AJAX-RESPONSE, in process hunchentoot-worker-1(11).
;;; ;;; #<PROCESS hunchentoot-worker-1(11) [Active] #x9452A16> requires access to Shared Terminal Input ;;; Type (:y 11) to yield control to this thread. ;;;
Can anyone offer any advice on how to proceed?
Thanks,
- Scott
* sblist@me.com [2009-01-08 07:25+0100] writes:
Can anyone offer any advice on how to proceed?
If those things work in SBCL but not in CCL then it probably means that CCL implements some thread related features differently.
Global IO redirection only works if *standard-output* etc. are truly global variables. If those variables are thread-local we can't set them with a simple setf and would have to use something else, e.g. with a backend specific function setf-global. I don't know how these things work in CCL; you could ask the CCL developers how to do it properly.
For the debugger, we set *debugger-hook* (again if that isn't a global variable it has no effect on other threads). We also have a backend spefic function install-debugger-globally which could use implementation specific tricks, but for CCL it doesn't.
It looks like BREAK invokes the Slime debugger only inside call-with-debugger-hook. See also *break-in-sldb* in swank-openmcl.lisp. Maybe it works better if you set that to T.
In general, you can invoke the Slime debugger by calling swank:invoke-slime-debugger. This might be more robust than relying on *debugger-hook* etc.
Helmut.
Helmut Eller heller@common-lisp.net writes:
- sblist@me.com [2009-01-08 07:25+0100] writes:
Can anyone offer any advice on how to proceed?
If those things work in SBCL but not in CCL then it probably means that CCL implements some thread related features differently.
Global IO redirection only works if *standard-output* etc. are truly global variables. If those variables are thread-local we can't set them with a simple setf and would have to use something else, e.g. with a backend specific function setf-global. I don't know how these things work in CCL; you could ask the CCL developers how to do it properly.
Looking at the source, CCL does indeed make the *STANDARD-FOO* bindings thread-local by default. Changing the current implementation of SPAWN to
(defimplementation spawn (fn &key name) (ccl:process-run-function `(:name ,(or name "Anonymous (Swank)") :use-standard-initial-bindings nil) fn))
will probably solve the issue. I'm not sure how reasonable it would be, though. Perhaps
(defimplementation spawn (fn &key name) (let ((initial-bindings (set-difference (ccl::standard-initial-bindings) '((*standard-input*) (*standard-output*)) :key #'car))) (ccl:process-run-function `(:name ,(or name "Anonymous (Swank)") :use-standard-initial-bindings nil :initial-bindings ,initial-bindings) fn)))
would be more sensible.
-T.
* Tobias C. Rittweiler [2009-01-09 12:53+0100] writes:
Looking at the source, CCL does indeed make the *STANDARD-FOO* bindings thread-local by default. Changing the current implementation of SPAWN to
(defimplementation spawn (fn &key name) (ccl:process-run-function `(:name ,(or name "Anonymous (Swank)") :use-standard-initial-bindings nil) fn))
will probably solve the issue. I'm not sure how reasonable it would be, though.
That would only affect threads created by SWANK. I think the threads created by the webserver are the more interesting problem.
(defimplementation spawn (fn &key name) (let ((initial-bindings (set-difference (ccl::standard-initial-bindings)
We could probably mess around with those ccl::standard-initial-bindings
Helmut.
Helmut Eller heller@common-lisp.net writes:
- Tobias C. Rittweiler [2009-01-09 12:53+0100] writes:
(defimplementation spawn (fn &key name) (ccl:process-run-function `(:name ,(or name "Anonymous (Swank)") :use-standard-initial-bindings nil) fn))
That would only affect threads created by SWANK. I think the threads created by the webserver are the more interesting problem.
The debugger is globally installed, and the io streams are globally redirected from within SWANK threads, aren't they?
-T.
* Tobias C. Rittweiler [2009-01-09 15:52+0100] writes:
Helmut Eller heller@common-lisp.net writes:
- Tobias C. Rittweiler [2009-01-09 12:53+0100] writes:
(defimplementation spawn (fn &key name) (ccl:process-run-function `(:name ,(or name "Anonymous (Swank)") :use-standard-initial-bindings nil) fn))
That would only affect threads created by SWANK. I think the threads created by the webserver are the more interesting problem.
The debugger is globally installed, and the io streams are globally redirected from within SWANK threads, aren't they?
Yes.
Are you implying that threads created with :use-standard-initial-bindings=nil can modify ccl::standard-initial-bindings (and hence the bindings for the threads created by the webserver) simply by setting *standard-output*? That could be.
Helmut.
On 9-Jan-09, at 8:50 AM, Helmut Eller wrote:
The debugger is globally installed, and the io streams are globally redirected from within SWANK threads, aren't they?
Yes.
Are you implying that threads created with :use-standard-initial-bindings=nil can modify ccl::standard-initial-bindings (and hence the bindings for the threads created by the webserver) simply by setting *standard-output*? That could be.
Helmut.
Here is Gary's reply on openmcl-devel on how to set the initial or `static' bindings of such variables rather than the thread-local binding. Perhaps this is enough to obtain the desired behavior?
Gary Byers wrote:
"If I understand the question correctly, the answer is that
(CCL::%SET-SYM-GLOBAL-VALUE sym value)
behaves like CL:SET, only it ignores any thread-local/dynamic bindings of the variable and modifies the global/static binding.
The standard stream variables (*TERMINAL-IO*, etc.) are bound in each thread (well, each thread that's created by the lisp); the initial values of these bindings are the static values of the variables. So, setting the global/static value of *TERMINAL-IO* would affect the value of *TERMINAL-IO* in any subsequently-created threads."
- Scott
* sblist@me.com [2009-01-10 07:45+0100] writes:
Here is Gary's reply on openmcl-devel on how to set the initial or `static' bindings of such variables rather than the thread-local binding. Perhaps this is enough to obtain the desired behavior?
I committed something. I used ccl::def-standard-initial-binding which seems to work.
Helmut.