Alexander Shenkin
2016-Sep-14 08:49 UTC
[R] Maximum # of DLLs reached, or, how to clean up after yourself?
Hi Henrik, Thanks for your reply. I didn't realize that floating DLLs were an issue (good to know). My query is actually a bit more basic. I'm actually wondering how folks manage their loading and unloading of packages when calling scripts within scripts. Quick example: Script1: library(package1) source("script2.r") # do stuff reliant on package1 detach("package:package1", unload=TRUE) Script2: library(package1) library(package2) # do stuff reliant on package1 and package2 detach("package:package1", unload=TRUE) detach("package:package2", unload=TRUE) Script2 breaks Script1 by unloading package1 (though unloading package2 is ok). I will have to test whether each package is loaded in Script2 before loading it, and use that list when unloading at the end of the Script2. *Unless there's a better way to do it* (which is my question - is there?). I'm possibly just pushing the whole procedural scripting thing too far, but I also think that this likely isn't uncommon in R. Any thoughts greatly appreciated! Thanks, Allie On 9/13/2016 7:23 PM, Henrik Bengtsson wrote:> In R.utils (>= 2.4.0), which I hope to submitted to CRAN today or > tomorrow, you can simply call: > > R.utils::gcDLLs() > > It will look at base::getLoadedDLLs() and its content and compare to > loadedNamespaces() and unregister any "stray" DLLs that remain after > corresponding packages have been unloaded. > > Until the new version is on CRAN, you can install it via > > source("http://callr.org/install#HenrikBengtsson/R.utils at develop") > > or alternatively just source() the source file: > > source("https://raw.githubusercontent.com/HenrikBengtsson/R.utils/develop/R/gcDLLs.R") > > > DISCUSSION: > (this might be better suited for R-devel; feel free to move it there) > > As far as I understand the problem, running into this error / limit is > _not_ the fault of the user. Instead, I'd argue that it is the > responsibility of package developers to make sure to unregister any > registered DLLs of theirs when the package is unloaded. A developer > can do this by adding the following to their package: > > .onUnload <- function(libpath) { > library.dynam.unload(utils::packageName(), libpath) > } > > That should be all - then the DLL will be unloaded as soon as the > package is unloaded. > > I would like to suggest that 'R CMD check' would include a check that > asserts when a package is unloaded it does not leave any registered > DLLs behind, e.g. > > * checking whether the namespace can be unloaded cleanly ... WARNING > Unloading the namespace does not unload DLL > * checking loading without being on the library search path ... OK > > For further details on my thoughts on this, see > https://github.com/HenrikBengtsson/Wishlist-for-R/issues/29. > > Hope this helps > > Henrik > > On Tue, Sep 13, 2016 at 6:05 AM, Alexander Shenkin <ashenkin at ufl.edu> wrote: >> Hello all, >> >> I have a number of analyses that call bunches of sub-scripts, and in the >> end, I get the "maximal number of DLLs reached" error. This has been asked >> before (e.g. >> http://stackoverflow.com/questions/36974206/r-maximal-number-of-dlls-reached), >> and the general answer is, "just clean up after yourself". >> >> Assuming there are no plans to raise this 100-DLL limit in the near future, >> my question becomes, what is best practice for cleaning up (detaching) >> loaded packages in scripts, when those scripts are sometimes called from >> other scripts? One can detach all packages at the end of a script that were >> loaded at the beginning of the script. However, if a package is required in >> a calling script, one should really make sure it hadn't been loaded prior to >> sub-script invocation before detaching it. >> >> I could write a custom function that pushes and pops package names from a >> global list, in order to keep track, but maybe there's a better way out >> there... >> >> Thanks for any thoughts. >> >> Allie >> >> ______________________________________________ >> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see >> https://stat.ethz.ch/mailman/listinfo/r-help >> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html >> and provide commented, minimal, self-contained, reproducible code.
Jeff Newmiller
2016-Sep-14 13:41 UTC
[R] Maximum # of DLLs reached, or, how to clean up after yourself?
I never detach packages. I rarely load more than 6 or 7 packages directly before restarting R. I frequently re-run my scripts in new R sessions to confirm reproducibility. -- Sent from my phone. Please excuse my brevity. On September 14, 2016 1:49:55 AM PDT, Alexander Shenkin <ashenkin at ufl.edu> wrote:>Hi Henrik, > >Thanks for your reply. I didn't realize that floating DLLs were an >issue (good to know). My query is actually a bit more basic. I'm >actually wondering how folks manage their loading and unloading of >packages when calling scripts within scripts. > >Quick example: >Script1: > library(package1) > source("script2.r") > # do stuff reliant on package1 > detach("package:package1", unload=TRUE) > >Script2: > library(package1) > library(package2) > # do stuff reliant on package1 and package2 > detach("package:package1", unload=TRUE) > detach("package:package2", unload=TRUE) > >Script2 breaks Script1 by unloading package1 (though unloading package2 > >is ok). I will have to test whether each package is loaded in Script2 >before loading it, and use that list when unloading at the end of the >Script2. *Unless there's a better way to do it* (which is my question >- >is there?). I'm possibly just pushing the whole procedural scripting >thing too far, but I also think that this likely isn't uncommon in R. > >Any thoughts greatly appreciated! > >Thanks, >Allie > >On 9/13/2016 7:23 PM, Henrik Bengtsson wrote: >> In R.utils (>= 2.4.0), which I hope to submitted to CRAN today or >> tomorrow, you can simply call: >> >> R.utils::gcDLLs() >> >> It will look at base::getLoadedDLLs() and its content and compare to >> loadedNamespaces() and unregister any "stray" DLLs that remain after >> corresponding packages have been unloaded. >> >> Until the new version is on CRAN, you can install it via >> >> >source("http://callr.org/install#HenrikBengtsson/R.utils at develop") >> >> or alternatively just source() the source file: >> >> >source("https://raw.githubusercontent.com/HenrikBengtsson/R.utils/develop/R/gcDLLs.R") >> >> >> DISCUSSION: >> (this might be better suited for R-devel; feel free to move it there) >> >> As far as I understand the problem, running into this error / limit >is >> _not_ the fault of the user. Instead, I'd argue that it is the >> responsibility of package developers to make sure to unregister any >> registered DLLs of theirs when the package is unloaded. A developer >> can do this by adding the following to their package: >> >> .onUnload <- function(libpath) { >> library.dynam.unload(utils::packageName(), libpath) >> } >> >> That should be all - then the DLL will be unloaded as soon as the >> package is unloaded. >> >> I would like to suggest that 'R CMD check' would include a check that >> asserts when a package is unloaded it does not leave any registered >> DLLs behind, e.g. >> >> * checking whether the namespace can be unloaded cleanly ... WARNING >> Unloading the namespace does not unload DLL >> * checking loading without being on the library search path ... OK >> >> For further details on my thoughts on this, see >> https://github.com/HenrikBengtsson/Wishlist-for-R/issues/29. >> >> Hope this helps >> >> Henrik >> >> On Tue, Sep 13, 2016 at 6:05 AM, Alexander Shenkin <ashenkin at ufl.edu> >wrote: >>> Hello all, >>> >>> I have a number of analyses that call bunches of sub-scripts, and in >the >>> end, I get the "maximal number of DLLs reached" error. This has >been asked >>> before (e.g. >>> >http://stackoverflow.com/questions/36974206/r-maximal-number-of-dlls-reached), >>> and the general answer is, "just clean up after yourself". >>> >>> Assuming there are no plans to raise this 100-DLL limit in the near >future, >>> my question becomes, what is best practice for cleaning up >(detaching) >>> loaded packages in scripts, when those scripts are sometimes called >from >>> other scripts? One can detach all packages at the end of a script >that were >>> loaded at the beginning of the script. However, if a package is >required in >>> a calling script, one should really make sure it hadn't been loaded >prior to >>> sub-script invocation before detaching it. >>> >>> I could write a custom function that pushes and pops package names >from a >>> global list, in order to keep track, but maybe there's a better way >out >>> there... >>> >>> Thanks for any thoughts. >>> >>> Allie >>> >>> ______________________________________________ >>> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see >>> https://stat.ethz.ch/mailman/listinfo/r-help >>> PLEASE do read the posting guide >http://www.R-project.org/posting-guide.html >>> and provide commented, minimal, self-contained, reproducible code. > >______________________________________________ >R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see >https://stat.ethz.ch/mailman/listinfo/r-help >PLEASE do read the posting guide >http://www.R-project.org/posting-guide.html >and provide commented, minimal, self-contained, reproducible code.
Henrik Bengtsson
2016-Sep-14 18:42 UTC
[R] Maximum # of DLLs reached, or, how to clean up after yourself?
As Jeff says, I think the common use case is to run/rerun in fresh R sessions. But, yes, if you'd like to have each script clean up after itself, then you need to check with pkgs0 <- loadedNamespaces() to see what packages are loaded when the script starts (not just attached) and then unload the ones added at the end by pkgsDiff <- setdiff(loadedNamespaces(), pkgs0). However, it's not as simple as calling unloadNamespace(pkgsDiff), because they need to be unloaded in an order that is compatible with the package dependencies. One way is to too use while(length(pkgDiffs) > 0) loop over with a try(unloadNamespace(pkg)) until all are unloaded. At the end, run R.utils::gcDLLs() too (now on CRAN). unloadNamespace("foo") should result in the same as detach("package::foo", unload=TRUE) [anyone correct me if I'm wrong]. Hope this helps Henrik On Wed, Sep 14, 2016 at 6:41 AM, Jeff Newmiller <jdnewmil at dcn.davis.ca.us> wrote:> I never detach packages. I rarely load more than 6 or 7 packages directly before restarting R. I frequently re-run my scripts in new R sessions to confirm reproducibility. > -- > Sent from my phone. Please excuse my brevity. > > On September 14, 2016 1:49:55 AM PDT, Alexander Shenkin <ashenkin at ufl.edu> wrote: >>Hi Henrik, >> >>Thanks for your reply. I didn't realize that floating DLLs were an >>issue (good to know). My query is actually a bit more basic. I'm >>actually wondering how folks manage their loading and unloading of >>packages when calling scripts within scripts. >> >>Quick example: >>Script1: >> library(package1) >> source("script2.r") >> # do stuff reliant on package1 >> detach("package:package1", unload=TRUE) >> >>Script2: >> library(package1) >> library(package2) >> # do stuff reliant on package1 and package2 >> detach("package:package1", unload=TRUE) >> detach("package:package2", unload=TRUE) >> >>Script2 breaks Script1 by unloading package1 (though unloading package2 >> >>is ok). I will have to test whether each package is loaded in Script2 >>before loading it, and use that list when unloading at the end of the >>Script2. *Unless there's a better way to do it* (which is my question >>- >>is there?). I'm possibly just pushing the whole procedural scripting >>thing too far, but I also think that this likely isn't uncommon in R. >> >>Any thoughts greatly appreciated! >> >>Thanks, >>Allie >> >>On 9/13/2016 7:23 PM, Henrik Bengtsson wrote: >>> In R.utils (>= 2.4.0), which I hope to submitted to CRAN today or >>> tomorrow, you can simply call: >>> >>> R.utils::gcDLLs() >>> >>> It will look at base::getLoadedDLLs() and its content and compare to >>> loadedNamespaces() and unregister any "stray" DLLs that remain after >>> corresponding packages have been unloaded. >>> >>> Until the new version is on CRAN, you can install it via >>> >>> >>source("http://callr.org/install#HenrikBengtsson/R.utils at develop") >>> >>> or alternatively just source() the source file: >>> >>> >>source("https://raw.githubusercontent.com/HenrikBengtsson/R.utils/develop/R/gcDLLs.R") >>> >>> >>> DISCUSSION: >>> (this might be better suited for R-devel; feel free to move it there) >>> >>> As far as I understand the problem, running into this error / limit >>is >>> _not_ the fault of the user. Instead, I'd argue that it is the >>> responsibility of package developers to make sure to unregister any >>> registered DLLs of theirs when the package is unloaded. A developer >>> can do this by adding the following to their package: >>> >>> .onUnload <- function(libpath) { >>> library.dynam.unload(utils::packageName(), libpath) >>> } >>> >>> That should be all - then the DLL will be unloaded as soon as the >>> package is unloaded. >>> >>> I would like to suggest that 'R CMD check' would include a check that >>> asserts when a package is unloaded it does not leave any registered >>> DLLs behind, e.g. >>> >>> * checking whether the namespace can be unloaded cleanly ... WARNING >>> Unloading the namespace does not unload DLL >>> * checking loading without being on the library search path ... OK >>> >>> For further details on my thoughts on this, see >>> https://github.com/HenrikBengtsson/Wishlist-for-R/issues/29. >>> >>> Hope this helps >>> >>> Henrik >>> >>> On Tue, Sep 13, 2016 at 6:05 AM, Alexander Shenkin <ashenkin at ufl.edu> >>wrote: >>>> Hello all, >>>> >>>> I have a number of analyses that call bunches of sub-scripts, and in >>the >>>> end, I get the "maximal number of DLLs reached" error. This has >>been asked >>>> before (e.g. >>>> >>http://stackoverflow.com/questions/36974206/r-maximal-number-of-dlls-reached), >>>> and the general answer is, "just clean up after yourself". >>>> >>>> Assuming there are no plans to raise this 100-DLL limit in the near >>future, >>>> my question becomes, what is best practice for cleaning up >>(detaching) >>>> loaded packages in scripts, when those scripts are sometimes called >>from >>>> other scripts? One can detach all packages at the end of a script >>that were >>>> loaded at the beginning of the script. However, if a package is >>required in >>>> a calling script, one should really make sure it hadn't been loaded >>prior to >>>> sub-script invocation before detaching it. >>>> >>>> I could write a custom function that pushes and pops package names >>from a >>>> global list, in order to keep track, but maybe there's a better way >>out >>>> there... >>>> >>>> Thanks for any thoughts. >>>> >>>> Allie >>>> >>>> ______________________________________________ >>>> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see >>>> https://stat.ethz.ch/mailman/listinfo/r-help >>>> PLEASE do read the posting guide >>http://www.R-project.org/posting-guide.html >>>> and provide commented, minimal, self-contained, reproducible code. >> >>______________________________________________ >>R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see >>https://stat.ethz.ch/mailman/listinfo/r-help >>PLEASE do read the posting guide >>http://www.R-project.org/posting-guide.html >>and provide commented, minimal, self-contained, reproducible code. >