Skip to content

Commit

Permalink
Wrap __init__ functions of Base submodules in try/catch
Browse files Browse the repository at this point in the history
Prevents them from throwing any InitError exceptions that will not get
handled
  • Loading branch information
jdlangs committed Aug 26, 2015
1 parent 8883f30 commit fe0337e
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 106 deletions.
29 changes: 17 additions & 12 deletions base/gmp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,19 +53,24 @@ _gmp_clear_func = C_NULL
_mpfr_clear_func = C_NULL

function __init__()
if gmp_version().major != GMP_VERSION.major || gmp_bits_per_limb() != GMP_BITS_PER_LIMB
error(string("The dynamically loaded GMP library (version $(gmp_version()) with __gmp_bits_per_limb == $(gmp_bits_per_limb()))\n",
"does not correspond to the compile time version (version $GMP_VERSION with __gmp_bits_per_limb == $GMP_BITS_PER_LIMB).\n",
"Please rebuild Julia."))
end
try
if gmp_version().major != GMP_VERSION.major || gmp_bits_per_limb() != GMP_BITS_PER_LIMB
error(string("The dynamically loaded GMP library (version $(gmp_version()) with __gmp_bits_per_limb == $(gmp_bits_per_limb()))\n",
"does not correspond to the compile time version (version $GMP_VERSION with __gmp_bits_per_limb == $GMP_BITS_PER_LIMB).\n",
"Please rebuild Julia."))
end

global _gmp_clear_func = cglobal((:__gmpz_clear, :libgmp))
global _mpfr_clear_func = cglobal((:mpfr_clear, :libmpfr))
ccall((:__gmp_set_memory_functions, :libgmp), Void,
(Ptr{Void},Ptr{Void},Ptr{Void}),
cglobal(:jl_gc_counted_malloc),
cglobal(:jl_gc_counted_realloc_with_old_size),
cglobal(:jl_gc_counted_free))
global _gmp_clear_func = cglobal((:__gmpz_clear, :libgmp))
global _mpfr_clear_func = cglobal((:mpfr_clear, :libmpfr))
ccall((:__gmp_set_memory_functions, :libgmp), Void,
(Ptr{Void},Ptr{Void},Ptr{Void}),
cglobal(:jl_gc_counted_malloc),
cglobal(:jl_gc_counted_realloc_with_old_size),
cglobal(:jl_gc_counted_free))
catch ex
Base.showerror_nostdio(ex,
"WARNING: Error during initialization of module GMP")
end
end

widen(::Type{Int128}) = BigInt
Expand Down
11 changes: 8 additions & 3 deletions base/linalg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -236,9 +236,14 @@ include("linalg/arpack.jl")
include("linalg/arnoldi.jl")

function __init__()
Base.check_blas()
if Base.blas_vendor() == :mkl
ccall((:MKL_Set_Interface_Layer, Base.libblas_name), Void, (Cint,), USE_BLAS64 ? 1 : 0)
try
Base.check_blas()
if Base.blas_vendor() == :mkl
ccall((:MKL_Set_Interface_Layer, Base.libblas_name), Void, (Cint,), USE_BLAS64 ? 1 : 0)
end
catch ex
Base.showerror_nostdio(ex,
"WARNING: Error during initialization of module LinAlg")
end
end

Expand Down
11 changes: 8 additions & 3 deletions base/mpfr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,14 @@ import Base.GMP: ClongMax, CulongMax, CdoubleMax
import Base.Math.lgamma_r

function __init__()
# set exponent to full range by default
set_emin!(get_emin_min())
set_emax!(get_emax_max())
try
# set exponent to full range by default
set_emin!(get_emin_min())
set_emax!(get_emax_max())
catch ex
Base.showerror_nostdio(ex,
"WARNING: Error during initialization of module MPFR")
end
end

