デッドロック?

R6RS 処理系であるところの Sagittarius を使って簡単な通信をしようと考えてこんな感じのコードを書いた。

#!r6rs
(import (rnrs)
        (rnrs io ports)
        (sagittarius socket)
        (sagittarius threads))

(define sock (make-client-socket "localhost" "7" AF_INET))
(define port (socket-port sock))

(define thread
  (make-thread (lambda()(do()(#f)(display (integer->char (get-u8 port)))))))
(thread-start! thread)
(sys-nanosleep 1000000000) ;;確実にスレッドが起動して読込待機状態になるまで待つ
(put-bytevector port (string->utf8 "Hello\n"))
(sys-nanosleep 1000000000) ;;受信した内容を表示するまで待つ

ローカルのエコーサーバにメッセージを投げ、返答を表示するだけのものだ。

受信側は専用のスレッドを起動しているが、読込待機に入った状態で送信しようとすると送信せずにその場でロックしてしまう。

ソケットから入力ポートと出力ポートを個別に作ることも出来て、それで書くとロックせずに動作する。

#!r6rs
(import (rnrs)
        (rnrs io ports)
        (sagittarius socket)
        (sagittarius threads))

(define sock (make-client-socket "localhost" "7" AF_INET))
(define in (socket-input-port sock))
(define out (socket-output-port sock))

(define thread
  (make-thread (lambda()(do()(#f)(display (integer->char (get-u8 in)))))))
(thread-start! thread)
(sys-nanosleep 1000000000)
(put-bytevector out (string->utf8 "Hello\n"))
(sys-nanosleep 1000000000)

関連する定義は ext/socket/socket.c にあるのでざっと見たのだけれど、最終的には同じ操作しているようにしか見えないのでどうしてこういう差が生じるのかわからないでいる。

Document ID: b1b97a2165ed4ac65e38a24f2a69c7ee