From 8514d46092256ad35207f6842a57975b1765c1bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 23 May 2016 20:29:01 +0300 Subject: [PATCH] Use a Mutex to protect the URI storage get_uri()/set_uri() can be called at any time from any thread, only all other methods of Source/Sink are guaranteed to be called by only a single thread at a time. --- src/rsfilesink.rs | 23 +++++++++++++++-------- src/rsfilesrc.rs | 23 +++++++++++++++-------- src/rshttpsrc.rs | 23 +++++++++++++++-------- 3 files changed, 45 insertions(+), 24 deletions(-) diff --git a/src/rsfilesink.rs b/src/rsfilesink.rs index 8da9596a..24547e18 100644 --- a/src/rsfilesink.rs +++ b/src/rsfilesink.rs @@ -21,13 +21,14 @@ use std::path::PathBuf; use url::Url; use std::io::Write; +use std::sync::Mutex; use utils::*; use rssink::*; #[derive(Debug)] pub struct FileSink { - location: Option, + location: Mutex>, file: Option, position: u64, } @@ -37,7 +38,7 @@ unsafe impl Send for FileSink {} impl FileSink { fn new() -> FileSink { - FileSink { location: None, file: None, position: 0 } + FileSink { location: Mutex::new(None), file: None, position: 0 } } fn new_source() -> Box { @@ -53,7 +54,8 @@ impl Sink for FileSink { fn set_uri(&mut self, uri_str: Option<&str>) -> bool { match uri_str { None => { - self.location = None; + let mut location = self.location.lock().unwrap(); + *location = None; return true; }, Some(ref uri_str) => { @@ -62,18 +64,21 @@ impl Sink for FileSink { Ok(u) => { match u.to_file_path().ok() { Some(p) => { - self.location = Some(p); + let mut location = self.location.lock().unwrap(); + *location = Some(p); return true; }, None => { - self.location = None; + let mut location = self.location.lock().unwrap(); + *location = None; println_err!("Unsupported file URI '{}'", uri_str); return false; } } }, Err(err) => { - self.location = None; + let mut location = self.location.lock().unwrap(); + *location = None; println_err!("Failed to parse URI '{}': {}", uri_str, err); return false; } @@ -83,7 +88,8 @@ impl Sink for FileSink { } fn get_uri(&self) -> Option { - self.location.as_ref() + let location = self.location.lock().unwrap(); + (*location).as_ref() .map(|l| Url::from_file_path(l).ok()) .and_then(|i| i) // join() .map(|u| u.into_string()) @@ -93,7 +99,8 @@ impl Sink for FileSink { self.file = None; self.position = 0; - match self.location { + let location = self.location.lock().unwrap(); + match *location { None => return false, Some(ref location) => { match File::create(location.as_path()) { diff --git a/src/rsfilesrc.rs b/src/rsfilesrc.rs index ceb69467..0358fd85 100644 --- a/src/rsfilesrc.rs +++ b/src/rsfilesrc.rs @@ -19,6 +19,7 @@ use std::u64; use std::io::{Read, Seek, SeekFrom}; use std::fs::File; use std::path::PathBuf; +use std::sync::Mutex; use url::Url; use std::io::Write; @@ -28,7 +29,7 @@ use rssource::*; #[derive(Debug)] pub struct FileSrc { - location: Option, + location: Mutex>, file: Option, position: u64, } @@ -38,7 +39,7 @@ unsafe impl Send for FileSrc {} impl FileSrc { fn new() -> FileSrc { - FileSrc { location: None, file: None, position: 0 } + FileSrc { location: Mutex::new(None), file: None, position: 0 } } fn new_source() -> Box { @@ -54,7 +55,8 @@ impl Source for FileSrc { fn set_uri(&mut self, uri_str: Option<&str>) -> bool { match uri_str { None => { - self.location = None; + let mut location = self.location.lock().unwrap(); + *location = None; return true; }, Some(ref uri_str) => { @@ -63,18 +65,21 @@ impl Source for FileSrc { Ok(u) => { match u.to_file_path().ok() { Some(p) => { - self.location = Some(p); + let mut location = self.location.lock().unwrap(); + *location = Some(p); return true; }, None => { - self.location = None; + let mut location = self.location.lock().unwrap(); + *location = None; println_err!("Unsupported file URI '{}'", uri_str); return false; } } }, Err(err) => { - self.location = None; + let mut location = self.location.lock().unwrap(); + *location = None; println_err!("Failed to parse URI '{}': {}", uri_str, err); return false; } @@ -84,7 +89,8 @@ impl Source for FileSrc { } fn get_uri(&self) -> Option { - self.location.as_ref() + let location = self.location.lock().unwrap(); + (*location).as_ref() .map(|l| Url::from_file_path(l).ok()) .and_then(|i| i) // join() .map(|u| u.into_string()) @@ -105,8 +111,9 @@ impl Source for FileSrc { fn start(&mut self) -> bool { self.file = None; self.position = 0; + let location = self.location.lock().unwrap(); - match self.location { + match *location { None => return false, Some(ref location) => { match File::open(location.as_path()) { diff --git a/src/rshttpsrc.rs b/src/rshttpsrc.rs index 3ee387ef..ffeb1cc3 100644 --- a/src/rshttpsrc.rs +++ b/src/rshttpsrc.rs @@ -23,13 +23,14 @@ use hyper::client::Client; use hyper::client::response::Response; use std::io::Write; +use std::sync::Mutex; use utils::*; use rssource::*; #[derive(Debug)] pub struct HttpSrc { - url: Option, + url: Mutex>, client: Client, response: Option, seekable: bool, @@ -44,7 +45,7 @@ unsafe impl Send for HttpSrc {} impl HttpSrc { fn new() -> HttpSrc { - HttpSrc { url: None, client: Client::new(), response: None, seekable: false, position: 0, size: u64::MAX, start: 0, stop: u64::MAX } + HttpSrc { url: Mutex::new(None), client: Client::new(), response: None, seekable: false, position: 0, size: u64::MAX, start: 0, stop: u64::MAX } } fn new_source() -> Box { @@ -61,7 +62,8 @@ impl HttpSrc { self.position = 0; self.size = u64::MAX; - match self.url { + let url = self.url.lock().unwrap(); + match *url { None => return false, Some(ref url) => { let mut req = self.client.get(url.clone()); @@ -131,7 +133,8 @@ impl Source for HttpSrc { match uri_str { None => { - self.url = None; + let mut url = self.url.lock().unwrap(); + *url = None; return true; }, Some(ref uri_str) => { @@ -140,16 +143,19 @@ impl Source for HttpSrc { Ok(u) => { if u.scheme() == "http" || u.scheme() == "https" { - self.url = Some(u); + let mut url = self.url.lock().unwrap(); + *url = Some(u); return true; } else { - self.url = None; + let mut url = self.url.lock().unwrap(); + *url = None; println_err!("Unsupported file URI '{}'", uri_str); return false; } }, Err(err) => { - self.url = None; + let mut url = self.url.lock().unwrap(); + *url = None; println_err!("Failed to parse URI '{}': {}", uri_str, err); return false; } @@ -159,7 +165,8 @@ impl Source for HttpSrc { } fn get_uri(&self) -> Option { - self.url.as_ref().map(|u| String::from(u.as_str())) + let url = self.url.lock().unwrap(); + (*url).as_ref().map(|u| String::from(u.as_str())) } fn is_seekable(&self) -> bool {