const ROUNDING_MODE = Cint[0]
Expand Down
23 changes: 14 additions & 9 deletions base/pcre.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,20 @@ global JIT_STACK = C_NULL
global MATCH_CONTEXT = C_NULL

function __init__()
JIT_STACK_START_SIZE = 32768
JIT_STACK_MAX_SIZE = 1048576
global JIT_STACK = ccall((:pcre2_jit_stack_create_8, PCRE_LIB), Ptr{Void},
(Cint, Cint, Ptr{Void}),
JIT_STACK_START_SIZE, JIT_STACK_MAX_SIZE, C_NULL)
global MATCH_CONTEXT = ccall((:pcre2_match_context_create_8, PCRE_LIB),
Ptr{Void}, (Ptr{Void},), C_NULL)
ccall((:pcre2_jit_stack_assign_8, PCRE_LIB), Void,
(Ptr{Void}, Ptr{Void}, Ptr{Void}), MATCH_CONTEXT, C_NULL, JIT_STACK)
try
JIT_STACK_START_SIZE = 32768
JIT_STACK_MAX_SIZE = 1048576
global JIT_STACK = ccall((:pcre2_jit_stack_create_8, PCRE_LIB), Ptr{Void},
(Cint, Cint, Ptr{Void}),
JIT_STACK_START_SIZE, JIT_STACK_MAX_SIZE, C_NULL)
global MATCH_CONTEXT = ccall((:pcre2_match_context_create_8, PCRE_LIB),
Ptr{Void}, (Ptr{Void},), C_NULL)
ccall((:pcre2_jit_stack_assign_8, PCRE_LIB), Void,
(Ptr{Void}, Ptr{Void}, Ptr{Void}), MATCH_CONTEXT, C_NULL, JIT_STACK)
catch ex
Base.showerror_nostdio(ex,
"WARNING: Error during initialization of module PCRE")
end
end

