:gun_http.ws_send/6 is undefined or private
cultofmetatron opened this issue · 9 comments
version: 2.0
I'm getting a crash in our gun cluster system. seems to happen only when we send a ping
** (UndefinedFunctionError) function :gun_http.ws_send/6 is undefined or private
(gun 2.0.0-rc.2) :gun_http.ws_send({:ping, "ping"}, {:http_state, {:sslsocket, {:gen_tcp, #Port<0.843240>, :tls_connection, :undefined}, [#PID<0.18172.744>, #PID<0.2620.744>]}, :gun_tls, %{}, :"HTTP/1.1", :keepalive, "", :undefined, [{:stream, {:websocket, #Reference<0.3877686489.3231711234.17167>, #PID<0.30539.291>, "GkoTOlbK5BKnn6USQSTgwQ==", [], %{silence_pings: false}}, #PID<0.30539.291>, :infinity, "GET", 'Sp422452vloc2.connect.paymentsense.cloud', "/pat?token=0784af15-8445-45e8-82b8-1b6cc0c16c2e&api-version=v1&software-house-id=SP769R44&installer-id=SP769R44", true, :undefined}], :head, {0, 0}, :head}, #Reference<0.3877686489.3231711234.17167>, #PID<0.30539.291>, :gun_default_event_h, :undefined)
(gun 2.0.0-rc.2) /app/deps/gun/src/gun.erl:1307: :gun.connected/3
(stdlib 3.12.1.2) gen_statem.erl:1118: :gen_statem.loop_state_callback/11
(stdlib 3.12.1.2) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
at no point in my own code am I calling a 6 arrity version of ws_send so I'm at a loss. I can only conclude something is causing it to call some old code that calls a function that does't exist in this case?
There's no ping in HTTP so that might be why this happens. How do you send pings?
@essen thsi is the code I have that does it. the traceback is non exsitant but this is the only place I send {:ping, "ping"} so I assume this is where it slips into the library
def handle_cast({:send_message, "ping"}, %{name: name, stream_ref: stream_ref, gun_pid: gun_pid} = state) do
case :gun.ws_send(gun_pid, stream_ref, {:ping, "ping"}) do
:ok ->
{:noreply, state}
reply ->
{:noreply, state}
end
end
and this is occurring over a websocket
The 6-arity is an internal call that results from yours. What might be a bug is if you try to send a Websocket ping when the connection is using HTTP, it tries to call a function that does not exist instead of rejecting the call.
hmm ok so what it uses depends conditionally on if the websocket handshake is established?
ok so I added a guard clause that prevents the ws_send from sending the ping unless the status of the websocket is successfully upgraded. will let you know if it works.
Thankyou for the insight!
Cheers. If that's it please leave the ticket open and I'll make sure Gun avoids this crash.
unfortunately I am still seeing it after the guard clause was added.
I got the same crashes. It happens when gen_statem
in e.g connected
state receives {ws_send, frames()}
but the protocol is gun_http
which doesn't have a ws_send
function. Depending conditionally on ws handshake doesn't solve the issue due to the async nature there is no guarantee gun will not reconnect having {ws_send, frames()}
in the mailbox. It is easily reproducible just by calling gun:ws_send/3
and reconnecting.
Good point. Should handle that better.