I'm trying to understand the behavioral difference that I'm seeing between the sbcl and clisp backends for slime on Windows. First some background. I have Lisp code that enters a loop to process Windows messages. There is a get-message function that blocks until the next message is available, retrieves each such message, and then once that message has been processed, the loop returns to get-message. Eventually, the application exits the message loop and control ultimately returns to the repl.
I understand that in single-threaded Lisps like clisp and sbcl/win32, this means that the slime repl will freeze until my message loop exits, though commands that I type ahead will be queued (and that's another nice feature of slime).
Now, when I run clisp via slime, this configuration works fine. Messages get processed just fine while in the loop, and slime works just fine between runs of my code (i.e., outside of the message loop).
When I run sbcl via slime, not only does the slime repl freeze (which I accept as expected behavior), but the blocking call to get-message never returns either. I can use C-c C-c to interrupt sbcl, though.
With some experimental hackery, which I have not yet boiled down to a workable solution, I can actually get a functional message loop running in the slime/sbcl case. This involves bastardizing my code's setup for the loop one time, let that execute and so it immediately returns control to slime, and then restore the correct code. So there seems to be a possibility of achieving the same behavior as I'm getting with clisp.
I see that there is a configuration parameter called swank::*communication-style* that I can set in my local .swank.lisp. The swank-sbcl.lisp backend code appears to force the comm style to nil and there is a comment in the preferred-communication-style function about needing to revisit that once sbcl/win32 gets better select() support.
I did verify that the comm style is nil when running clisp as well.
Does anyone have any thoughts as to what the difference might be between the clisp and sbcl backends in this regard, or possible workarounds to investigate?
Thanks in advance.
* Jack Unrue [2006-11-05 21:27+0100] writes:
Does anyone have any thoughts as to what the difference might be between the clisp and sbcl backends in this regard, or possible workarounds to investigate?
The only backend specific functions used with communication-style nil, should be CREATE-SOCKET and ACCEPT-CONNECTION. But it sounds unlikely that those have much influence on your code.
Does your get-message function return in SBCL if you call it from a bare SBCL REPL (without loading Swank)?
Helmut.
On 11/6/06, Helmut Eller heller@common-lisp.net wrote:
Does your get-message function return in SBCL if you call it from a bare SBCL REPL (without loading Swank)?
Yes, it does.
"Jack Unrue" jdunrue@gmail.com writes:
When I run sbcl via slime, not only does the slime repl freeze (which I accept as expected behavior), but the blocking call to get-message never returns either. I can use C-c C-c to interrupt sbcl, though.
The first order of business is to see if the happens without Slime. If yes, we should probably take this to sbcl-devel...
Even if Slime is a required component, this does sound like an SBCL issue, though.
With some experimental hackery, which I have not yet boiled down to a workable solution, I can actually get a functional message loop running in the slime/sbcl case. This involves bastardizing my code's setup for the loop one time, let that execute and so it immediately returns control to slime, and then restore the correct code. So there seems to be a possibility of achieving the same behavior as I'm getting with clisp.
I'm not sure I understand. On one hand you say that your loop hangs in GetMessage, which never returns, on the other you say that sometimes it doesn't hang?
Can you send a test-case & example? (Depending on eg. GRAPHIC-FORMS is OK, though a self-contained test-case would be nicer.)
A couple of not-directly applicable, but still related, things:
* On Windows SBCL currently converts between FDs and HANDLEs in a way that is liable to cause trouble sooner or later. I would not be overly surprised if you troubles are mysteriously related to this. I have an slightly mutant (and right now defunct) tree that uses HANDLEs only, but there is still more work to be done there before it is good to go.
* In the long run SBCL will likely provide a wrapper on MsgWaitForMultipleObjects, so you can structure your loop something like
(loop (process-message (sb-windows:get-message :serve-events t)))
where SB-WINDOWS:GET-MESSAGE also deals with IO events from eg. Slime, dispatching them to the appropriate handlers. Since things like GRAPHIC-FORMS are probably among the primary users of such interfaces, your input on this would be good to have.
Cheers,
-- Nikodemus Schemer: "Buddha is small, clean, and serious." Lispnik: "Buddha is big, has hairy armpits, and laughs."
On 11/6/06, Nikodemus Siivola nikodemus@random-state.net wrote:
"Jack Unrue" jdunrue@gmail.com writes:
When I run sbcl via slime, not only does the slime repl freeze (which I accept as expected behavior), but the blocking call to get-message never returns either. I can use C-c C-c to interrupt sbcl, though.
The first order of business is to see if the happens without Slime. If yes, we should probably take this to sbcl-devel...
Even if Slime is a required component, this does sound like an SBCL issue, though.
The message loop works fine from a bare REPL in SBCL.
With some experimental hackery, which I have not yet boiled down to a workable solution, I can actually get a functional message loop running in the slime/sbcl case. This involves bastardizing my code's setup for the loop one time, let that execute and so it immediately returns control to slime, and then restore the correct code. So there seems to be a possibility of achieving the same behavior as I'm getting with clisp.
I'm not sure I understand. On one hand you say that your loop hangs in GetMessage, which never returns, on the other you say that sometimes it doesn't hang?
It does seem confusing, but that's indeed what I'm saying. Unfortunately, the case where GetMessage returns is when I've hacked my code to the extent that it's not actually entering the normal message loop -- and I don't yet understand why, after subsequently restoring the calls to GetMessage, that my message loop works. I can only speculate that some kind of internal state in either swank or SBCL has been modified by the initial "hacked up" run.
Can you send a test-case & example? (Depending on eg. GRAPHIC-FORMS is OK, though a self-contained test-case would be nicer.)
I will work on a test case that just uses SBCL's FFI and make that available.
A couple of not-directly applicable, but still related, things:
On Windows SBCL currently converts between FDs and HANDLEs in a way that is liable to cause trouble sooner or later. I would not be overly surprised if you troubles are mysteriously related to this. I have an slightly mutant (and right now defunct) tree that uses HANDLEs only, but there is still more work to be done there before it is good to go.
In the long run SBCL will likely provide a wrapper on MsgWaitForMultipleObjects, so you can structure your loop something like
(loop (process-message (sb-windows:get-message :serve-events t)))
where SB-WINDOWS:GET-MESSAGE also deals with IO events from eg. Slime, dispatching them to the appropriate handlers. Since things like GRAPHIC-FORMS are probably among the primary users of such interfaces, your input on this would be good to have.
I'd be happy to help test this.
Thanks for your response, and I'll provide a standalone test case shortly.
I wrote:
I will work on a test case that just uses SBCL's FFI and make that available.
I should have done this first. My simple test case is able to process timer messages whether started via SLIME or not. The problem has something to do with the standard initialization sequence for creating a window. GetMessage is not getting stuck, there just aren't any further messages related to window initialization generated after the first two. Yet timer events continue to get delivered to the same window callback.
I'm back to square one on this problem, so I'll have to narrow this down better before I bother you folks any further.