rolandoislas / BrightWebSocket

RFC 6455 WebSocket Library for the Roku
Other
14 stars 11 forks source link

Overloaded by mass incoming frames #1

Closed lkrocek closed 5 years ago

lkrocek commented 6 years ago

Hi there,

I made some app and when I send to the roku client with this library more messages at once like 50 messages in 10-20 ms interval app will crash with stack trace below:

Suspending threads...
Thread selected:  1*   ...tlibrary:/WebSocketClient.brs(634)   send(message, m.OPCODE_CLOSE)

Current Function:
627:  function send_close_frame(code, reason)
628:      message = createObject("roByteArray")
629:      message.push(code >> 8)
630:      message.push(code)
631:      if reason <> invalid
632:          message.append(reason)
633:      end if
634:*     send(message, m.OPCODE_CLOSE)
635:  end function
Stack overflow. (runtime error &hdf) in mycomponentlibrary:/WebSocketClient.brs(634)
634:     send(message, m.OPCODE_CLOSE)
Backtrace:
#69 Function send_close_frame(code As Dynamic, reason As Dynamic) As Dynamic
   file/line: mycomponentlibrary:/WebSocketClient.brs(634)
#68 Function close() As Integer
   file/line: mycomponentlibrary:/WebSocketClient.brs(611)
#67 Function send(message As Dynamic, _opcode As Integer) As Boolean
   file/line: mycomponentlibrary:/WebSocketClient.brs(226)
#66 Function send_close_frame(code As Dynamic, reason As Dynamic) As Dynamic
   file/line: mycomponentlibrary:/WebSocketClient.brs(634)
#65 Function close() As Integer
   file/line: mycomponentlibrary:/WebSocketClient.brs(611)
#64 Function send(message As Dynamic, _opcode As Integer) As Boolean
   file/line: mycomponentlibrary:/WebSocketClient.brs(226)
#63 Function send_close_frame(code As Dynamic, reason As Dynamic) As Dynamic
   file/line: mycomponentlibrary:/WebSocketClient.brs(634)
#62 Function close() As Integer
   file/line: mycomponentlibrary:/WebSocketClient.brs(611)
#61 Function send(message As Dynamic, _opcode As Integer) As Boolean
   file/line: mycomponentlibrary:/WebSocketClient.brs(226)
#60 Function send_close_frame(code As Dynamic, reason As Dynamic) As Dynamic
   file/line: mycomponentlibrary:/WebSocketClient.brs(634)
#59 Function close() As Integer
   file/line: mycomponentlibrary:/WebSocketClient.brs(611)
#58 Function send(message As Dynamic, _opcode As Integer) As Boolean
   file/line: mycomponentlibrary:/WebSocketClient.brs(226)
#57 Function send_close_frame(code As Dynamic, reason As Dynamic) As Dynamic
   file/line: mycomponentlibrary:/WebSocketClient.brs(634)
#56 Function close() As Integer
   file/line: mycomponentlibrary:/WebSocketClient.brs(611)
#55 Function send(message As Dynamic, _opcode As Integer) As Boolean
   file/line: mycomponentlibrary:/WebSocketClient.brs(226)
#54 Function send_close_frame(code As Dynamic, reason As Dynamic) As Dynamic
   file/line: mycomponentlibrary:/WebSocketClient.brs(634)
#53 Function close() As Integer
   file/line: mycomponentlibrary:/WebSocketClient.brs(611)
#52 Function send(message As Dynamic, _opcode As Integer) As Boolean
   file/line: mycomponentlibrary:/WebSocketClient.brs(226)
#51 Function send_close_frame(code As Dynamic, reason As Dynamic) As Dynamic
   file/line: mycomponentlibrary:/WebSocketClient.brs(634)
#50 Function close() As Integer
   file/line: mycomponentlibrary:/WebSocketClient.brs(611)
#49 Function send(message As Dynamic, _opcode As Integer) As Boolean
   file/line: mycomponentlibrary:/WebSocketClient.brs(226)
#48 Function send_close_frame(code As Dynamic, reason As Dynamic) As Dynamic
   file/line: mycomponentlibrary:/WebSocketClient.brs(634)
#47 Function close() As Integer
   file/line: mycomponentlibrary:/WebSocketClient.brs(611)
#46 Function send(message As Dynamic, _opcode As Integer) As Boolean
   file/line: mycomponentlibrary:/WebSocketClient.brs(226)
#45 Function send_close_frame(code As Dynamic, reason As Dynamic) As Dynamic
   file/line: mycomponentlibrary:/WebSocketClient.brs(634)
