[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [MIT-Scheme-devel] multi-threading problem: Unassigned variable: roo
From: |
Matt Birkholz |
Subject: |
Re: [MIT-Scheme-devel] multi-threading problem: Unassigned variable: root-continuation-default |
Date: |
Fri, 27 Apr 2012 18:40:16 -0700 |
> From: "Micah Brodsky" <address@hidden>
> Date: Thu, 26 Apr 2012 22:36:21 -0400
>
> [...] entirely irrelevant to MIT Scheme, except inasmuch as the same
> problems reappear and are much more of a pain to deal with without
> them. I.e., as far as I can tell, everyone who wants to abort a
> blocking call like a socket read has to roll their own abstraction
> to handle safe cross-thread signaling.
Hey, we are already in the weeds. Let's not joke about rolling our
own... :-)
... and let's get concrete with the existing thread-event mechanism.
To throw an error/abort in a thread blocked in channel-read
(e.g. read-line), you should be able to do this:
(signal-thread-event thread (lambda () (error "Abort!")))
Thread would be the blocked reader, perhaps
(thread-mutex-owner (port/thread-mutex socket))
Here's our example again, spiffed up with some messages, minus the
curious nested create-thread.
(let ((socket (open-tcp-server-socket 54321)))
(create-thread
#f (lambda ()
(let ((port (tcp-server-connection-accept socket #t #f)))
(display ";Connection accepted.\n")
(for-each display
(list ";Read: "
(ignore-errors (lambda () (read-line port)))
"\n"))
(display "ok\n" port)
(close-port port)
(display ";Connection disconnected.\n")))))
Entering that into the console REPL, I get the REPL prompt back and I
can connect via `nc localhost 54321'. When I connect ";Connection
accepted." appears on my console:
;Value 11: #[thread 11]
1 ]=> ;Connection accepted.
I then enter at the REPL the charm already mentioned:
(signal-thread-event address@hidden (lambda () (error "Abort!")))
and I see this:
;Unspecified return value
1 ]=> ;Read: #[condition 12 simple-error]
;Connection disconnected.
(pp address@hidden)
#[thread 11]
(execution-state dead)
...
My nc command emits "ok" and exits without error. If I had kept
#[thread 11] out of the REPL's hash table, it would be garbage
collected too.
When I punt the ignore-errors wrapper I see this:
;Unspecified return value
1 ]=>
;The thread #[thread 11] signalled an error:
Abort!
;To continue, call RESTART with an option number:
; (RESTART 1) => Return to read-eval-print level 1.
2 error>
The situation is quite sane. Here is the output of the debugger's
history command:
SL# Procedure-name Expression
0 (begin (event) (set-interrupt-enables! int ...
1 (begin (if event (let ((block? (%record-re ...
2 (let ((any-events? (handle-thread-events t ...
3 (begin (%suspend-current-thread) result)
4 (let ((value (let ((result (quote interrup ...
5 (let ((result (TEST-FOR-IO-ON-CHANNEL chan ...
6 (let ((value (thunk))) (set-interrupt-enab ...
7 (let ((n (do-read 0))) (if n (begin (%reco ...
8 fill-input-buffer (let ((n (read-bytes ib))) (if n (if (grea ...
9 (let ((r (fill-input-buffer ib))) (let ((t ...
10 (let ((char (defer port))) (transcribe-inp ...
11 loop (let ((char (read-char port))) (cond ((eq? ...
12 (list ";Read: " (read-line port) "\n")
13 (for-each display (list ";Read: " (read-li ...
14 (begin (for-each display (list ";Read: " ( ...
15 (exit-current-thread (thunk))
16 loop (loop (bind-abort-restart cmdl (lambda () ...
3 debug>
Actually I upcased test-for-io-on-channel because I think it is cool
that I can see where my #[thread 11] was hanging out when it got the
bad news. That's Bodacious, dude.
> [...] Imagine if you couldn't safely do debug prints from a worker thread!
I can only imagine doing it safely if the debug-print procedure grabs
the port/mutex for the duration of the message output (write-line?)
process. A write-line made up of tiny atomic write-chars is no more
"safe" except for the precious buffer pointers. I would call them a
costly set of suspenders IF they kept the pants from falling down.
Thread-safe and child-proof are marketing terms.
> I have not looked at the spec or code in the case of glibc, but I
> know for certain MS's stdio and iostream protect their buffers with
> locks.
Marketing term. Definitely. Tiny atomic ops won't keep your pants
up!
> MIT Scheme has some particularly bad failure modes when you rub its
> sockets the wrong way from multiple threads, i.e. producing an
> infinite explosion of interrupt-triggered errors that surfaces on
> socket close, well after the offending code has run, and almost
> un-debuggable because all you can interact through is the interrupt
> menu. The only way I figured that one out is by asking Taylor to
> tell me what I did wrong. :P
Fascinating (as my hero would say, without a trace of sarcasm).
What did you do wrong?
- [MIT-Scheme-devel] multi-threading problem: Unassigned variable: root-continuation-default, craven, 2012/04/26
- Re: [MIT-Scheme-devel] multi-threading problem: Unassigned variable: root-continuation-default, Micah Brodsky, 2012/04/26
- Re: [MIT-Scheme-devel] multi-threading problem: Unassigned variable: root-continuation-default, Matt Birkholz, 2012/04/26
- Re: [MIT-Scheme-devel] multi-threading problem: Unassigned variable: root-continuation-default, Micah Brodsky, 2012/04/26
- Re: [MIT-Scheme-devel] multi-threading problem: Unassigned variable: root-continuation-default, Taylor R Campbell, 2012/04/27
- Re: [MIT-Scheme-devel] multi-threading problem: Unassigned variable: root-continuation-default,
Matt Birkholz <=
- Re: [MIT-Scheme-devel] multi-threading problem: Unassigned variable: root-continuation-default, Taylor R Campbell, 2012/04/28
- Re: [MIT-Scheme-devel] multi-threading fun: closing a socket, Matt Birkholz, 2012/04/30
- Re: [MIT-Scheme-devel] multi-threading problem: Unassigned variable: root-continuation-default, Taylor R Campbell, 2012/04/27
Re: [MIT-Scheme-devel] multi-threading problem: Unassigned variable: root-continuation-default, Taylor R Campbell, 2012/04/26
Re: [MIT-Scheme-devel] multi-threading problem: Unassigned variable: root-continuation-default, Taylor R Campbell, 2012/04/26