niv / websocket.nim

websockets for nim
http://niv.github.io/websocket.nim/docs/0.1.1/websocket.html
Other
102 stars 25 forks source link

Browser refreshing causes websocket server exception #49

Open gogolxdong opened 5 years ago

gogolxdong commented 5 years ago

websocket-0.3.5 latest version Everytime enters the index.html again causes

[Warning] WS negotiation failed: the only supported sec-websocket-version is 13
pmserver.nim(157)        pmserver
pmserver.nim(141)        serve
asyncdispatch.nim(1656)  waitFor
asyncdispatch.nim(1516)  poll
asyncdispatch.nim(1282)  runOnce
asyncdispatch.nim(191)   processPendingCallbacks
asyncmacro.nim(36)       processRequest_continue
asynchttpserver.nim(275) processRequestIter
asyncnet.nim(628)        close
asyncdispatch.nim(1122)  closeSocket
ioselectors_epoll.nim(180) unregister
system.nim(3877)         failedAssertImpl
system.nim(3870)         raiseAssert
system.nim(2916)         sysFatal
[[reraised from:
pmserver.nim(157)        pmserver
pmserver.nim(141)        serve
asyncdispatch.nim(1656)  waitFor
asyncdispatch.nim(1516)  poll
asyncdispatch.nim(1282)  runOnce
asyncdispatch.nim(191)   processPendingCallbacks
asyncmacro.nim(36)       processClient_continue
asynchttpserver.nim(288) processClientIter
asyncfutures.nim(302)    read
]]
[[reraised from:
pmserver.nim(157)        pmserver
pmserver.nim(141)        serve
asyncdispatch.nim(1656)  waitFor
asyncdispatch.nim(1516)  poll
asyncdispatch.nim(1282)  runOnce
asyncdispatch.nim(191)   processPendingCallbacks
asyncfutures.nim(349)    :anonymous
]]
Error: unhandled exception: /usr/local/Nim/lib/pure/ioselects/ioselectors_epoll.nim(180, 11) `
not (pkey.ident == InvalidIdent)` Descriptor 15 is not registered in the selector!
Async traceback:
  pmserver.nim(157)          pmserver
  pmserver.nim(141)          serve
  asyncdispatch.nim(1656)    waitFor
  asyncdispatch.nim(1516)    poll
    ## Processes asynchronous completion events
  asyncdispatch.nim(1282)    runOnce
  asyncdispatch.nim(191)     processPendingCallbacks
    ## Executes pending callbacks
  asyncmacro.nim(36)         processRequest_continue
    ## Resumes an async procedure
  asynchttpserver.nim(275)   processRequestIter
  asyncnet.nim(628)          close
  asyncdispatch.nim(1122)    closeSocket
  ioselectors_epoll.nim(180) unregister
  system.nim(3877)           failedAssertImpl
  system.nim(3870)           raiseAssert
  system.nim(2916)           sysFatal
  #[
    pmserver.nim(157)          pmserver
    pmserver.nim(141)          serve
    asyncdispatch.nim(1656)    waitFor
    asyncdispatch.nim(1516)    poll
      ## Processes asynchronous completion events
    asyncdispatch.nim(1282)    runOnce
    asyncdispatch.nim(191)     processPendingCallbacks
      ## Executes pending callbacks
    asyncmacro.nim(36)         processClient_continue
      ## Resumes an async procedure
    asynchttpserver.nim(288)   processClientIter
    asyncfutures.nim(302)      read
  ]#
Exception message: /usr/local/Nim/lib/pure/ioselects/ioselectors_epoll.nim(180, 11) `
not (pkey.ident == InvalidIdent)` Descriptor 15 is not registered in the selector!
Exception type: [AssertionError]

as a websocket opened on page loading and closed on leaving. our websocket server code is as follows: http://ix.io/1yUB

dom96 commented 5 years ago

That's not a bug, is it? The socket has been closed so you get an exception to notify you of that.

gogolxdong commented 5 years ago

