r-lib / later

Schedule an R function or formula to run after a specified period of time.
https://r-lib.github.io/later
Other
139 stars 28 forks source link

WebSocket run with later private loop can sometimes not be GC'd #83

Closed wch closed 5 years ago

wch commented 5 years ago

Note: this needs the joe/feature/private-event-loops2 branch branch of later.

In this example, the websocket is created and closed, and driven from a private event loop. It calls run_now() until the websocket's has readyState()==3. If the ws object is removed and then a GC happens, the object is not garbage collected. The event loop needs to be run one more time before the GC occurs.

devtools::install_github("r-lib/later@joe/feature/private-event-loops2")

library(later)
library(WebSocket)

private_loop <- NULL
later::with_private_loop({
  private_loop <<- current_loop()
  ws <- WebSocket$new("ws://echo.websocket.org")
  reg.finalizer(ws, function(e) message("finalized!"))
  ws$close()
  while (ws$readyState() != 3L) {
    run_now()
  }
})

rm(ws)
gc()
#>           used (Mb) gc trigger (Mb) limit (Mb) max used (Mb)
#> Ncells  967903 51.7    1538886 82.2         NA  1538886 82.2
#> Vcells 2165223 16.6    8388608 64.0      16384  4722708 36.1

run_now(loop = private_loop)
gc()
#> finalized!
#>           used (Mb) gc trigger (Mb) limit (Mb) max used (Mb)
#> Ncells  967903 51.7    1538886 82.2         NA  1538886 82.2
#> Vcells 2165394 16.6    8388608 64.0      16384  4722708 36.1

This happens because scheduleIncoming() is always called right after wsPoll(), even if that wsPoll() call changes the readyState to 3:

https://github.com/rstudio/websocket/blob/ccc03d59868b3ced956d54bd22dc4e89376dd207/R/websocket.R#L240-L247

wch commented 5 years ago

Oops, filed this on the wrong repo.