diary

I like Hatena Star with a text selection.

2024-09-07

必要にかられて druby の実装を読んでいた。

ブロックの処理がうまくいかないような気がしていて、試してみたら案の定うまく動かなかった。

# server.rb
require "drb"

class Front
  def f(&b)
    @b = b
  end

  def g
    @b.call
  end
end

uri = "druby://localhost:55331"

DRb.start_service(uri, Front.new)
DRb.thread.join
# client.rb
require "drb"
DRb.start_service

front = DRbObject.new_with_uri("druby://localhost:55331")

front.f do
  p 42
end

GC.start
GC.start
GC.start

front.g

front.gを呼ぶときには、front.fに渡したブロックはGCに回収されてしまっている。

これを回避するにはProcに対するDRbObjectが死ぬまでProcGC に回収されないようにしなければいけないのだけれど、大変そう。というか、これをどうしているかを知りたくて druby のコードを読んでいたのだけど、対応していないので自分で方法を考えなければならない……。druby でやるなら、Procはクライアント側でHashにでも詰めておいて、サーバー側のProcに対するDRbObjectが回収されるときにfinalizerでクライアント側でも回収させるとかかな。だるそう

とここまで書いて、Procじゃなくて普通のオブジェクトでも同じことが起こるのではと思って試したのだけど、こっちは動く。なんでだろう。

# server.rb
require "drb"

class Front
  def f(x)
    @x = x
  end

  def g
    @x.hello
  end
end

uri = "druby://localhost:55331"

DRb.start_service(uri, Front.new)
DRb.thread.join
# client.rb
require "drb"
DRb.start_service

front = DRbObject.new_with_uri("druby://localhost:55331")

class C
  include DRb::DRbUndumped
  def hello
    puts 'hello'
  end
end

front.f(C.new)

GC.start
GC.start
GC.start

front.g