rabbibotton / clog

CLOG - The Common Lisp Omnificent GUI
Other
1.52k stars 106 forks source link

0 fell through ETYPECASE expression. Wanted one of (LIST FUNCTION). #368

Closed MCSH closed 3 months ago

MCSH commented 3 months ago

Hi all!

One of my users leaves the tabs open and eventually the tab gets eaten by their browser's memory saver. When the tab wakes up, it tries to connect to the same clog URL and causes the following error. What would be the best way to patch this up?

0 fell through ETYPECASE expression.
Wanted one of (LIST FUNCTION).
   [Condition of type SB-KERNEL:CASE-FAILURE]

Restarts:
 0: [ABORT] abort thread (#<THREAD "hunchentoot-worker-127.0.0.1:52694" RUNNING {1006CB37A3}>)

Backtrace:
  0: (CLACK.HANDLER.HUNCHENTOOT::HANDLE-RESPONSE 0)
      Locals:
        RES = 0
  1: ((:METHOD HUNCHENTOOT:ACCEPTOR-DISPATCH-REQUEST (CLACK.HANDLER.HUNCHENTOOT::CLACK-ACCEPTOR T)) #<CLACK.HANDLER.HUNCHENTOOT::CLACK-ACCEPTOR (host 0.0.0.0, port 8080)> #<HUNCHENTOOT:REQUEST {1006CBB9D3}..
      Locals:
        CLACK.HANDLER.HUNCHENTOOT::ACCEPTOR = #<CLACK.HANDLER.HUNCHENTOOT::CLACK-ACCEPTOR (host 0.0.0.0, port 8080)>
        CLACK.HANDLER.HUNCHENTOOT::REQ = #<HUNCHENTOOT:REQUEST {1006CBB9D3}>
  2: ((:METHOD HUNCHENTOOT:HANDLE-REQUEST (HUNCHENTOOT:ACCEPTOR HUNCHENTOOT:REQUEST)) #<CLACK.HANDLER.HUNCHENTOOT::CLACK-ACCEPTOR (host 0.0.0.0, port 8080)> #<HUNCHENTOOT:REQUEST {1006CBB9D3}>) [fast-metho..
      Locals:
        SB-C::.ANONYMOUS. = #<CLACK.HANDLER.HUNCHENTOOT::CLACK-ACCEPTOR (host 0.0.0.0, port 8080)>
        SB-C::.ANONYMOUS.#1 = #<HUNCHENTOOT:REQUEST {1006CBB9D3}>
  3: ((:METHOD HUNCHENTOOT:PROCESS-REQUEST (T)) #<HUNCHENTOOT:REQUEST {1006CBB9D3}>) [fast-method]
      Locals:
        SB-C::.ANONYMOUS. = #<HUNCHENTOOT:REQUEST {1006CBB9D3}>
      Catch-tags:
        HUNCHENTOOT::HANDLER-DONE
        HUNCHENTOOT::REQUEST-PROCESSED
  4: (HUNCHENTOOT::DO-WITH-ACCEPTOR-REQUEST-COUNT-INCREMENTED #<CLACK.HANDLER.HUNCHENTOOT::CLACK-ACCEPTOR (host 0.0.0.0, port 8080)> #<FUNCTION (LAMBDA NIL :IN HUNCHENTOOT:PROCESS-CONNECTION) {1006CBB93B}>..
      Locals:
        SB-C::.ANONYMOUS. = #<CLACK.HANDLER.HUNCHENTOOT::CLACK-ACCEPTOR (host 0.0.0.0, port 8080)>
        FUNCTION = #<FUNCTION (LAMBDA () :IN HUNCHENTOOT:PROCESS-CONNECTION) {1006CBB93B}>
  5: ((:METHOD HUNCHENTOOT:PROCESS-CONNECTION (HUNCHENTOOT:ACCEPTOR T)) #<CLACK.HANDLER.HUNCHENTOOT::CLACK-ACCEPTOR (host 0.0.0.0, port 8080)> #<USOCKET:STREAM-USOCKET {1006CB3153}>) [fast-method]
  6: ((:METHOD HUNCHENTOOT:PROCESS-CONNECTION :AROUND (HUNCHENTOOT:ACCEPTOR T)) #<CLACK.HANDLER.HUNCHENTOOT::CLACK-ACCEPTOR (host 0.0.0.0, port 8080)> #<USOCKET:STREAM-USOCKET {1006CB3153}>) [fast-method]
  7: ((:METHOD HUNCHENTOOT:PROCESS-CONNECTION :AROUND (CLACK.HANDLER.HUNCHENTOOT::CLACK-ACCEPTOR T)) #<CLACK.HANDLER.HUNCHENTOOT::CLACK-ACCEPTOR (host 0.0.0.0, port 8080)> #<USOCKET:STREAM-USOCKET {1006CB3..
  8: ((:METHOD HUNCHENTOOT::HANDLE-INCOMING-CONNECTION% (HUNCHENTOOT:ONE-THREAD-PER-CONNECTION-TASKMASTER T)) #<HUNCHENTOOT:ONE-THREAD-PER-CONNECTION-TASKMASTER {10023DF423}> #<USOCKET:STREAM-USOCKET {1006..
  9: ((LABELS BORDEAUX-THREADS::%BINDING-DEFAULT-SPECIALS-WRAPPER :IN BORDEAUX-THREADS::BINDING-DEFAULT-SPECIALS))
 10: ((FLET SB-UNIX::BODY :IN SB-THREAD::RUN))
 11: ((FLET "WITHOUT-INTERRUPTS-BODY-10" :IN SB-THREAD::RUN))
 12: ((FLET SB-UNIX::BODY :IN SB-THREAD::RUN))
 13: ((FLET "WITHOUT-INTERRUPTS-BODY-3" :IN SB-THREAD::RUN))
 14: (SB-THREAD::RUN)
 15: ("foreign function: call_into_lisp")
 16: ("foreign function: funcall1")

Inspecting the request, it's fairly obviously a /clog URI with an "r" parameter that has been cleaned up from the server. What can I do to gracefully handle these errors?

rabbibotton commented 3 months ago

Not sure that gives me enough information to work from, I assume you are seeing the /clog uri in some log? This seems to be failing in clack, one layer in from hunchentoot and one layer away from CLOG and 2 from your CL code.

I would love to reproduce this if you could give me enough to do this. The CLOG reconnect code has been very robust and have had pages up for months. (Granted chrome added some sort of power saver mode a few months ago, so if related even more reason want to reproduce)

This is on a local machine or over a network?

excited :)

rabbibotton commented 3 months ago

As an experiment can you add your CLOG URLs to chrome://settings/performance exclusions for memory management and see if would make a difference?

MCSH commented 3 months ago

I see the clog uri if I inspect the values passed to hunchentoot in one of the backtrace frames 1 to 3. Frame zero only have one value passed to (RES=0).

I host an advanced calculator for an online game written in common lisp with connectors to discord and web, and this happens only with one of my clients, and only if they leave the tab running for long periods of time, but it still annoys me to get the error! This is over network.

I can share the entire codebase with you but that would be too much for you to go through, so instead I'll first ask them to add the clog uris to the exclusion list and then try to replicate the behavior with curl and pass that to you for reproducing.

As this is a hobby project I can't say how long that would take me but I'll do my best to be timely. And thanks for the awesome library!

rabbibotton commented 3 months ago

Looking forward to it, real world errors are golden!

MCSH commented 3 months ago

It turned out to be fairly easy to reproduce the error, though I can't explain why this is happening.

Steps to reproduce, starting SBCL with Quicklisp loaded:

> (ql:quickload :clog)
> (clog:run-tutorial 1)

Assuming port 8080, run the the following:

$ curl "http://localhost:8080/clog

This would cause the same exception to happen.

I understand what is happening, but I can't necessarily say why. At some point chrome decides to make an https request instead of a wss one to the /clog uri when the tab wakes up, and I have no idea why as I don't have access to their machine and it doesn't happen to me.

This is the log made in the stdout (which you'd get the same if you reproduce through the method above):

Condition caught in clog-server start-up - No Sec-WebSocket-Version header.

Which I believe originates from clog-connection-websocket.lisp function clog-server, and the reason is that the websocket-driver function expects a websocket but is getting an HTTP request instead.

A fix that comes to mind is to check whether the request is a websocket one through the websocket version header and if it isn't, gracefuly ignore the request. But personally I don't like this because it doesn't solve the actual problem. Would love to hear your thoughts on this!

rabbibotton commented 3 months ago

Sounds to me like but in the browser, ouch. What browser are they running?

MCSH commented 3 months ago

I believe it's chrome

rabbibotton commented 3 months ago

able to reproduce working on fix

rabbibotton commented 3 months ago

ok, error handled gracefully with a 400 status (it is the client failure) and exception caught. Not much we can do to recover from a faulty html request. If see it happen still outside this one client let me know. Change in git.