gun icon indicating copy to clipboard operation
gun copied to clipboard

:gun_http.ws_send/6 is undefined or private

Open cultofmetatron opened this issue 2 years ago • 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?

cultofmetatron avatar Jun 27 '22 17:06 cultofmetatron

There's no ping in HTTP so that might be why this happens. How do you send pings?

essen avatar Jun 27 '22 19:06 essen

@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

cultofmetatron avatar Jun 27 '22 19:06 cultofmetatron

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.

essen avatar Jun 27 '22 20:06 essen

hmm ok so what it uses depends conditionally on if the websocket handshake is established?

cultofmetatron avatar Jun 27 '22 20:06 cultofmetatron

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!

cultofmetatron avatar Jun 27 '22 21:06 cultofmetatron

Cheers. If that's it please leave the ticket open and I'll make sure Gun avoids this crash.

essen avatar Jun 27 '22 21:06 essen

unfortunately I am still seeing it after the guard clause was added.

cultofmetatron avatar Jul 02 '22 19:07 cultofmetatron

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.

vshev4enko avatar Feb 23 '23 11:02 vshev4enko

Good point. Should handle that better.

essen avatar Feb 23 '23 11:02 essen