# supported options for different use cases
Expand Down
9 changes: 8 additions & 1 deletion base/random.jl
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,14 @@ randjump(r::MersenneTwister, jumps::Integer) = randjump(r, jumps, dSFMT.JPOLY1e2

## initialization

__init__() = srand()
function __init__()
try
srand()
catch ex
Base.showerror_nostdio(ex,
"WARNING: Error during initialization of module Random")
end
end


## make_seed()
Expand Down
11 changes: 11 additions & 0 deletions base/replutil.jl
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,17 @@ function showerror(io::IO, ex::MethodError)
show_method_candidates(io, ex)
end

#Show an error by directly calling jl_printf.
#Useful in Base submodule __init__ functions where STDERR isn't defined yet.
function showerror_nostdio(err, msg::AbstractString)
stderr_stream = ccall(:jl_stderr_stream, Ptr{Void}, ())
ccall(:jl_printf, UInt, (Ptr{Void},Cstring), stderr_stream, msg)
ccall(:jl_printf, UInt, (Ptr{Void},Cstring), stderr_stream, ":\n")
ccall(:jl_static_show, UInt, (Ptr{Void},Ptr{Void}), stderr_stream,
pointer_from_objref(err))
ccall(:jl_printf, UInt, (Ptr{Void},Cstring), stderr_stream, "\n")
end

const UNSHOWN_METHODS = ObjectIdDict(
which(call, Tuple{Type, Vararg{Any}}) => true
)
Expand Down
164 changes: 88 additions & 76 deletions base/sparse/cholmod.jl
Original file line number Diff line number Diff line change
Expand Up @@ -63,94 +63,106 @@ end
const version = VersionNumber(version_array...)

function __init__()
### Check if the linked library is compatible with the Julia code
if Libdl.dlsym(Libdl.dlopen("libcholmod"), :cholmod_version) == C_NULL
hasversion = false
warn("""
CHOLMOD version incompatibility
Julia was compiled with CHOLMOD version $version. It is
currently linked with a version older than 2.1.0. This
might cause Julia to terminate when working with sparse
matrix factorizations, e.g. solving systems of equations
with \\.
It is recommended that you use Julia with a recent version
of CHOLMOD, or download the OS X or generic Linux binaries
from www.julialang.org, which ship with the correct
versions of all dependencies.
""")
else
hasversion = true
tmp = Array(Cint, 3)
ccall((:cholmod_version, :libcholmod), Cint, (Ptr{Cint},), version_array)
ccall((:jl_cholmod_version, :libsuitesparse_wrapper), Cint, (Ptr{Cint},), tmp)
if tmp != version_array
try
### Check if the linked library is compatible with the Julia code
if Libdl.dlsym(Libdl.dlopen("libcholmod"), :cholmod_version) == C_NULL
hasversion = false
warn("""
CHOLMOD version incompatibility
CHOLMOD version incompatibility
Julia was compiled with CHOLMOD version $version. It
is currently linked with a version older than
$(VersionNumber(tmp...)). This might cause Julia to
terminate when working with sparse matrix
factorizations, e.g. solving systems of equations
with \\.
Julia was compiled with CHOLMOD version $version. It is
currently linked with a version older than 2.1.0. This
might cause Julia to terminate when working with sparse
matrix factorizations, e.g. solving systems of equations
with \\.
It is recommended that you use Julia with a recent
version of CHOLMOD, or download the OS X or generic
Linux binary from www.julialang.org, which ship with
the correct versions of all dependencies.
It is recommended that you use Julia with a recent version
of CHOLMOD, or download the OS X or generic Linux binaries
from www.julialang.org, which ship with the correct
versions of all dependencies.
""")
else
hasversion = true
tmp = Array(Cint, 3)
ccall((:cholmod_version, :libcholmod), Cint, (Ptr{Cint},), version_array)
ccall((:jl_cholmod_version, :libsuitesparse_wrapper), Cint, (Ptr{Cint},), tmp)
if tmp != version_array
warn("""
CHOLMOD version incompatibility
Julia was compiled with CHOLMOD version $version. It
is currently linked with a version older than
$(VersionNumber(tmp...)). This might cause Julia to
terminate when working with sparse matrix
factorizations, e.g. solving systems of equations
with \\.
It is recommended that you use Julia with a recent
version of CHOLMOD, or download the OS X or generic
Linux binary from www.julialang.org, which ship with
the correct versions of all dependencies.
""")
end
end
end

intsize = Int(ccall((:jl_cholmod_sizeof_long,:libsuitesparse_wrapper),Csize_t,()))
if intsize != 4length(IndexTypes)
warn("""
intsize = Int(ccall((:jl_cholmod_sizeof_long,:libsuitesparse_wrapper),Csize_t,()))
if intsize != 4length(IndexTypes)
warn("""
CHOLMOD integer size incompatibility
CHOLMOD integer size incompatibility
Julia was compiled with a version of CHOLMOD that
supported $(32length(IndexTypes)) bit integers. It is
currently linked with version that supports $(8intsize)
integers. This might cause Julia to terminate when
working with sparse matrix factorizations, e.g. solving
systems of equations with \\.
Julia was compiled with a version of CHOLMOD that
supported $(32length(IndexTypes)) bit integers. It is
currently linked with version that supports $(8intsize)
integers. This might cause Julia to terminate when
working with sparse matrix factorizations, e.g. solving
systems of equations with \\.
This problem can be fixed by modifying the Julia build
configuration or by downloading the OS X or generic
Linux binary from www.julialang.org, which include
the correct versions of all dependencies.
""")
end
This problem can be fixed by modifying the Julia build
configuration or by downloading the OS X or generic
Linux binary from www.julialang.org, which include
the correct versions of all dependencies.
""")
end

### Initiate CHOLMOD
### The common struct. Controls the type of factorization and keeps pointers
### to temporary memory.
global const commonStruct = fill(0xff, common_size)

global const common_supernodal = convert(Ptr{Cint}, pointer(commonStruct, cholmod_com_offsets[4] + 1))
global const common_final_ll = convert(Ptr{Cint}, pointer(commonStruct, cholmod_com_offsets[7] + 1))
global const common_print = convert(Ptr{Cint}, pointer(commonStruct, cholmod_com_offsets[13] + 1))
global const common_itype = convert(Ptr{Cint}, pointer(commonStruct, cholmod_com_offsets[18] + 1))
global const common_dtype = convert(Ptr{Cint}, pointer(commonStruct, cholmod_com_offsets[19] + 1))
global const common_nmethods = convert(Ptr{Cint}, pointer(commonStruct, cholmod_com_offsets[15] + 1))
global const common_postorder = convert(Ptr{Cint}, pointer(commonStruct, cholmod_com_offsets[17] + 1))

start(commonStruct) # initializes CHOLMOD
set_print_level(commonStruct, 0) # no printing from CHOLMOD by default

# Register gc tracked allocator if CHOLMOD is new enough
if hasversion && version >= v"3.0.0"
cnfg = cglobal((:SuiteSparse_config, :libsuitesparseconfig), Ptr{Void})
unsafe_store!(cnfg, cglobal(:jl_malloc, Ptr{Void}), 1)
unsafe_store!(cnfg, cglobal(:jl_calloc, Ptr{Void}), 2)
unsafe_store!(cnfg, cglobal(:jl_realloc, Ptr{Void}), 3)
unsafe_store!(cnfg, cglobal(:jl_free, Ptr{Void}), 4)
end
### Initiate CHOLMOD
### The common struct. Controls the type of factorization and keeps pointers
### to temporary memory.
global const commonStruct = fill(0xff, common_size)

global const common_supernodal =
convert(Ptr{Cint}, pointer(commonStruct, cholmod_com_offsets[4] + 1))
global const common_final_ll =
convert(Ptr{Cint}, pointer(commonStruct, cholmod_com_offsets[7] + 1))
global const common_print =
convert(Ptr{Cint}, pointer(commonStruct, cholmod_com_offsets[13] + 1))
global const common_itype =
convert(Ptr{Cint}, pointer(commonStruct, cholmod_com_offsets[18] + 1))
global const common_dtype =
convert(Ptr{Cint}, pointer(commonStruct, cholmod_com_offsets[19] + 1))
global const common_nmethods =
convert(Ptr{Cint}, pointer(commonStruct, cholmod_com_offsets[15] + 1))
global const common_postorder =
convert(Ptr{Cint}, pointer(commonStruct, cholmod_com_offsets[17] + 1))

start(commonStruct) # initializes CHOLMOD
set_print_level(commonStruct, 0) # no printing from CHOLMOD by default

# Register gc tracked allocator if CHOLMOD is new enough
if hasversion && version >= v"3.0.0"
cnfg = cglobal((:SuiteSparse_config, :libsuitesparseconfig), Ptr{Void})
unsafe_store!(cnfg, cglobal(:jl_malloc, Ptr{Void}), 1)
unsafe_store!(cnfg, cglobal(:jl_calloc, Ptr{Void}), 2)
unsafe_store!(cnfg, cglobal(:jl_realloc, Ptr{Void}), 3)
unsafe_store!(cnfg, cglobal(:jl_free, Ptr{Void}), 4)
end

catch ex
Base.showerror_nostdio(ex,
"WARNING: Error during initialization of module CHOLMOD")
end
end

function set_print_level(cm::Array{UInt8}, lev::Integer)
Expand Down
4 changes: 2 additions & 2 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -673,7 +673,7 @@ end
@test names(Module(:anonymous, false), true, true) == [:anonymous]

# exception from __init__()
let t =
let didthrow =
try
include_string(
"""
Expand All @@ -687,7 +687,7 @@ let t =
@test isa(ex.error, InitError)
true
end
@test t
@test didthrow
end

# issue #7307
Expand Down

0 comments on commit fe0337e

Please sign in to comment.