9

I can load my library, but I cannot unload it with LibraryUnload. I do have a void WolframLibrary_uninitialize(WolframLibraryData libData) (which does nothing). I get the following error:

LibraryFunction::unloadlib: The library "/my/library.so" cannot be unloaded.

I am not loading any function after loading the library. The OS is Linux x86_64.

I don't seem to be able to unload not even the demo library:

LibraryLoad@"demo"
LibraryUnload@%

This gets me the same error.

EDIT: As worked out by Szabolcs and halirutan, I need to load one function at least (LibraryFunctionLoad) to have the initialization function called, and so being able to call LibraryUnload successfully. Yet, my ultimate goal is to be able to reload a new build of the library: this seems impossible because calling LibraryUnload doesn't actually close the handle of the library, and further calls to LibraryFunctionLoad reuse it. I checked with lsof, and if I delete the library and try to reload it I get that the new file is ignored and instead a handle to the old file (tagged correctly as DEL in lsof) is kept.

Szabolcs
  • 234,956
  • 30
  • 623
  • 1,263
Lorenzo Pistone
  • 1,607
  • 11
  • 16
  • Apparently I cannot unload the demo libraries too. I need this feature because I'm coding this library, and I don't want to restart the kernel each time. – Lorenzo Pistone Dec 05 '13 at 23:25
  • 2
    If you see the issue even with the demo-libraries, can you please make a minimal, self-contained example where you exactly show how you load and unload the library-function? I have Mathematica 9.0.1 and Ubuntu x86-64 and here, unloading seems to work properly. – halirutan Dec 06 '13 at 00:54
  • @halirutan done. – Lorenzo Pistone Dec 08 '13 at 18:20
  • 2
    It seems that if I actually load some functions from the library (as here) then afterwards I can unload without problems. But if I don't load any functions (and only use LibraryLoad) then I get the error you mentioned. – Szabolcs Dec 08 '13 at 18:28
  • 1
    I'm not sure, but I think that LibraryLoad won't actually run the library initialization code, it will only load the library. You can use LibraryLoad to load any shared library that your code may need, not only LibraryLink-specific libraries (see here). So it would make sense that it doesn't attempt to run the wolfram library initialization. Maybe if this is not run then uninitialization fails. Just guesses. – Szabolcs Dec 08 '13 at 18:31
  • I think you're right @Szabolcs . I just tried and loading a function makes the library unloadable... But! This doesn't mean that the library is dlclose()'d (I checked with lsof, the handle is still there), which is what I actually want to do, because in the process of developing the library I might want to recompile it, and I don't want to reboot the kernel every time. – Lorenzo Pistone Dec 08 '13 at 18:47
  • 1
    I'm not familiar with the intricacies of shared libraries, but when I was writing LibraryLink-based tools, as far as I can remember I didn't have a problem with using LibraryUnload, deleting the library, recompiling, and loading again. Are you saying this doesn't work as expected? – Szabolcs Dec 08 '13 at 18:53
  • @Szabolcs yes, see edit. – Lorenzo Pistone Dec 09 '13 at 13:43
  • @LorenzoPistone How did you solve the problem in the end? I encountered the same problem. Even I update my library file, Mathematica still uses the old library file until a kernel restart. – xslittlegrass Dec 02 '16 at 18:52
  • @xslittlegrass I don't think I ever solved the problem in a reliable way, and in general I started avoiding C interoperability with Mathematica, it is in general too clunky. Now I'm using giant dump files between my C code and Mathematica, which is meh but at least I don't get hard crashes. – Lorenzo Pistone Dec 03 '16 at 10:32

2 Answers2

4

Todd Gayley once mentioned that LibraryLoad is for pre-loading depend libraries you need. So for instance, if you write a function which needs some numeric-library, you can load this before calling the functions in your library.

You don't need to pre-load the WolframLibrary library you have developed because you implicitly load it by loading the functions in it.

Therefore, I believe the solution to your problem is that you have to call LibraryFunctionLoad on one of the functions you are developing and after that LibraryUnload should work as expected.

Furthermore, you should unload all functions with LibraryFunctionUnload before unloading the library.

