summaryrefslogtreecommitdiffstats
path: root/openpgp-ffi/src/io.rs
diff options
context:
space:
mode:
Diffstat (limited to 'openpgp-ffi/src/io.rs')
-rw-r--r--openpgp-ffi/src/io.rs25
1 files changed, 19 insertions, 6 deletions
diff --git a/openpgp-ffi/src/io.rs b/openpgp-ffi/src/io.rs
index 484615cf..3c5668d6 100644
--- a/openpgp-ffi/src/io.rs
+++ b/openpgp-ffi/src/io.rs
@@ -26,7 +26,7 @@ pub struct Reader(ReaderKind);
/// In some cases, we want to call functions on concrete types. To
/// avoid nasty hacks, we have specialized variants for that.
pub(crate) enum ReaderKind {
- Generic(Box<dyn io::Read>),
+ Generic(Box<dyn io::Read + Send + Sync>),
Armored(openpgp::armor::Reader<'static>),
}
@@ -80,26 +80,39 @@ type ReaderCallbackFn = extern fn(*mut c_void, *const c_void, size_t) -> ssize_t
/// Creates an reader from a callback and cookie.
///
/// This reader calls the given callback to write data.
+///
+/// # Sending objects across thread boundaries
+///
+/// If you send a Sequoia object (like a pgp_verifier_t) that reads
+/// from an callback across thread boundaries, you must make sure that
+/// the callback and cookie support that as well.
#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
fn pgp_reader_from_callback(cb: ReaderCallbackFn,
cookie: *mut c_void)
-> *mut Reader {
- let r: Box<dyn io::Read> = Box::new(ReaderCallback {
- cb, cookie,
- });
+ let r: Box<dyn io::Read + Send + Sync> =
+ Box::new(ReaderCallback(Mutex::new(ReaderClosure {
+ cb, cookie,
+ })));
ReaderKind::Generic(r).move_into_raw()
}
/// A generic callback-based reader implementation.
-struct ReaderCallback {
+struct ReaderCallback(Mutex<ReaderClosure>);
+
+struct ReaderClosure {
cb: ReaderCallbackFn,
cookie: *mut c_void,
}
+unsafe impl Send for ReaderClosure {}
+
impl Read for ReaderCallback {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+ let closure = self.0.get_mut().expect("Mutex not to be poisoned");
let r =
- (self.cb)(self.cookie, buf.as_mut_ptr() as *mut c_void, buf.len());
+ (closure.cb)(closure.cookie,
+ buf.as_mut_ptr() as *mut c_void, buf.len());
if r < 0 {
use std::io as stdio;
Err(stdio::Error::new(stdio::ErrorKind::Other,