#44 Function close() As Integer
   file/line: mycomponentlibrary:/WebSocketClient.brs(611)
#43 Function send(message As Dynamic, _opcode As Integer) As Boolean
   file/line: mycomponentlibrary:/WebSocketClient.brs(226)
#42 Function send_close_frame(code As Dynamic, reason As Dynamic) As Dynamic
   file/line: mycomponentlibrary:/WebSocketClient.brs(634)
#41 Function close() As Integer
   file/line: mycomponentlibrary:/WebSocketClient.brs(611)
#40 Function send(message As Dynamic, _opcode As Integer) As Boolean
   file/line: mycomponentlibrary:/WebSocketClient.brs(226)
#39 Function send_close_frame(code As Dynamic, reason As Dynamic) As Dynamic
   file/line: mycomponentlibrary:/WebSocketClient.brs(634)
#38 Function close() As Integer
   file/line: mycomponentlibrary:/WebSocketClient.brs(611)
#37 Function send(message As Dynamic, _opcode As Integer) As Boolean
   file/line: mycomponentlibrary:/WebSocketClient.brs(226)
#36 Function send_close_frame(code As Dynamic, reason As Dynamic) As Dynamic
   file/line: mycomponentlibrary:/WebSocketClient.brs(634)
#35 Function close() As Integer
   file/line: mycomponentlibrary:/WebSocketClient.brs(611)
#34 Function send(message As Dynamic, _opcode As Integer) As Boolean
   file/line: mycomponentlibrary:/WebSocketClient.brs(226)
#33 Function send_close_frame(code As Dynamic, reason As Dynamic) As Dynamic
   file/line: mycomponentlibrary:/WebSocketClient.brs(634)
#32 Function close() As Integer
   file/line: mycomponentlibrary:/WebSocketClient.brs(611)
#31 Function send(message As Dynamic, _opcode As Integer) As Boolean
   file/line: mycomponentlibrary:/WebSocketClient.brs(226)
#30 Function send_close_frame(code As Dynamic, reason As Dynamic) As Dynamic
   file/line: mycomponentlibrary:/WebSocketClient.brs(634)
#29 Function close() As Integer
   file/line: mycomponentlibrary:/WebSocketClient.brs(611)
#28 Function send(message As Dynamic, _opcode As Integer) As Boolean
   file/line: mycomponentlibrary:/WebSocketClient.brs(226)
#27 Function send_close_frame(code As Dynamic, reason As Dynamic) As Dynamic
   file/line: mycomponentlibrary:/WebSocketClient.brs(634)
#26 Function close() As Integer
   file/line: mycomponentlibrary:/WebSocketClient.brs(611)
#25 Function send(message As Dynamic, _opcode As Integer) As Boolean
   file/line: mycomponentlibrary:/WebSocketClient.brs(226)
#24 Function send_close_frame(code As Dynamic, reason As Dynamic) As Dynamic
   file/line: mycomponentlibrary:/WebSocketClient.brs(634)
#23 Function close() As Integer
   file/line: mycomponentlibrary:/WebSocketClient.brs(611)
#22 Function send(message As Dynamic, _opcode As Integer) As Boolean
   file/line: mycomponentlibrary:/WebSocketClient.brs(226)
#21 Function send_close_frame(code As Dynamic, reason As Dynamic) As Dynamic
   file/line: mycomponentlibrary:/WebSocketClient.brs(634)
#20 Function close() As Integer
   file/line: mycomponentlibrary:/WebSocketClient.brs(611)
#19 Function send(message As Dynamic, _opcode As Integer) As Boolean
   file/line: mycomponentlibrary:/WebSocketClient.brs(226)
#18 Function send_close_frame(code As Dynamic, reason As Dynamic) As Dynamic
   file/line: mycomponentlibrary:/WebSocketClient.brs(634)
#17 Function close() As Integer
   file/line: mycomponentlibrary:/WebSocketClient.brs(611)
#16 Function send(message As Dynamic, _opcode As Integer) As Boolean
   file/line: mycomponentlibrary:/WebSocketClient.brs(226)
#15 Function send_close_frame(code As Dynamic, reason As Dynamic) As Dynamic
   file/line: mycomponentlibrary:/WebSocketClient.brs(634)
#14 Function close() As Integer
   file/line: mycomponentlibrary:/WebSocketClient.brs(611)
#13 Function send(message As Dynamic, _opcode As Integer) As Boolean
   file/line: mycomponentlibrary:/WebSocketClient.brs(226)
#12 Function send_close_frame(code As Dynamic, reason As Dynamic) As Dynamic
   file/line: mycomponentlibrary:/WebSocketClient.brs(634)
#11 Function close() As Integer
   file/line: mycomponentlibrary:/WebSocketClient.brs(611)
#10 Function send(message As Dynamic, _opcode As Integer) As Boolean
   file/line: mycomponentlibrary:/WebSocketClient.brs(226)
#9  Function send_close_frame(code As Dynamic, reason As Dynamic) As Dynamic
   file/line: mycomponentlibrary:/WebSocketClient.brs(634)
#8  Function close() As Integer
   file/line: mycomponentlibrary:/WebSocketClient.brs(611)
#7  Function send(message As Dynamic, _opcode As Integer) As Boolean
   file/line: mycomponentlibrary:/WebSocketClient.brs(226)
#6  Function send_close_frame(code As Dynamic, reason As Dynamic) As Dynamic
   file/line: mycomponentlibrary:/WebSocketClient.brs(634)
#5  Function close() As Integer
   file/line: mycomponentlibrary:/WebSocketClient.brs(611)
#4  Function send(message As Dynamic, _opcode As Integer) As Boolean
   file/line: mycomponentlibrary:/WebSocketClient.brs(226)
#3  Function send_close_frame(code As Dynamic, reason As Dynamic) As Dynamic
   file/line: mycomponentlibrary:/WebSocketClient.brs(634)
#2  Function close() As Integer
   file/line: mycomponentlibrary:/WebSocketClient.brs(611)
#1  Function send(message As Dynamic) As Integer
   file/line: mycomponentlibrary:/WebSocketClient.brs(226)
#0  Function run() As Void
   file/line: mycomponentlibrary:/WebSocketClient.brs(70)
Local Variables:
code             Integer val:1000 (&h3E8)
reason           bsc:roInvalid refcnt=2
global           Interface:ifGlobal
m                roAssociativeArray refcnt=71 count:36
message          bsc:roByteArray refcnt=1
Threads:
ID    Location                                Source Code
 0    pkg:/source/main.brs(15)                msg = wait(0, m.port)
 1*   ...tlibrary:/WebSocketClient.brs(634)   send(message, m.OPCODE_CLOSE)
  *selected

I was trying to investigate what actually happen but didn't find it.

I think this stack trace is actually another fail and feel like system break the app due to long term operation, the loop on roPortMessage is receiving message every 66 ms, so system queue incoming messages which are looking like big one.

PS: I am using the WebSocketClient lib in my ComponentLibrary, I tried put it into app ahead but it worked same, I have model 4200X - Roku 3, older but Software is 8.1.0

lkrocek commented 6 years ago

ok, reading of interface data it delay by 16 ms per each, so function try_force_close and try_send_ping when used m.top every time it delayed by 16 ms which are used 4 times in conditions at all is equal to delayed by 64ms at least.

rolandoislas commented 6 years ago

The error is a stack overflow caused by an infinite recursion bug. A send fails and the close process beings. Upon sending the close frame, the send fails, causing the close process to begin again.

The ping response check was likely what caused the initial close frame to be sent if the incoming/outgoing frames were not able to be handled within one second.

TODO:

lkrocek commented 6 years ago

I rapidly reduced delay by removing m.top. into m. where it was possible (Const as STATE_OPEN, etc., headers, protocols which I am not using), but still have on_message and send which are main communication way so if I simulate that 50x each 10ms it might not crash but still can because on_message field is fired and cause that 16ms delay.

Is there any another way how to communicate? Maybe put messagePort into interface and share data over it, I am still newbie in BrightScript so not sure if it is possible or how it could be done.

lkrocek commented 6 years ago

So now my application is based on your library, I completely removed all m.top usage within observes and setFields so I call directly on_message() function instead of m.top.setField("on_message" ,... which is defined in the same component and application works perfectly without delays. So maybe it could be somehow refactored.

And by the way I figured out on same delay issue happens in my other components extended by Group, I had to change extends field from Group to Poster, even it is so weird it works well, I reported this issue but unfortunately without reaction yet.

rolandoislas commented 6 years ago

See #2. The dev branch has a commit that removes Scenegraph dependencies for the main web socket logic.

lkrocek commented 6 years ago

It's mostly perfect, just put configurable wait loop I mentioned in https://github.com/rolandoislas/BrightWebSocket/issues/2#issuecomment-401727090

lkrocek commented 6 years ago

Hi, even the infinite recursion bug has been solved When I am sending lot requests with 25ms delay device in a while reset connection (guess some overload). I have 2 models of roku devices:

lkrocek commented 6 years ago

still no update of this?