Handle dynamic program dlopen failures gracefully

This commit is contained in:
Michael Vines 2018-10-13 10:37:37 -07:00
parent 3828eda507
commit 2d0f07091d
3 changed files with 15 additions and 8 deletions

View File

@ -13,6 +13,7 @@ use libc;
use libloading::os::unix::*; use libloading::os::unix::*;
#[cfg(windows)] #[cfg(windows)]
use libloading::os::windows::*; use libloading::os::windows::*;
use result::Result;
use solana_program_interface::account::KeyedAccount; use solana_program_interface::account::KeyedAccount;
use solana_program_interface::pubkey::Pubkey; use solana_program_interface::pubkey::Pubkey;
@ -80,12 +81,12 @@ pub enum DynamicProgram {
} }
impl DynamicProgram { impl DynamicProgram {
pub fn new_native(name: String) -> Self { pub fn new_native(name: String) -> Result<Self> {
// create native program // create native program
let path = ProgramPath::Native {}.create(&name); let path = ProgramPath::Native {}.create(&name);
// TODO linux tls bug can cause crash on dlclose, workaround by never unloading // TODO linux tls bug can cause crash on dlclose, workaround by never unloading
let library = Library::open(Some(path), libc::RTLD_NODELETE | libc::RTLD_NOW).unwrap(); let library = Library::open(Some(path), libc::RTLD_NODELETE | libc::RTLD_NOW)?;
DynamicProgram::Native { name, library } Ok(DynamicProgram::Native { name, library })
} }
pub fn new_bpf_from_file(name: String) -> Self { pub fn new_bpf_from_file(name: String) -> Self {

View File

@ -102,7 +102,13 @@ impl SystemProgram {
} }
SystemProgram::Load { program_id, name } => { SystemProgram::Load { program_id, name } => {
let mut hashmap = loaded_programs.write().unwrap(); let mut hashmap = loaded_programs.write().unwrap();
hashmap.insert(program_id, DynamicProgram::new_native(name)); hashmap.insert(
program_id,
DynamicProgram::new_native(name).map_err(|err| {
warn!("SystemProgram::Load failure: {:?}", err);
Error::InvalidArgument
})?,
);
} }
} }
Ok(()) Ok(())

View File

@ -142,7 +142,7 @@ fn test_native_file_noop() {
.map(|(key, account)| KeyedAccount { key, account }) .map(|(key, account)| KeyedAccount { key, account })
.collect(); .collect();
let dp = DynamicProgram::new_native("noop".to_string()); let dp = DynamicProgram::new_native("noop".to_string()).unwrap();
dp.call(&mut infos, &data); dp.call(&mut infos, &data);
} }
} }
@ -163,7 +163,7 @@ fn test_native_file_move_funds_success() {
.map(|(key, account)| KeyedAccount { key, account }) .map(|(key, account)| KeyedAccount { key, account })
.collect(); .collect();
let dp = DynamicProgram::new_native("move_funds".to_string()); let dp = DynamicProgram::new_native("move_funds".to_string()).unwrap();
dp.call(&mut infos, &data); dp.call(&mut infos, &data);
} }
assert_eq!(0, accounts[0].tokens); assert_eq!(0, accounts[0].tokens);
@ -186,7 +186,7 @@ fn test_native_file_move_funds_insufficient_funds() {
.map(|(key, account)| KeyedAccount { key, account }) .map(|(key, account)| KeyedAccount { key, account })
.collect(); .collect();
let dp = DynamicProgram::new_native("move_funds".to_string()); let dp = DynamicProgram::new_native("move_funds".to_string()).unwrap();
dp.call(&mut infos, &data); dp.call(&mut infos, &data);
} }
assert_eq!(10, accounts[0].tokens); assert_eq!(10, accounts[0].tokens);
@ -216,7 +216,7 @@ fn test_program_native_move_funds_succes_many_threads() {
.map(|(key, account)| KeyedAccount { key, account }) .map(|(key, account)| KeyedAccount { key, account })
.collect(); .collect();
let dp = DynamicProgram::new_native("move_funds".to_string()); let dp = DynamicProgram::new_native("move_funds".to_string()).unwrap();
dp.call(&mut infos, &data); dp.call(&mut infos, &data);
} }
assert_eq!(0, accounts[0].tokens); assert_eq!(0, accounts[0].tokens);