Rework dlsym(), dlopen(), jl_dlsym() and jl_load_dynamic_library() APIs#28888
Rework dlsym(), dlopen(), jl_dlsym() and jl_load_dynamic_library() APIs#28888staticfloat merged 8 commits intomasterfrom
dlsym(), dlopen(), jl_dlsym() and jl_load_dynamic_library() APIs#28888Conversation
Libdl.dlsym() and jl_dlsym().Libdl.dlsym(), Libdl.dlopen(), jl_dlsym() and jl_load_dynamic_library() APIs
Libdl.dlsym(), Libdl.dlopen(), jl_dlsym() and jl_load_dynamic_library() APIsdlsym(), dlopen(), jl_dlsym() and jl_load_dynamic_library() APIs
src/dlload.c
Outdated
| /* Next, check for errors. On Windows, a NULL pointer means the symbol | ||
| * was not found. On everything else, we can have NULL symbols, so we check | ||
| * for non-NULL returns from dlerror(). */ | ||
| const char * err = jl_dlerror(); |
There was a problem hiding this comment.
Not a big deal, but we don't really need to do this work on windows unless we know there's a failure.
There was a problem hiding this comment.
Yes, I originally had it split out but it was enough extra code that I liked it better this way. Optimizing for the programmer, not the program, I suppose.
src/dlload.c
Outdated
| { | ||
| #ifdef _OS_WINDOWS_ | ||
| CHAR reason[256]; | ||
| static CHAR reason[256]; |
There was a problem hiding this comment.
This makes this no longer thread safe, which is probably fine if we only do it in the error case, but if we do it in the success case as well, I'm worried the error message will get overwritten by the success of a different thread.
There was a problem hiding this comment.
I've fixed this by slapping __thread in front of it.
There was a problem hiding this comment.
Unfortunately, we can't assume that that's universally available.
There was a problem hiding this comment.
I was taking my inspiration from support/dirname.c. Can I do:
# if !defined(_COMPILER_MICROSOFT_)
static __thread char reason[256];
# else
static __declspec(thread) char reason[256];
# endif
There was a problem hiding this comment.
If you really need to, you can use our own tls... There're already platform dependent members in there so it shouldn't be a huge problem even though it won't look as nice and will certainly needs cross references in the comments.
There was a problem hiding this comment.
Because there seems to be some disagreement within the Julia codebase, I have taken the liberty of adding #define JL_THREAD_LOCAL to julia.h which emulates what is held within src/support/dirname.c. If this shouldn't be done (and we should instead use the more complex TLS implementation in src/threading.c), it's probably best to transition both jl_dlerror() and dirname() to use that new stuff instead.
|
Do you want to separate out the |
src/ccall.cpp
Outdated
| }; | ||
| #define is_libjulia_func(name) _is_libjulia_func((uintptr_t)&(name), #name) | ||
|
|
||
| static auto ptls_getter = &jl_get_ptls_states; |
There was a problem hiding this comment.
Why the change? This completely defeated the purpose of the old code, which is clearly stated in the comment..............
There was a problem hiding this comment.
It's because I have been dealing with the dynamic (runtime) linker too much, so when it said "can cause linker issues" I naively thought that meant at runtime when the symbol actually gets used. I didn't realize this caused issues at compile-time link. :P
There was a problem hiding this comment.
You are welcome to change the comment in whichever way you want so that anyone that have read that comment won't change this code without testing the compiler configure combination again.....
|
With regards to splitting out the That's okay though; because BP doesn't strictly need this; the |
d517d3a to
cac021c
Compare
^^ Due to a missing semicolon. Impressive. |
119d60d to
29398e6
Compare
|
Huzzah! We are passing all tests. If I could get a thumbs up or thumbs down on the API exposed here, then we can make the final decision. I have purposefully not put in deprecation warnings for the |
|
Ok by me. @yuyichao ? |
yuyichao
left a comment
There was a problem hiding this comment.
LGTM. The ccall ptls getter lookup is correct but is just very confusing though....
| // on some configurations (e.g. AArch64 + -Bsymbolic-functions), so we guard the | ||
| // `&jl_get_ptls_states` within this `#ifdef` guard, and use a more roundabout | ||
| // method involving `jl_dlsym()` on Linux platforms instead. | ||
| #ifdef _OS_LINUX_ |
There was a problem hiding this comment.
This actually makes the static useless. The performance isn't super critical here so if you want to just get rid of the static that's fine. Otherwise you can write it as.
static auto ptls_getter = [] {
#ifdef _OS_LINUX_
jl_ptls_t (*p)(void);
jl_dlsym(....);
return p;
#else
return jl_get_ptls_states;
#endif
}();There was a problem hiding this comment.
Wow, that's available even all the way back to GCC 4.8.5. I'm amazed. And yes, you're right this completely defeats static, but I like this fancy lambda initialization. I'm gonna go with that since compiler support is good enough.
There was a problem hiding this comment.
This is standard C++11 feature and we require C++11 so that shouldn't be very surprising......
| { | ||
| #ifdef _OS_WINDOWS_ | ||
| CHAR reason[256]; | ||
| static JL_THREAD_LOCAL CHAR reason[256]; |
There was a problem hiding this comment.
No change needed but note that the "more complex" tls implementation we have should actually be simpler and faster.
There was a problem hiding this comment.
Simpler than just writing JL_THREAD_LOCAL? How would I use it?
There was a problem hiding this comment.
Simpler in the code generated that is.
* Remove `jl_dlsym_e()` to instead be rolled into `jl_dlsym()` with a `throw_err` parameter, similar to `jl_load_dynamic_library()`. * Fix #28881 by having `Libdl.dlsym()` return `nothing` on missing symbol, rather than `C_NULL`.
This changes `dlopen()` to mimic `dlsym()` so that a negative result returns `nothing`. While not necessary in the same way as in the `dlsym()` case (there are no valid `NULL` `dlopen()` results) the consistency is worth it.
|
When this goes green, I'm going to merge. Thanks for the shepherding, Keno and Yichao! |
|
I'm not sure that I like the new API any better than the old, but I suppose that's not very helpful feedback. |
|
Feel free to suggest a better API in a new PR. I’m going to sit with his one for now. |
|
The behavioral change of returning |
|
Seems like the correct place to me. |
Remove
jl_dlsym_e()to instead be rolled intojl_dlsym()with athrow_errparameter, similar tojl_load_dynamic_library_().Fix
jl_dlsymincorrectly assumes a NULL return is an error #28881 by havingLibdl.dlsym()returnnothingon missing symbol, rather thanC_NULL.Change
dlopen()to mimicdlsym()so that a negative result returnsnothing. While not necessary in the same way as in thedlsym()case (there are no validNULLdlopen()results) the consistency is worth it.