Skip to content

Instantly share code, notes, and snippets.

@HidetakaKojo
Last active February 15, 2017 14:25
Show Gist options
  • Save HidetakaKojo/c4bb4b5ce059f1d07f17ee8e770d3aa0 to your computer and use it in GitHub Desktop.
Save HidetakaKojo/c4bb4b5ce059f1d07f17ee8e770d3aa0 to your computer and use it in GitHub Desktop.
Phoenix.Transports.WebSocekt.ws_closeが実行されると
Channel.Serverのそれぞれのpidに対してPhoenix.Channel.Server.close(pid)が呼ばれる
closeはcastでChannelプロセスの後片付けをしていて、
Phoenix.Channel.Server.handle_cast(:close, socket)が実行されて、
{:shutdown, :close}イベントが渡されるhandle_castの返り値に{:stop, {:shutdown, :close}, socket}が戻るので
Phoenix.Channel.Server.terminate({:shutdown, :close}, socket)が呼ばれてChannelが整理される
じゃあPhoenix.Transports.WebSocket.ws_closeは誰が叩いてるんだって話だと、
Phoenix.Endpoint.CowboyWebSocketで、cowboy_websocketのhandler経由.
cowboyのcowboy_websocket.erlの中を見るとhandle_loop_timeoutでtimeoutのtimerを設定していて
handler_loopでtimeoutイベントをreceiveするとwebsocket_terminateに{normal, timeout}を渡す
websocket_timeoutは{:error, :closed}, {:remote, :closed}, {:remote, code, _}なものを受け取ると
Phoenix.Endpoint.CowboyWebSocketのws_closeが呼ばれるのだが、
{normal, timeout}だと、Phoenix.Endpoint.CowboyWebSocket.ws_terminateが呼ばれそうな予感がする.... あれ?
cowboy_websocket.erlの中でTransport:send(Socket, << 1:1, 0:3, 8:4, 0:1, 2:7, 1000:16 >>)を送っている。
Transportはranch_tcp(ranch_ssl)だから、ここにwebsocketのRFC6455が規定する1000(正常な終了)をおくることになる。
ただ実際にはすでにconnectionは失われているわけで、handler_loop中で正常終了に対するresponseでエラーが返ってきて死亡ルートにはいるのだろうか...
少し謎が残る....
phx_leave eventを受けると、最終的にはhandle_infoの返り値に{:stop, {:shutdown, :left}, socket}が戻るので、
Phoenix.Channel.Server.terminate({:shutdown, :left}, socket)が呼ばれてChannelが整理される。
こっちは大丈夫そう
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment