gen_tcp:controlling_process/2

Erlangを触る時間がなかなかとれずに心身に深刻なダメージが蓄積してきたので、久しぶりにいじることにしました。今まで何度書いてきたか分かりませんがポートフォワーディングを書いています。

双方向からのデータを相手に転送することを考えると、{active, true}にしておいて受信データはメッセージで貰ったほうが都合がよいため、別プロセスを立ち上げて gen_tcp:controlling_process/2 してみたのですがどうも期待通りに動きません。こんな感じのコードでした:

accept_loop(LSock) ->
  {ok, Sock} = gen_tcp:accept(LSock),
  spawn(fun() ->
    gen_tcp:controlling_process(Sock, self()),
    accepted(Sock)
  end),
  accepted_loop(LSock).

accepted(Sock) ->
  receive
    {tcp, Sock, Bin} ->
      以下略

いろいろ試してみたところ、accept_loopの方のプロセスにメッセージが飛んできているようで、 controlling_process が効いていないようでした。戻り値チェックしていないことにようやく気付いて調べてみたところ、 {error, not_owner} なる結果が。そうだったのか… と今更知りました。現在制御プロセスであるプロセスから他のプロセスに制御を渡すことしかできないのですね…

初めて使ったわけでもないのになんで今更そんなことに気付くのだろうと不思議に思ってソースを追ってみたところ、どうやら R13B03 でチェックが追加されたようです。しかしそれも4年半前のことですので、今までどうやって気付かずに生きてきたんだろうと思いました…。