Erlang Skip Graph デバッグ中

Skip Graph へ (key value) を並列 insert をしたときに gen_server がデッドロックする問題に悩まされる。


insert は handle_call 経由で insert_op_call が担当する。insert 自体は自分自身のデータを変更(左右のノードの更新とか)が発生する。つまり State の更新があるので handle_call で spawn せずに処理を行っていた。
この場合 gen_server が動いている 2 つのプロセス同士がお互いに gen_server:call で get_op, buddy_op を発行するとブロックしてしまい、お互い insert が終わらなくなってしまう。


タイムアウト&リトライでもこの問題は解決しない。

  • get_op, buddy_op などにタイムアウトを設定すると、結局 insert 自体は return しないので gen_server loop がブロックしたまま
  • insert_op をタイムアウト設定すると、壊れた状態で失敗してしまう可能性がある


結局 insert_op が長い間 gen_server loop をブロックするのが問題。そこで insert_op も spawn で処理する。State 更新は spawn したプロセスから元のプロセスへの gen_server:call で更新する。
という方法を試してみよう。
注意すべき点は、State 更新が一貫性を保てるように、意味のあるまとまった単位で更新する事かな。

追記

デッドロック解決した。