video: Fix race condition if multiple video backends are downloading OpenH264 at the same time

Co-authored-by: TÖRÖK Attila <torokati44@gmail.com>
This commit is contained in:
Nathan Adams 2024-08-07 21:22:12 +02:00 committed by Kamil Jarosz
parent 9b5e33ab7d
commit 23d4a61fbd
3 changed files with 13 additions and 7 deletions

1
Cargo.lock generated
View File

@ -4565,6 +4565,7 @@ dependencies = [
"ruffle_video_software", "ruffle_video_software",
"slotmap", "slotmap",
"swf", "swf",
"tempfile",
"tracing", "tracing",
] ]

View File

@ -21,6 +21,7 @@ md-5 = "0.10.6"
reqwest = { version = "0.12.5", default-features = false, features = ["blocking"] } reqwest = { version = "0.12.5", default-features = false, features = ["blocking"] }
hex = "0.4.3" hex = "0.4.3"
bzip2 = { version = "0.4.4", features = ["static"] } bzip2 = { version = "0.4.4", features = ["static"] }
tempfile = "3.11.0"
[package.metadata.cargo-machete] [package.metadata.cargo-machete]
ignored = [ ignored = [

View File

@ -85,20 +85,24 @@ impl ExternalVideoBackend {
let (filename, md5sum) = Self::get_openh264_data()?; let (filename, md5sum) = Self::get_openh264_data()?;
let filepath = std::env::current_exe()? let current_exe = std::env::current_exe()?;
let directory = current_exe
.parent() .parent()
.ok_or("Could not determine Ruffle location.")? .ok_or("Could not determine Ruffle location.")?;
.join(filename); let filepath = directory.join(filename);
// If the binary doesn't exist in the expected location, download it. // If the binary doesn't exist in the expected location, download it.
if !filepath.is_file() { if !filepath.is_file() {
let url = format!("{}{}{}", URL_BASE, filename, URL_SUFFIX); let url = format!("{}{}{}", URL_BASE, filename, URL_SUFFIX);
let response = reqwest::blocking::get(url)?; let response = reqwest::blocking::get(url)?;
let bytes = response.bytes()?; let mut bzip2_reader = BzDecoder::new(response);
let mut bzip2_reader = BzDecoder::new(bytes.as_ref());
let mut file = File::create(filepath.clone())?; let mut tempfile = tempfile::NamedTempFile::with_prefix_in(filename, directory)?;
copy(&mut bzip2_reader, &mut file)?; copy(&mut bzip2_reader, &mut tempfile)?;
// Let's assume that if this fails, it's because another process has already put it there
// and loaded it, therefore it can't be overwritten (on Windows at least), but in the end,
// all's fine - the MD5 hash will still be checked before attempting to load the library.
let _ = tempfile.persist(&filepath);
} }
// Regardless of whether the library was already there, or we just downloaded it, let's check the MD5 hash. // Regardless of whether the library was already there, or we just downloaded it, let's check the MD5 hash.