This is very helpful when we want a specific library to be dlopen-ed with different flags.
Diff Detail
Event Timeline
What's the expected use of the new API? Do we provide a portable way to dlopen() something with special flags?
include/llvm/Support/DynamicLibrary.h | ||
---|---|---|
77 | Please add some doxygen comments for the new function, with a description of what 'handle' is. | |
lib/Support/DynamicLibrary.cpp | ||
71 | You won't have the symbols mutex held here if you call this method directly. Is that fine? I'm not really sure what that mutex protects (seems like more than just the ExplicitSymbols map).. |
Addressed comments; removed old copy-paste code (we shouldn't dlclose if the handle is already registered).
lib/Support/DynamicLibrary.cpp | ||
---|---|---|
52 | This change is a bit out-of-scope for your patch, perhaps? A separate review may be worthwhile to figure out if we really need two layers of locking (one implicit in the ManagedStatic, another with the SymbolsMutex). | |
71 | Is there a double-lock scenario here? getPermanentLibrary() would lock, then addPermanentLibrary() would lock again? | |
77–92 | There is a leak here when this function is called by getPermanentLibrary(). |
This is somewhat related to something I've been trying to get reviewed here: https://reviews.llvm.org/D30107
I think there is a serious problem with DynamicLibrary::getPermanentLibrary on Windows.
I believe D30107 handles the memory leak as well.
lib/Support/DynamicLibrary.cpp | ||
---|---|---|
52 | It seems ManagedStaticBase::RegisterManagedStatic does some locking, but I guess it's just a one-time thing. At any rate, I'd suggest that the ManagedStatic change be left for a different commit, because it doesn't seem like a required change to make the addPermanentLibrary API work. | |
71 | Maybe std::lock_guard would be a good solution. I.e add an API to grab a std::lock_guard from the DynamicLibrary class, then require the lock_guard to be moved into addPermanentLibrary. |
- Split the OpenedHandles leak fix D30178;
- Add more fine-grained locking, avoiding the double locking issue;
- Add more information if an error occurred.
lib/Support/DynamicLibrary.cpp | ||
---|---|---|
71 | It seems the locking should protect only dlerror. I decided to lock around dlopen/dlclose because I found some bug reports of them not being thread safe on some implementations. |
- Can you add a private addPermanentLibraryWithLock(void *handle, SmartScopedLock &) method? You can then use this from {add,get}PermanentLibrary, to avoid acquiring the mutex multiple times. That kills the benign race where two clients try to add the same dylib in parallel calls to getPermanentLibrary.
- Could you rebase this patch on D30178 once it's updated?
As a general note (unrelated to this patch), I'm a bit unhappy with how there is no clear thing that SymbolMutex guards, but we don't have to fix that here.
Typo.
It seems that we could even avoid using a private member but local static functions. Let me know I should remove the static private method.
Thanks, lgtm. There is some overlap with D30107, but it looks like it'll need to be rebased on this patch anyway.
FWIW applying D30107 before this would mean addPermanentLibraryWithLock would no longer be necessary.
Otherwise, doesn't this make it impossible to get symbols from an already loaded library unless all libs are searched?
That is, assuming "libSomething" is already loaded:
DynamicLibrary DL = DynamicLibrary::addPermanentLibrary(dlopen("libSomething"));
DL.getAddressOfSymbol("func"); // Fails
In this case how is it possible to get symbols from "libSomething" without searching every loaded module?
On Windows this is a larger issue as it can cache all loaded libraries.
Yeah, I didn't mean to create more work for you in D30107! The 'with-lock' helper seemed like the right solution here, and I have still have some questions/comments about D30107, hence the lgtm.
Otherwise, doesn't this make it impossible to get symbols from an already loaded library unless all libs are searched?
That is, assuming "libSomething" is already loaded:
DynamicLibrary DL = DynamicLibrary::addPermanentLibrary(dlopen("libSomething"));
DL.getAddressOfSymbol("func"); // Fails
In that case, the client could check if DL is invalid, and then simply construct "DynamicLibrary(dlopen'd-value)". Perhaps the API could be cleaned up if we returned "Expected<DynamicLibrary>" from the static constructors, and got rid of the isValid method.
In this case how is it possible to get symbols from "libSomething" without searching every loaded module?
See above.
Yeah, I didn't mean to create more work for you in D30107! The 'with-lock' helper seemed like the right solution here, and I have still have some questions/comments about D30107, hence the lgtm.
It shouldn't be that much work integrating it...was just saying as the addPermanentLibraryWithLock is a bit ugly and would go away anyway.
Otherwise, doesn't this make it impossible to get symbols from an already loaded library unless all libs are searched?
That is, assuming "libSomething" is already loaded:
DynamicLibrary DL = DynamicLibrary::addPermanentLibrary(dlopen("libSomething"));
DL.getAddressOfSymbol("func"); // FailsIn that case, the client could check if DL is invalid, and then simply construct "DynamicLibrary(dlopen'd-value)". Perhaps the API could be cleaned up if we returned "Expected<DynamicLibrary>" from the static constructors, and got rid of the isValid method.
Why not just have addPermanentLibrary take an optional bool* indicating whether it was already loaded or not?
Whether it was loaded or not seems orthogonal to the task of adding a permanent library/getting a platform independent way to do lookups on it?
Either way if D30107 is to be expanded per your comments this could also be discussed then rather than holding this up.
If you mean 'bool &', then your suggestion is actually very similar to mine (return 'Expected<DynamicLibrary>').
I agree that it's something we could improve, but think that it's something we can address as a follow-up (i.e I don't think the addPermanentLibrary API is broken as-is).
Either way if D30107 is to be expanded per your comments this could also be discussed then rather than holding this up.
Sure.
Reverted in r296463.
The module is loaded twice for clang static analyzer plugins.
- clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
- clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
Please consider such a case, or tweak clang plugins.
FYI, clang's plugin test can be enabled with CLANG_BUILD_EXAMPLES=ON
Please add some doxygen comments for the new function, with a description of what 'handle' is.