rstudio/websocket

Error in callback leaves WebSocket object in non-responsive state

wch opened this issue · 1 comments

wch commented

Example:

ws <- websocket::WebSocket$new("ws://echo.websocket.org")
ws$onMessage(function(event) {
  message("Message received: ", event$data)
  stop("error here")
})

ws$send("hello")
#> Message received: hello
#> later: exception occurred while executing callback: 
#> Evaluation error: Evaluation error: error here..

ws$send("hello")  # Nothing happens
wch commented

In my testing, it looks like there are two problems. The callback is invoked from the later event loop. The R code at https://github.com/rstudio/websocket/blob/3f27afd2/R/websocket.R#L244 calls wsPoll, which is a wrapper for the wsPoll C++ function, which calls handleMessage, which calls the invoke R function, which calls the user-defined onMessage callback.

If that R code throws an exception, the exception bubbles up from R to C++ to the R handleIncoming method, and private$scheduleIncoming doesn't get called.

Even if that's fixed by adding a tryCatch around the wsPoll(private$wsObj), it appears that the websocket on the C++ side ends up in a messed up state when an exception occurs, either in the R user code or in an exception that's thrown directly in C++. I don't understand the websocketpp code well enough to say why this is happening.

Basically, the structure of the calls is:
later calls R handleIncoming function -> calls C++ poll function -> (mystery stuff) -> calls C++ handleMessage function -> calls R invoke function -> calls R user callback.

If the error happens in the (mystery stuff) layer, then the websocket seems like it ends up in a state where it no longer works properly.

I think the solution is to catch the error in either the R invoke function or the C++ `handleMessage function.