From 7165821b9e697316086ab5287914b2c4c532d928 Mon Sep 17 00:00:00 2001 From: Octogonapus Date: Fri, 4 Aug 2023 12:38:04 -0400 Subject: [PATCH] Fix Crash due to Duplicate Initialization of System (#91) --- Project.toml | 2 +- src/CameraList.jl | 2 +- src/Spinnaker.jl | 109 ++++++++++++++++++++++++---------------------- test/runtests.jl | 6 +++ 4 files changed, 66 insertions(+), 53 deletions(-) diff --git a/Project.toml b/Project.toml index 525b2bc..954ded5 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "Spinnaker" uuid = "8e0d2ad3-56b8-53f3-8036-54b674872bef" -version = "1.1.1" +version = "1.1.2" [deps] FixedPointNumbers = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" diff --git a/src/CameraList.jl b/src/CameraList.jl index f67d258..c04c360 100644 --- a/src/CameraList.jl +++ b/src/CameraList.jl @@ -15,7 +15,7 @@ mutable struct CameraList handle::spinCameraList function CameraList() - system_initialized || init() + init() hcamlist_ref = Ref(spinCameraList(C_NULL)) spinCameraListCreateEmpty(hcamlist_ref) @assert hcamlist_ref[] != C_NULL diff --git a/src/Spinnaker.jl b/src/Spinnaker.jl index 2e46483..c3ac85b 100644 --- a/src/Spinnaker.jl +++ b/src/Spinnaker.jl @@ -54,64 +54,71 @@ include("Nodes.jl") get_bool_env(name::String; default::String="false") = lowercase(Base.get(ENV, name, default)) in ("t", "true", "y", "yes", "1") -system_initialized = false +const _system_initialized = Ref(false) +const _init_lock = ReentrantLock() # Create a System object at runtime function init() - if haskey(ENV, "JULIA_SPINNAKER_MANUAL_INIT") - @warn """ - The environment variable `JULIA_SPINNAKER_MANUAL_INIT` is deprecated. - Spinnaker is initialized during first CameraList usage""" maxlog=1 - end - @static if Sys.iswindows() - paths = [joinpath(ENV["ProgramFiles"], "Point Grey Research", "Spinnaker", "bin", "vs2015")] - libspinnaker = "SpinnakerC_v140.dll" - libspinvideo = "" - elseif Sys.islinux() - paths = ["/usr/lib" "/opt/spinnaker/lib"] - libspinnaker = "libSpinnaker_C.so" - libspinvideo = "libSpinVideo_C.so" - elseif Sys.isapple() - paths = ["/usr/local/lib"] - libspinnaker = "libSpinnaker_C.dylib" - libspinvideo = "libSpinVideo_C.dylib" - else - error("Spinnaker SDK is only supported on Linux, Windows and MacOS platforms") - end - libSpinnaker_C_path = "" - libSpinVideo_C_path = "" - for path in paths - libSpinnaker_C_path = joinpath(path, libspinnaker) - libSpinVideo_C_path = joinpath(path, libspinvideo) - if isfile(libSpinnaker_C_path) && isfile(libSpinVideo_C_path) - libSpinnaker_C[] = libSpinnaker_C_path - libSpinVideo_C[] = libSpinVideo_C_path + lock(_init_lock) do + if _system_initialized[] + return end - end - if libSpinnaker_C[] == "" || libSpinVideo_C[] == "" - error("Spinnaker SDK cannot be found.") - end - try - libSpinnaker_C_handle = dlopen(libSpinnaker_C[]) - !Sys.iswindows() && (libSpinVideo_C_handle = dlopen(libSpinVideo_C[])) - catch - @error "Spinnaker SDK cannot be dlopen-ed" - rethrow() - end - try - global spinsys = System() - catch - bt = catch_backtrace() - @error "Spinnaker SDK loaded but Spinnaker.jl failed to initialize" - if !haskey(ENV, "FLIR_GENTL64_CTI") - @warn "The environment is missing the variable `FLIR_GENTL64_CTI`, which may be the cause of this error. Check that it is set to the path to `FLIR_GenTL.cti` (e.g. `/opt/spinnaker/lib/flir-gentl/FLIR_GenTL.cti`)." - elseif !endswith(ENV["FLIR_GENTL64_CTI"], "FLIR_GenTL.cti") - @warn "The environment has the variable `FLIR_GENTL64_CTI`, but it does not point to `FLIR_GenTL.cti`, which may be the cause of this error. Check that it is set to the path to `FLIR_GenTL.cti` (e.g. `/opt/spinnaker/lib/flir-gentl/FLIR_GenTL.cti`)." + if haskey(ENV, "JULIA_SPINNAKER_MANUAL_INIT") + @warn """ + The environment variable `JULIA_SPINNAKER_MANUAL_INIT` is deprecated. + Spinnaker is initialized during first CameraList usage""" maxlog=1 + end + @static if Sys.iswindows() + paths = [joinpath(ENV["ProgramFiles"], "Point Grey Research", "Spinnaker", "bin", "vs2015")] + libspinnaker = "SpinnakerC_v140.dll" + libspinvideo = "" + elseif Sys.islinux() + paths = ["/usr/lib" "/opt/spinnaker/lib"] + libspinnaker = "libSpinnaker_C.so" + libspinvideo = "libSpinVideo_C.so" + elseif Sys.isapple() + paths = ["/usr/local/lib"] + libspinnaker = "libSpinnaker_C.dylib" + libspinvideo = "libSpinVideo_C.dylib" + else + error("Spinnaker SDK is only supported on Linux, Windows and MacOS platforms") + end + libSpinnaker_C_path = "" + libSpinVideo_C_path = "" + for path in paths + libSpinnaker_C_path = joinpath(path, libspinnaker) + libSpinVideo_C_path = joinpath(path, libspinvideo) + if isfile(libSpinnaker_C_path) && isfile(libSpinVideo_C_path) + libSpinnaker_C[] = libSpinnaker_C_path + libSpinVideo_C[] = libSpinVideo_C_path + end + end + + if libSpinnaker_C[] == "" || libSpinVideo_C[] == "" + error("Spinnaker SDK cannot be found.") + end + try + libSpinnaker_C_handle = dlopen(libSpinnaker_C[]) + !Sys.iswindows() && (libSpinVideo_C_handle = dlopen(libSpinVideo_C[])) + catch + @error "Spinnaker SDK cannot be dlopen-ed" + rethrow() + end + try + global spinsys = System() + catch + bt = catch_backtrace() + @error "Spinnaker SDK loaded but Spinnaker.jl failed to initialize" + if !haskey(ENV, "FLIR_GENTL64_CTI") + @warn "The environment is missing the variable `FLIR_GENTL64_CTI`, which may be the cause of this error. Check that it is set to the path to `FLIR_GenTL.cti` (e.g. `/opt/spinnaker/lib/flir-gentl/FLIR_GenTL.cti`)." + elseif !endswith(ENV["FLIR_GENTL64_CTI"], "FLIR_GenTL.cti") + @warn "The environment has the variable `FLIR_GENTL64_CTI`, but it does not point to `FLIR_GenTL.cti`, which may be the cause of this error. Check that it is set to the path to `FLIR_GenTL.cti` (e.g. `/opt/spinnaker/lib/flir-gentl/FLIR_GenTL.cti`)." + end + rethrow() end - rethrow() + _system_initialized[] = true end - system_initialized = true end end # module diff --git a/test/runtests.jl b/test/runtests.jl index 70d65f3..de86494 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -54,5 +54,11 @@ else end end end + + @testset "#90: duplicate initialization crash" begin + CameraList() + CameraList() + GC.gc(true) + end end end