-
Notifications
You must be signed in to change notification settings - Fork 154
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Debug build DLL hangs on LoadLibrary (Windows) #1298
Comments
Some update. I've made some progress in investigating the DLL loading issue and wanted to share the latest findings. Using Process Monitor alongside Dependency Walker, I've confirmed that there are no issues with dependency resolution. All necessary DLLs are found, opened, and then closed without any errors, just before the hang occurs. I used gflags and WinDbg to analyze the call stack at the point of the hang. The last output line before the hang is:
The call stack suggests a hang related to a lock, specifically involving C++ standard library mutex operations. This indicates that the issue is happening during the dynamic initialization of the DLL:
As my code is extremely simple and doesn't contain any global objects, this indicates that the hang is likely occurring within the AdaptiveCpp runtime initialization. I am using Release build of AdaptiveCpp. I plan to build AdaptiveCpp with Debug configuration to include debug symbols. This will probably provide greater visibility into the library's initialization code during the DLL loading process. |
This page has a lot of good information on what you are allowed to do in DllMain: https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices Try Application Verifier, it might add more information, but it sounds like a loader lock problem. |
Thank you for the information. However, I have no DllMain. The code I provided is a full reproducer. Providing DllMain in a Windows DLL is not strictly necessary. The compiler and linker automatically generate an entry point for the DLL. However, I tried to add DllMain for debug purposes, and this didn't help, breakpoint in this function doesn't hit, which indicates that the problem may occur in other dependency libraries. |
Hi @blinkfrog. I'm not really a Windows person so I'm afraid I cannot help much. I am just curious, you said the hang occurs if you remove the Your reproducer is missing a |
Hi @illuhad. No, it's the opposite: hang occurs only when As for missing |
Are there any globals (or static data structures) that are calling OS code in the library? Those get initialized and code run in them at load. I can't tell you how many times I have been burnt by this particular issue. |
That's interesting. I would not expect any additional libraries being loaded just for a
No, this is incorrect. Buffers have their own synchronization rules, so if you were using buffers they might block in their destructor. But for the queue itself, this is not the case. From https://registry.khronos.org/SYCL/specs/sycl-2020/html/sycl-2020.html#sec:interface.queue.class
Queue destructor does not block. Normally this is not an issue, if the task does not have any observable side effect, as in your case. However, problems can arise if there is also no synchronization before exiting |
Almost all of the runtime is initialized "at first use", so loading the runtime itself should not be an issue. What it does do however which departs from that pattern is that it registers the kernels that are contained in the binary with the kernel cache using constructors of global objects. I'm not sure to what extent this process includes OS functions in the call graph. In principle, it is not complex logic. It might check some environment variables for user settings that it is affected by. |
Yes, it happens for both CUDA and OpenMP backends. Just have tried also this mixed variant - compiled for CUDA and forced to run on OpenMP, but result is the same - it hangs. From the last lines of the call stack I only can conclude that the hang occurs during the dynamic initialization of global objects. The lock might be part of the initialization of a global or static object, possibly a singleton.
Thanks, this is very useful to know (although I never use SYCL without buffers and I usually work with accessors that way so I don't need to call |
Can you try commenting out this line here? |
Sure! After commenting this line out, my test app loads dll fine now without hanging on LoadLibrary. |
Some update regarding this issue (using original unmodified AdaptiveCpp). The hang occurs not only when loading the DLL but also when starting an executable built in Debug mode. The executable hangs at the same point – acquiring a mutex lock, which suggests a common underlying problem. I have a questions. In my current setup, the Debug build of my program uses the AdaptiveCpp runtime built in Release configuration. Could this be a potential cause of the hang issue? Is it generally advisable or acceptable to use a Release build of AdaptiveCpp with a Debug build of a program? I also would like to know if such a configuration (Debug program with Release AdaptiveCpp runtime) is commonly used or tested on Linux. Thank you for your time and assistance. |
Hi, this is not systematically tested, but I remember having occasionally used such configurations on Linux when changing build types. I am not aware of any issues nor why this could cause problems. But I don't know about Windows (are there ABI changes on Windows when switching between debug and release builds?). |
Jup, don't mix Debug and Release on windows, they have different abi and when linking normally (I.e. not at runtime), you will be notified about this by erroring out with "iterator level x in file X doesn't match level y in file Y" |
Thank you very much. I am new to building opensource programs from source, and using cmake in overall. Could you please suggest a proper way to build and install debug version of llvm and AdaptiveCpp in case when I need to have both Debug and Release versions installed? Should I install them into a different directories, or this isn't needed - may be binaries will have |
Is Debug build of LLVM required for debug build of AdaptiveCpp? I can't build Debug LLVM: I get this error: |
Closing the issue as it is obviously because of mixing Release build of AdaptiveCpp/Clang and Debug build of binaries I build. I should use Debug build of Clang which I can't compile :( and AdaptiveCpp for debug purposes. |
I'm encountering an issue where a DLL built in Debug configuration hangs when loaded using LoadLibrary. Dependency Walker also freezes when attempting to load the DLL. This issue does not occur in Release mode.
The hang occurs during the DLL loading process, specifically when using the SYCL parallel_for construct. Removing this construct allows the DLL to load correctly.
Minimal Reproducible Example:
This simple DLL hangs on load in Debug mode.
Build:
Using command line:
python "c:/adaptivecpp/bin/acpp" -g -D_DEBUG -shared -o dynamiclib.dll dynamiclib.cpp --acpp-targets="omp" -D_MT -lmsvcrtd -Xlinker /NODEFAULTLIB:libcmt
Using cmake:
CMakeLists.txt:
cmake .. -G Ninja -DCMAKE_C_COMPILER=clang.exe -DCMAKE_CXX_COMPILER=clang++.exe -DCMAKE_BUILD_TYPE=Debug
ninja
Trying to load DLL:
Dependency Walker also freezes while trying to load this DLL.
Any insights or suggestions would be greatly appreciated.
The text was updated successfully, but these errors were encountered: