Make error handling for loading shared libraries not silently discard errors

This commit is contained in:
William Venner 2022-01-03 01:10:35 +00:00
parent 20108136d2
commit e20834fbeb
5 changed files with 101 additions and 46 deletions

2
Cargo.lock generated
View File

@ -135,7 +135,7 @@ dependencies = [
[[package]] [[package]]
name = "gmod" name = "gmod"
version = "10.2.2" version = "11.0.0"
dependencies = [ dependencies = [
"cfg_table 1.0.0", "cfg_table 1.0.0",
"cstr", "cstr",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "gmod" name = "gmod"
version = "10.2.2" version = "11.0.0"
authors = ["William Venner <william@venner.io>"] authors = ["William Venner <william@venner.io>"]
edition = "2018" edition = "2018"
license = "MIT" license = "MIT"

View File

@ -80,5 +80,5 @@ pub fn restore_stdout() {
let _ = join_handle.join(); let _ = join_handle.join();
} }
std::io::set_output_capture(None); std::io::set_output_capture(None); // TODO fix side effect
} }

View File

@ -98,7 +98,10 @@ pub fn is_x86_64() -> bool {
#[macro_export] #[macro_export]
macro_rules! open_library_raw { macro_rules! open_library_raw {
($($path:literal),+) => { ($($path:literal),+) => {
$crate::libloading::Library::new(concat!($($path),+)).map(|lib| (lib, concat!($($path),+))) match $crate::libloading::Library::new(concat!($($path),+)) {
Ok(lib) => Ok((lib, concat!($($path),+))),
Err(err) => Err((err, concat!($($path),+)))
}
} }
} }
@ -119,28 +122,36 @@ macro_rules! open_library_srv {
} }
#[cfg(all(target_os = "windows", target_pointer_width = "64"))] { #[cfg(all(target_os = "windows", target_pointer_width = "64"))] {
$crate::__private__gmod_rs__try_chained_open! {
$crate::open_library_raw!("bin/win64/", $name, ".dll") $crate::open_library_raw!("bin/win64/", $name, ".dll")
} }
}
#[cfg(all(target_os = "windows", target_pointer_width = "32"))] { #[cfg(all(target_os = "windows", target_pointer_width = "32"))] {
$crate::open_library_raw!("bin/", $name, ".dll") $crate::__private__gmod_rs__try_chained_open! {
.or_else(|_| $crate::open_library_raw!("garrysmod/bin/", $name, ".dll")) $crate::open_library_raw!("bin/", $name, ".dll"),
$crate::open_library_raw!("garrysmod/bin/", $name, ".dll")
}
} }
#[cfg(all(target_os = "linux", target_pointer_width = "64"))] { #[cfg(all(target_os = "linux", target_pointer_width = "64"))] {
$crate::open_library_raw!("bin/linux64/", $name, ".so") $crate::__private__gmod_rs__try_chained_open! {
.or_else(|_| $crate::open_library_raw!("bin/linux64/lib", $name, ".so")) $crate::open_library_raw!("bin/linux64/", $name, ".so"),
$crate::open_library_raw!("bin/linux64/lib", $name, ".so")
}
} }
#[cfg(all(target_os = "linux", target_pointer_width = "32"))] { #[cfg(all(target_os = "linux", target_pointer_width = "32"))] {
$crate::open_library_raw!("bin/linux32/", $name, ".so") $crate::__private__gmod_rs__try_chained_open! {
.or_else(|_| $crate::open_library_raw!("bin/linux32/lib", $name, ".so")) $crate::open_library_raw!("bin/linux32/", $name, ".so"),
.or_else(|_| $crate::open_library_raw!("bin/", $name, "_srv.so")) $crate::open_library_raw!("bin/linux32/lib", $name, ".so"),
.or_else(|_| $crate::open_library_raw!("bin/lib", $name, "_srv.so")) $crate::open_library_raw!("bin/", $name, "_srv.so"),
.or_else(|_| $crate::open_library_raw!("garrysmod/bin/", $name, "_srv.so")) $crate::open_library_raw!("bin/lib", $name, "_srv.so"),
.or_else(|_| $crate::open_library_raw!("garrysmod/bin/lib", $name, "_srv.so")) $crate::open_library_raw!("garrysmod/bin/", $name, "_srv.so"),
.or_else(|_| $crate::open_library_raw!("bin/", $name, ".so")) $crate::open_library_raw!("garrysmod/bin/lib", $name, "_srv.so"),
.or_else(|_| $crate::open_library_raw!("bin/lib", $name, ".so")) $crate::open_library_raw!("bin/", $name, ".so"),
.or_else(|_| $crate::open_library_raw!("garrysmod/bin/", $name, ".so")) $crate::open_library_raw!("bin/lib", $name, ".so"),
.or_else(|_| $crate::open_library_raw!("garrysmod/bin/lib", $name, ".so")) $crate::open_library_raw!("garrysmod/bin/", $name, ".so"),
$crate::open_library_raw!("garrysmod/bin/lib", $name, ".so"),
}
} }
}}; }};
} }
@ -162,28 +173,74 @@ macro_rules! open_library {
} }
#[cfg(all(target_os = "windows", target_pointer_width = "64"))] { #[cfg(all(target_os = "windows", target_pointer_width = "64"))] {
$crate::__private__gmod_rs__try_chained_open! {
$crate::open_library_raw!("bin/win64/", $name, ".dll") $crate::open_library_raw!("bin/win64/", $name, ".dll")
} }
}
#[cfg(all(target_os = "windows", target_pointer_width = "32"))] { #[cfg(all(target_os = "windows", target_pointer_width = "32"))] {
$crate::open_library_raw!("bin/", $name, ".dll") $crate::__private__gmod_rs__try_chained_open! {
.or_else(|_| $crate::open_library_raw!("garrysmod/bin/", $name, ".dll")) $crate::open_library_raw!("bin/", $name, ".dll"),
$crate::open_library_raw!("garrysmod/bin/", $name, ".dll"),
}
} }
#[cfg(all(target_os = "linux", target_pointer_width = "64"))] { #[cfg(all(target_os = "linux", target_pointer_width = "64"))] {
$crate::open_library_raw!("bin/linux64/", $name, ".so") $crate::__private__gmod_rs__try_chained_open! {
.or_else(|_| $crate::open_library_raw!("bin/linux64/lib", $name, ".so")) $crate::open_library_raw!("bin/linux64/", $name, ".so"),
$crate::open_library_raw!("bin/linux64/lib", $name, ".so"),
}
} }
#[cfg(all(target_os = "linux", target_pointer_width = "32"))] { #[cfg(all(target_os = "linux", target_pointer_width = "32"))] {
$crate::open_library_raw!("bin/linux32/", $name, ".so") $crate::__private__gmod_rs__try_chained_open! {
.or_else(|_| $crate::open_library_raw!("bin/linux32/lib", $name, ".so")) $crate::open_library_raw!("bin/linux32/", $name, ".so"),
.or_else(|_| $crate::open_library_raw!("bin/", $name, ".so")) $crate::open_library_raw!("bin/linux32/lib", $name, ".so"),
.or_else(|_| $crate::open_library_raw!("bin/lib", $name, ".so")) $crate::open_library_raw!("bin/", $name, ".so"),
.or_else(|_| $crate::open_library_raw!("garrysmod/bin/", $name, ".so")) $crate::open_library_raw!("bin/lib", $name, ".so"),
.or_else(|_| $crate::open_library_raw!("garrysmod/bin/lib", $name, ".so")) $crate::open_library_raw!("garrysmod/bin/", $name, ".so"),
.or_else(|_| $crate::open_library_raw!("bin/", $name, "_srv.so")) $crate::open_library_raw!("garrysmod/bin/lib", $name, ".so"),
.or_else(|_| $crate::open_library_raw!("bin/lib", $name, "_srv.so")) $crate::open_library_raw!("bin/", $name, "_srv.so"),
.or_else(|_| $crate::open_library_raw!("garrysmod/bin/", $name, "_srv.so")) $crate::open_library_raw!("bin/lib", $name, "_srv.so"),
.or_else(|_| $crate::open_library_raw!("garrysmod/bin/lib", $name, "_srv.so")) $crate::open_library_raw!("garrysmod/bin/", $name, "_srv.so"),
$crate::open_library_raw!("garrysmod/bin/lib", $name, "_srv.so"),
}
} }
}}; }};
} }
#[derive(Default)]
#[doc(hidden)]
pub struct OpenGmodLibraryErrs(pub std::collections::HashMap<&'static str, libloading::Error>);
impl std::error::Error for OpenGmodLibraryErrs {}
impl std::fmt::Display for OpenGmodLibraryErrs {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "")?;
for (path, err) in &self.0 {
writeln!(f, "{} = {}", path, err)?;
}
writeln!(f, "")?;
Ok(())
}
}
impl std::fmt::Debug for OpenGmodLibraryErrs {
#[inline]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self, f)
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __private__gmod_rs__try_chained_open {
{$($expr:expr),+} => {
loop {
let mut errors = $crate::OpenGmodLibraryErrs::default();
$(
match $expr {
Ok(val) => break Ok(val),
Err((err, path)) => { errors.0.insert(path, err); }
}
)+
break Err(errors);
}
};
}

View File

@ -5,12 +5,6 @@ use std::{cell::UnsafeCell, ffi::c_void};
use libloading::{Library, Symbol}; use libloading::{Library, Symbol};
macro_rules! find_library {
($path:literal) => {
Library::new($path).map(|lib| (lib, $path))
};
}
use super::{LuaError, State as LuaState, LuaDebug}; use super::{LuaError, State as LuaState, LuaDebug};
pub type LuaInt = isize; pub type LuaInt = isize;
@ -250,27 +244,31 @@ impl LuaShared {
#[cfg(all(target_os = "windows", target_pointer_width = "64"))] #[cfg(all(target_os = "windows", target_pointer_width = "64"))]
pub unsafe fn find_lua_shared() -> (Library, &'static str) { pub unsafe fn find_lua_shared() -> (Library, &'static str) {
find_library!("bin/win64/lua_shared.dll") crate::open_library_raw!("bin/win64/lua_shared.dll")
.expect("Failed to load lua_shared.dll") .expect("Failed to load lua_shared.dll")
} }
#[cfg(all(target_os = "windows", target_pointer_width = "32"))] #[cfg(all(target_os = "windows", target_pointer_width = "32"))]
pub unsafe fn find_lua_shared() -> (Library, &'static str) { pub unsafe fn find_lua_shared() -> (Library, &'static str) {
find_library!("garrysmod/bin/lua_shared.dll") crate::__private__gmod_rs__try_chained_open! {
.or_else(|_| find_library!("bin/lua_shared.dll")) crate::open_library_raw!("garrysmod/bin/lua_shared.dll"),
crate::open_library_raw!("bin/lua_shared.dll")
}
.expect("Failed to load lua_shared.dll") .expect("Failed to load lua_shared.dll")
} }
#[cfg(all(target_os = "linux", target_pointer_width = "32"))] #[cfg(all(target_os = "linux", target_pointer_width = "32"))]
pub unsafe fn find_lua_shared() -> (Library, &'static str) { pub unsafe fn find_lua_shared() -> (Library, &'static str) {
find_library!("garrysmod/bin/lua_shared_srv.so") crate::__private__gmod_rs__try_chained_open! {
.or_else(|_| find_library!("bin/linux32/lua_shared.so")) crate::open_library_raw!("garrysmod/bin/lua_shared_srv.so"),
crate::open_library_raw!("bin/linux32/lua_shared.so")
}
.expect("Failed to find lua_shared.so or lua_shared_srv.so") .expect("Failed to find lua_shared.so or lua_shared_srv.so")
} }
#[cfg(all(target_os = "linux", target_pointer_width = "64"))] #[cfg(all(target_os = "linux", target_pointer_width = "64"))]
pub unsafe fn find_lua_shared() -> (Library, &'static str) { pub unsafe fn find_lua_shared() -> (Library, &'static str) {
find_library!("bin/linux64/lua_shared.so") crate::open_library_raw!("bin/linux64/lua_shared.so")
.expect("Failed to find lua_shared.so") .expect("Failed to find lua_shared.so")
} }
} }