It's such a subtle severe bug that at least two places have to be changed to make the example server not crashing when interacting with Karax websocket on page refreshing. shared.nim line 134 should be:

  if headerLen < result.len:
    copyMem(addr result[headerLen], addr data[0], data.len)

regarding the example server , it should be

  while true and not isClosed(ws.sock):
    let (opcode, data) = await ws.readData()
    try:
      echo "(opcode: ", opcode, ", data length: ", data.len, ")"
      case opcode
      of Opcode.Text:
        var msg = parseJson data
        var cmd = msg["cmd"].getStr
        var user = User()
        var response: JsonNode
        {.gcsafe.}:
          if dispatchTable.hasKey(cmd):
              response = await dispatchTable[cmd](user, msg)
          else:
              echo("unknown cmd:" & cmd)
              response = %*{}
          waitFor ws.sendText($response)
      of Opcode.Binary:
        waitFor ws.sendBinary(data)
      of Opcode.Close:
        await ws.close()
        let (closeCode, reason) = extractCloseData(data)
        echo "socket went away, close code: ", closeCode, ", reason: ", reason
      else: discard 
    except:
      echo "encountered exception: ", getCurrentExceptionMsg()

and cannot avoid this issue in our own case: Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: [Warning] WS negotiation failed: the only supported sec-websocket-version is 13 Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: [Warning] WS negotiation failed: the only supported sec-websocket-version is 13 Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: [Warning] WS negotiation failed: the only supported sec-websocket-version is 13 Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: [Warning] WS negotiation failed: the only supported sec-websocket-version is 13 Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: [Warning] WS negotiation failed: the only supported sec-websocket-version is 13 Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: [Warning] WS negotiation failed: the only supported sec-websocket-version is 13 Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: [Warning] WS negotiation failed: the only supported sec-websocket-version is 13 Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: [Warning] WS negotiation failed: the only supported sec-websocket-version is 13 Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: [Warning] WS negotiation failed: the only supported sec-websocket-version is 13 Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: nqtpserver.nim(123) nqtpserver Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: nqtpserver.nim(107) serve Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: asyncdispatch.nim(1656) waitFor Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: asyncdispatch.nim(1516) poll Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: asyncdispatch.nim(1282) runOnce Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: asyncdispatch.nim(191) processPendingCallbacks Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: asyncmacro.nim(39) processRequest_continue Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: asynchttpserver.nim(275) processRequestIter Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: asyncnet.nim(628) close Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: asyncdispatch.nim(1122) closeSocket Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: ioselectors_epoll.nim(180) unregister Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: system.nim(3877) failedAssertImpl Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: system.nim(3870) raiseAssert Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: system.nim(2916) sysFatal Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: [[reraised from: Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: nqtpserver.nim(123) nqtpserver Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: nqtpserver.nim(107) serve Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: asyncdispatch.nim(1656) waitFor Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: asyncdispatch.nim(1516) poll Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: asyncdispatch.nim(1282) runOnce Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: asyncdispatch.nim(191) processPendingCallbacks Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: asyncmacro.nim(36) processClient_continue Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: asynchttpserver.nim(288) processClientIter Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: asyncfutures.nim(302) read Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: ]] Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: [[reraised from: Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: nqtpserver.nim(123) nqtpserver Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: nqtpserver.nim(107) serve Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: asyncdispatch.nim(1656) waitFor Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: asyncdispatch.nim(1516) poll Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: asyncdispatch.nim(1282) runOnce Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: asyncdispatch.nim(191) processPendingCallbacks Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: asyncfutures.nim(349) :anonymous Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: ]] Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: Error: unhandled exception: /root/Nim/lib/pure/ioselects/ioselectors_epoll.nim(180, 11) Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: not (pkey.ident == InvalidIdent) Descriptor 18 is not registered in the selector! Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: Async traceback: Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: nqtpserver.nim(123) nqtpserver Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: nqtpserver.nim(107) serve Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: asyncdispatch.nim(1656) waitFor Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: asyncdispatch.nim(1516) poll Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: ## Processes asynchronous completion events Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: asyncdispatch.nim(1282) runOnce Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: asyncdispatch.nim(191) processPendingCallbacks Jan 24 01:20:38 localhost.localdomain nqtpserver[24258]: ## Executes pending callbacks