I found ##thread-interrupt. I saw it before, but I couldn't get it working. I just had to take a closer look at the threading code.
The call seems to do exactly what you suggested, Christian. It executes an `action` thunk which can raise an exception in the context of another thread. I don't mind about the C code problem, I will work on a different, special development environment for C code when I come to it. I don't see any reason why the two should be integrated.
Marc (or anyone else who has used this function), is it safe for me to do this?
(define a 0) (define (interrupt-handler)
(display "got interrupted"))
(define t
(make-thread (lambda () (display "starting...\n") (with-exception-catcher (lambda (exc) (interrupt-handler)) (lambda () (let loop ((i 0)) (set! a i) (loop (+ i 1))))))))
(thread-start! t)
#<thread #2> starting...
(print a "\n")
15298085
(print a "\n")
18750998
(print a "\n")
20815043
(print a "\n")
22613558
(##thread-interrupt! t (lambda () (raise 'int) (##void)))
#<run-queue #3> got interrupted
(print a "\n")
67989053
(print a "\n")
67989053
(print a "\n")
67989053
On Dec 5, 2007 6:37 PM, James Long longster@gmail.com wrote:
Nevermind, that won't work for interrupts. I just thought about it a little more. The repl would never read from the string port if a command goes crazy and starts thrashing. Hm, we do need a real interrupt somehow, but I'm not sure if that's possible without disturbing the primordial thread.
So we do need something akin to your idea, which will only work if Gambit supports some kind of thread interrupting.
On Dec 5, 2007 6:26 PM, James Long longster@gmail.com wrote:
Interesting stuff Christian. The idea of executing something in the context of another thread is a bit competing though, right? A thread itself defines only one path of execution, so unless you mean to somehow stop a thread and replace its continuation with another one, I can't really imagine anything else. And doing that requires you to save the old continuation and make sure you set everything back up right.
It seems more natural to try and send a message to the thread. In this context, it's a repl service, so I figured we could try to communicate over the repl service string port. (NOTE: I am now calling the local process which reads commands and outputs the result a 'repl', and the remote process which evaluates the commands a 'repl service').
To achieve C-d, I replaced the line
(display cmd repl-worker-port)
with
(if (eof-object? cmd) (display "(raise 'eof)" repl-worker-port) (display cmd repl-worker-port))
and then my exception handler becomes
;; Fire up the repl with an explicit repl exception handler (with-exception-handler (lambda (exc) (if (symbol? exc) (cond ((eq? exc 'eof) (cmd-d))) (##repl-exception-handler-hook exc
##thread-end-with-uncaught-exception!))) (lambda () (##repl-debug-main)))))))
It worked pretty well actually, and you would do the same thing with interrupts. Now I just have to figure out how interrupts should actually behave... maybe C-c C-c should interrupt the local repl?
James
On Dec 5, 2007 9:08 AM, Christian Jaeger christian@pflanze.mine.nu wrote:
Christian Jaeger wrote:
I hope that by calling ##continuation-graft-with-winding you could throw an exception in the context of that thread (not sure, though)).
Ok, it didn't let me rest and I tested it out. Seems my hope is void: you can call a continuation from a foreign thread, but it is then not executed in the original thread, but in the current thread instead (the original thread continues normal execution). That makes sense, of course, since that allows one to transfer 'agents' to other threads (just what Termite is doing).
So you have to find out how to evaluate code in the context of another thread (I'd examine the code implementing the default signal handler), or let Marc tell you.
Christian.
-- James Long Coptix, Inc. longster@gmail.com
-- James Long Coptix, Inc. longster@gmail.com