Skip to content
Draft
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions base/Base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -250,15 +250,15 @@ include("missing.jl")
# version
include("version.jl")

# Logging
include("logging.jl")
using .CoreLogging

# system & environment
include("sysinfo.jl")
include("libc.jl")
using .Libc: getpid, gethostname, time

# Logging
include("logging.jl")
using .CoreLogging

# Concurrency
include("linked_list.jl")
include("condition.jl")
Expand Down
56 changes: 54 additions & 2 deletions base/libdl.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Base.DL_LOAD_PATH

export DL_LOAD_PATH, RTLD_DEEPBIND, RTLD_FIRST, RTLD_GLOBAL, RTLD_LAZY, RTLD_LOCAL,
RTLD_NODELETE, RTLD_NOLOAD, RTLD_NOW, dlclose, dlopen, dlopen_e, dlsym, dlsym_e,
dlpath, find_library, dlext, dllist
dlpath, find_library, dlext, dllist, check_dllist

"""
DL_LOAD_PATH
Expand Down Expand Up @@ -76,6 +76,57 @@ function dlsym_e(hnd::Ptr, s::Union{Symbol,AbstractString})
return something(dlsym(hnd, s; throw_error=false), C_NULL)
end

if Sys.isapple()
const dlpattern = r"^([^.]+).*\.dylib$"
elseif Sys.iswindows()
const dlpattern = r"^(.+)\.dll$"
else
#assume Sys.islinux, or similar
const dlpattern = r"^(.+?)\.so(?:\..*)?$"
end

const _dlname_cache = Dict{String, SubString{String}}()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not thread-safe and goes against #41602

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the comment; it should be thread-safe now (without a performance regression).


"""
dlname(fullpath::String)

Returns the name of the library.
"""
function dlname(fullpath::String)::SubString{String}
cache = get(_dlname_cache, fullpath, "")
cache != "" && return cache
bn = basename(fullpath)
m = match(dlpattern, bn)
ret = isnothing(m) ? bn : m.captures[1]
_dlname_cache[fullpath] = ret
return ret
end

"""
check_dllist()

Check wheather the same shared library is loaded from two different files.
The `warnings` determines if the warnings are printed to the console.
"""
function check_dllist()
fullpaths = dllist()
names = dlname.(fullpaths)
perm = sortperm(names)
dlabspath(x) = isfile(x) ? abspath(realpath(x)) : x
for i in 1:length(names)-1
p1, p2 = perm[i], perm[i+1]
if names[p1] == names[p2]
if dlabspath(fullpaths[p1]) == dlabspath(fullpaths[p2])
continue
end
@warn """Detected possible duplicate library loaded: $(names[p1])
This may lead to unexpected behavior!
$(fullpaths[p1])
$(fullpaths[p2])""" maxlog=1
end
end
end

"""
dlopen(libfile::AbstractString [, flags::Integer]; throw_error:Bool = true)

Expand Down Expand Up @@ -113,11 +164,12 @@ function dlopen end
dlopen(s::Symbol, flags::Integer = RTLD_LAZY | RTLD_DEEPBIND; kwargs...) =
dlopen(string(s), flags; kwargs...)

function dlopen(s::AbstractString, flags::Integer = RTLD_LAZY | RTLD_DEEPBIND; throw_error::Bool = true)
function dlopen(s::AbstractString, flags::Integer = RTLD_LAZY | RTLD_DEEPBIND; throw_error::Bool = true, warnings::Bool = true)
ret = ccall(:jl_load_dynamic_library, Ptr{Cvoid}, (Cstring,UInt32,Cint), s, flags, Cint(throw_error))
if ret == C_NULL
return nothing
end
warnings && check_dllist()
return ret
end

Expand Down
4 changes: 2 additions & 2 deletions stdlib/Libdl/src/Libdl.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ module Libdl
# Just re-export Base.Libc.Libdl:
export DL_LOAD_PATH, RTLD_DEEPBIND, RTLD_FIRST, RTLD_GLOBAL, RTLD_LAZY, RTLD_LOCAL,
RTLD_NODELETE, RTLD_NOLOAD, RTLD_NOW, dlclose, dlopen, dlopen_e, dlsym, dlsym_e,
dlpath, find_library, dlext, dllist
dlpath, find_library, dlext, dllist, check_dllist

import Base.Libc.Libdl: DL_LOAD_PATH, RTLD_DEEPBIND, RTLD_FIRST, RTLD_GLOBAL, RTLD_LAZY, RTLD_LOCAL,
RTLD_NODELETE, RTLD_NOLOAD, RTLD_NOW, dlclose, dlopen, dlopen_e, dlsym, dlsym_e,
dlpath, find_library, dlext, dllist
dlpath, find_library, dlext, dllist, check_dllist

end # module