45

From Hadley's C best practices:

Like with C++, whenever you use C code in your package, you should unload the DLL when the package is unloaded:

.onUnload <- function (libpath) {
  library.dynam.unload("mypackage", libpath)
}

Writing R Extensions on the other hand doesn't even mention this. I can see how it would be polite to unload the dlls, but doing so seems to cause some weird problems for me with packages that are loaded/unloaded/reloaded (see example further down). Additionally, there are some mentions that suggest maybe unloading isn't required. From ?library.dynam:

Note that whether or not it is possible to unload a DLL and then reload a revised version of the same file is OS-dependent: see the ‘Value’ section of the help for dyn.unload.

though this shouldn't affect objects that are not modified. Then there is this comment from Brian Ripley in R-devel:

Having said all that, my experience is that unloading the DLL often does not help if you need to load it again (and that is why e.g. tcltk does not unload its DLL).

So is it acceptable to leave the C libraries loaded? I would prefer not to have to dig into why stuff like the below is happening (did not happen before I started unloading libraries).

R version 3.1.1 (2014-07-10)
Platform: x86_64-apple-darwin13.1.0 (64-bit)

> library(alike)       # install_github("brodieg/alike", ref="fdaa578e"), if you're curious
> library(data.table)
data.table 1.9.2  For help type: help("data.table")
> detach("package:data.table", unload=T)
> detach("package:alike", unload=T)
> library(alike)
> library(data.table)
Error : .onLoad failed in loadNamespace() for 'data.table', details:
  call: address(x)
  error: object 'Caddress' not found
In addition: Warning messages:
1: In FUN(X[[9L]], ...) :
  failed to assign RegisteredNativeSymbol for alike to alike since alike is already defined in the ‘data.table’ namespace
2: In FUN(X[[9L]], ...) :
  failed to assign RegisteredNativeSymbol for typeof to typeof since typeof is already defined in the ‘data.table’ namespace
3: In FUN(X[[9L]], ...) :
  failed to assign RegisteredNativeSymbol for type_alike to type_alike since type_alike is already defined in the ‘data.table’ namespace
Error: package or namespace load failed for ‘data.table’

The warnings are all related to alike functions. alike did not use to unload its dynamic libraries, and the above errors did not happen. After I implemented unloading the errors started happening. Note that data.table 1.9.2 did not unload its DLLs, though other packages that also don't unload DLLs didn't cause this problems. data.table 1.9.4 works fine.

BrodieG
  • 51,669
  • 9
  • 93
  • 146
  • I know it's your question but did you even find any additional information about this? – Dason Apr 14 '15 at 00:08
  • @Dason, afraid not. I also ran into [this issue](https://github.com/Rdatatable/data.table/issues/990) with `data.table` which may or may not be related. Additionally, I haven't actually had this issue in a while, but too much has changed to know exactly what fixed it. – BrodieG Apr 14 '15 at 00:29
  • 1
    Weird. I'm in the habit of auto-unloading, because I've been bitten by debugging the wrong version of a DLL I forgot to unload. The workflow was: load package, find bug, fix, re-load package. But the DLL didn't get unloaded. Ewps. So Hadley's advice is excellent for developers. But I've never seen a problem like yours in the wild. Interesting stuff. – Jason Oct 06 '16 at 03:50
  • So are you asking the opinion-based question "should I do this", or the on-topic question "how can I unload and then re-load a DLL without getting these errors", to which the answer might be "don't"? – Nic Mar 16 '17 at 18:36
  • This seems somehow related (possible duplicate of?): http://stackoverflow.com/a/6979989/7411272 – Hassia Biker May 02 '17 at 21:53
  • @HassiaBiker, this is specifically about packages that load compiled code, and what those packages should internally do when the user tries to unload them. Your link is about unloading packages. – BrodieG May 02 '17 at 22:04

1 Answers1

3

Normally unloading a DLL would be a good idea. The resources it owns, would be completely freed, and re-loading would not be an issue.

In R, there is the complication of the R environment, because even if a DLL is unloaded, there may be some knowledge left behind in the R runtime. In this case, the result may be that the re-loaded DLL library does not share the same inferred state as the R variables which are intended to understand the DLL state, and thus errors occur.

I think it would be possible for an R package (DLL and R code) to be safely unloaded, but it would be easier for you to leave the DLLs loaded, unless you find particularly heavy resource usage.

mksteve
  • 12,614
  • 3
  • 28
  • 50
  • Yes. It's a very bad idea to unload a library if you do not have full control of all the pointers to that library. Unloading a library is a rather unusual operation, and many programs do not ever call FreeLibrary(). As a rule of thumb, resource allocation and de-allocation in an external package like R is the responsibility of the package itself _unless explicitly specified in the documentation_, – Michaël Roy Jun 13 '17 at 13:54