KhronosGroup / Vulkan-Hpp

Open-Source Vulkan C++ API
Apache License 2.0
3.12k stars 305 forks source link

DynamicLoader attempts to load the library even if already loaded #1811

Open d235j opened 8 months ago

d235j commented 8 months ago

The DynamicLoader, at https://github.com/KhronosGroup/Vulkan-Hpp/blob/main/snippets/DynamicLoader.hpp#L11, attempts to load the Vulkan Loader library by name regardless of whether is has already been loaded by the system. If the library path is not in the RPATH, this will fail. In many cases, the library will already have been loaded by the system dynamic loader/linker due to it being in the library paths for the executable. There are some attempts to avoid this, but they are ad-hoc and seem to fail for me.

Is there any reason not to use dladdr or similar functionality to try to detect if the library has already been loaded by the system? See https://stackoverflow.com/a/65216532 for details on how this could be implemented.

d235j commented 8 months ago

I'm looking for direction here — should I implement functionality using dlsym/dladdr and the equivalent on Windows to detect if the library already has been loaded? Or would some alternate mechanism be preferred?

theHamsta commented 8 months ago

I'm looking for direction here — should I implement functionality using dlsym/dladdr and the equivalent on Windows to detect if the library already has been loaded? Or would some alternate mechanism be preferred?

I assume you don't have the problem you mentioned on Windows. On Linux, the behavior could probably be changed by adapting the flags passed to dlopen. RTDL_LOCAL might be part of the behavior you're seeing and you could force to load symbols from the library you've already loaded.

This paragraph from the dlopen manpage could also help you control which paths are searched by Vulkan-hpp's dlopen (in addition to LD_LOAD_PATH)


       •  (ELF only) If the calling object (i.e., the shared library or
          executable from which dlopen() is called) contains a DT_RPATH
          tag, and does not contain a DT_RUNPATH tag, then the
          directories listed in the DT_RPATH tag are searched.

Is there any reason why you wouldn't want to use a driver/system provided libvulkan.so.1?

d235j commented 8 months ago

I assume you don't have the problem you mentioned on Windows.

I am experiencing this problem on macOS; I have not tested on Windows yet. This problem will occur whenever the libvulkan libraries are installed in a non-system prefix. If implicit linking is used, the dll should already have been loaded even on Windows.

On Linux, the behavior could probably be changed by adapting the flags passed to dlopen. RTDL_LOCAL might be part of the behavior you're seeing and you could force to load symbols from the library you've already loaded.

Why attempt to dlopen at all if the library has already been loaded by the system? I'm proposing to check if the library has already been loaded, and skip the forced dlopen in that case.

Is there any reason why you wouldn't want to use a driver/system provided libvulkan.so.1?

In some cases the libvulkan.so.1 or equivalent might be installed in a separate prefix, and in this case if the path to the lib directory of that prefix isn't in PATH or RPATH or the equivalent, the library won't be found when the dlopen is attempted. However, if the executable is already linked to that library, it will have already been loaded by the system dynamic linker. Therefore in this case, attempting to load it is unnecessary and may fail.

I'm running into a failure on macOS with Homebrew, which puts libvulkan.dylib in a separate prefix and relies on it being in the executable's library paths to be loaded by the system dynamic linker. But this could happen on any platform.