halirutan
  • 112,764
  • 7
  • 263
  • 474
  • I can confirm that this is how it works. Yet, LibraryUnload doesn't close the handle to the library, and if I replace it with a new build, there's no way to unlink the old version from the Kernel. – Lorenzo Pistone Dec 09 '13 at 13:37
  • Ok, if I LibraryFunctionLoad then LibraryFunctionUnload a function in my library, the library is correctly unlink from the kernel. If you add this to your answer I'll flag it as accepted – Lorenzo Pistone Dec 10 '13 at 11:46
  • @LorenzoPistone Sorry for the late reply. I added the information to the answer. You know that you could have done this by yourself. It's one of the basic rules of SE that everyone can edit everything. Don't be afraid to use it. – halirutan Dec 16 '13 at 14:27
  • haha sorry, I didn't realize after all this time using SO! – Lorenzo Pistone Dec 16 '13 at 15:22
  • 1
    @halirutan: you mention that LibraryLoad is needed to pre-load libraries which own libs depend on. This is what I currently need to do, but then I can't unload those libraries (there is no LibraryFunction to load from those). Do you have a solution how I can Unload those dependencies so I can remove them without closing the kernel? I'm afraid that won't work, which I consider an oversight (bug?)... – Albert Retey Dec 30 '15 at 16:58
  • @AlbertRetey The Details section of LibraryUnload says, that you can use it exactly for this: "LibraryUnload will unload a library that does not follow the Wolfram Library specification." – halirutan Dec 30 '15 at 17:16
  • @halirutan: yes, but that seems to not work, at least not for me on Windows. I'm not sure whether that is a shortcoming of LibraryLink` or of Windows, though. When I try to unload LibraryUnload gives an error message and the kernel still keeps a handle on the corresponding file... – Albert Retey Dec 30 '15 at 18:15
  • On OS X, there is more to it: if the library was loaded using LibraryLoad, then LibraryUnload will simply not work (whether LibraryFunctionLoad was used or not). The only way I found to make LibraryUnload work was never to use LibraryLoad in the first place. – Szabolcs Mar 03 '16 at 13:16
  • Hi @AlbertRetey ! May I ask have you found a solution to your question? I ran into exactly same problem on Windows recently. – Silvia Feb 08 '21 at 16:17
  • I don't remember really, but I think that I didn't find a solution. For the things I did, I could live with restarting the Kernel, I think... – Albert Retey Feb 08 '21 at 20:42
  • @AlbertRetey I just got a solution today from @ilian: if one appends the path of depended lib to PATH environment variable (something like SetEnvironment["PATH" -> Environment["PATH"] <> ";" <> libpath]), then one won't need to pre-load the lib with LibraryLoad anymore, as Windows will take care of it, as well as ensure it (quote:) "gets unloaded automatically when no longer referenced". – Silvia Feb 09 '21 at 13:07
  • @Silvia: thanks for mentioning this, will be of great help for me. Would you mind to add this as an answer? I think it would be very valuable to have that as an answer and not only as a hard-to-find and probably non-lasting comment... – Albert Retey Feb 10 '21 at 14:30
  • @AlbertRetey You're absolutely right. Done! – Silvia Feb 10 '21 at 16:14
3

(Information worth sharing for Windows users despite the tag in original question.)

As this comment mentioned, there is an additional problem on Windows platform, which I will try to describe here, as long as a solution to it.

The LibraryUnload failure problem on Windows

Suppose one has a "standalone" library myLib.dll, which has nothing to do with Mathematica or LibraryLink. Then one has a libLink.dll, which uses myLib and provides functions to Mathematica through LibraryLink.

As libLink depends on myLib, one may try to pre-load myLib before loading libLink, and it works with no problem:

LibraryLoad["myLib.dll"]
myfunc = LibraryFunctionLoad["libLink.dll", ... ]

But then, on Windows, if one tries to unload them with

LibraryUnload["libLink.dll"]
LibraryUnload["myLib.dll"]

The former one will succeed but the latter one will fail with an error message

LibraryFunction::unloadlib: The library myLib.dll cannot be unloaded.

Using tools such as Process Explorer one can see the file's handle has not been released by the kernel.

The solution

The described problem can be frustrating when one is developing myLib. One has to kill the kernel each time before re-compiling myLib. The solution, which was found and kindly shared to me by ilian (who has very generously reviewed my code and looked into the problem.), is

NOT to manually pre-load myLib with LibraryLoad at first place.

Instead, one may modify the OS environment so Windows can find all the depended libraries and manage them automatically:

SetEnvironment["PATH" -> Environment["PATH"] <> ";" <> "path_to_folder_of_myLib.dll"]
myfunc = LibraryFunctionLoad["libLink.dll", ... ]

Unloading will now be as simple as:

LibraryUnload["libLink.dll"]

After that, if there is no other reference to myLib.dll, it will be editable.

Silvia
  • 27,556
  • 3
  • 84
  • 164
  • Relying on the PATH environment variable is not 100% fool proof. There are ways in which the loader can ignore it. – ihojnicki Feb 10 '21 at 21:59
  • @ihojnicki I'm really quit new to C/C++/Windows API/etc. Is there any references on the topic you would recommend to? Thanks in advance! – Silvia Feb 16 '21 at 15:11
  • @ihojnicki Ah sorry.. By "the topic" I meant the scenario you mentioned in your comment, that is the case setting PATH fails to auto-load/unload dependencies. Could you tell more about that? By no means I was asking for a generic C++/Windows reference. – Silvia Feb 18 '21 at 06:36
  • 1
    The search order reference is here. It is a bit complicated, but the search order depends on the method the application is distributed and what preferences it sets up beforehand. – ihojnicki Feb 18 '21 at 14:10
  • @ihojnicki That is very informative! Thank you! – Silvia Feb 18 '21 at 17:10