Skip to content

Commit 4b016f7

Browse files
committed
Remove global engine info lock
1 parent 1d366a1 commit 4b016f7

File tree

3 files changed

+38
-61
lines changed

3 files changed

+38
-61
lines changed

src/context.rs

+14-7
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use libc;
1717
#[allow(deprecated)]
1818
use crate::{
1919
callbacks, edit,
20-
engine::EngineInfo,
20+
engine::{EngineInfo, EngineInfos},
2121
notation::SignatureNotations,
2222
results,
2323
utils::{convert_err, CStrArgument, SmallVec},
@@ -42,7 +42,7 @@ impl Drop for Context {
4242
impl Context {
4343
impl_wrapper!(ffi::gpgme_ctx_t);
4444

45-
fn new() -> Result<Self> {
45+
pub(crate) fn new() -> Result<Self> {
4646
crate::init();
4747
unsafe {
4848
let mut ctx = ptr::null_mut();
@@ -163,6 +163,13 @@ impl Context {
163163
unsafe { EngineInfo::from_raw(ffi::gpgme_ctx_get_engine_info(self.as_raw())) }
164164
}
165165

166+
/// Upstream documentation:
167+
/// [`gpgme_ctx_get_engine_info`](https://www.gnupg.org/documentation/manuals/gpgme/Crypto-Engine.html#index-gpgme_005fctx_005fget_005fengine_005finfo)
168+
#[inline]
169+
pub fn engines(&self) -> EngineInfos<'_> {
170+
unsafe { EngineInfos::from_list(ffi::gpgme_ctx_get_engine_info(self.as_raw())) }
171+
}
172+
166173
#[inline]
167174
pub fn set_engine_path(&mut self, path: impl CStrArgument) -> Result<()> {
168175
let path = path.into_cstr();
@@ -729,11 +736,11 @@ impl Context {
729736
let expires = expires.as_secs().value_into().unwrap_or_saturate();
730737
self::with_joined_cstr(subkeys, |subkeys, _| unsafe {
731738
convert_err(ffi::gpgme_op_setexpire(
732-
self.as_raw(),
733-
key.as_raw(),
734-
expires,
735-
subkeys.map_or(ptr::null(), |subkeys| subkeys.as_ptr()),
736-
0,
739+
self.as_raw(),
740+
key.as_raw(),
741+
expires,
742+
subkeys.map_or(ptr::null(), |subkeys| subkeys.as_ptr()),
743+
0,
737744
))
738745
})
739746
}

src/engine.rs

+9-14
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::{
99

1010
use ffi;
1111

12-
use crate::{utils::convert_err, NonNull, Protocol, Result};
12+
use crate::{utils::convert_err, Context, NonNull, Protocol, Result};
1313

1414
/// Upstream documentation:
1515
/// [`gpgme_engine_info_t`](https://www.gnupg.org/documentation/manuals/gpgme/Engine-Information.html#index-gpgme_005fengine_005finfo_005ft)
@@ -116,16 +116,15 @@ impl_list_iterator!(pub struct EngineInfos(EngineInfo: ffi::gpgme_engine_info_t)
116116

117117
/// A RAII guard type that ensures the global engine information list is not modified
118118
/// while it is being iterated.
119-
pub struct EngineInfoGuard(RwLockReadGuard<'static, ()>);
119+
pub struct EngineInfoGuard {
120+
snapshot: Context,
121+
}
120122

121123
impl EngineInfoGuard {
122-
pub fn new(lock: &'static RwLock<()>) -> Result<EngineInfoGuard> {
123-
let lock = lock.read().expect("engine info lock was poisoned");
124-
unsafe {
125-
let mut info = ptr::null_mut();
126-
convert_err(ffi::gpgme_get_engine_info(&mut info))?;
127-
}
128-
Ok(EngineInfoGuard(lock))
124+
pub(crate) fn new() -> Result<Self> {
125+
Ok(Self {
126+
snapshot: Context::new()?,
127+
})
129128
}
130129

131130
#[inline]
@@ -145,11 +144,7 @@ impl<'a> IntoIterator for &'a EngineInfoGuard {
145144

146145
#[inline]
147146
fn into_iter(self) -> Self::IntoIter {
148-
unsafe {
149-
let mut first = ptr::null_mut();
150-
assert_eq!(ffi::gpgme_get_engine_info(&mut first), 0);
151-
EngineInfos::from_list(first)
152-
}
147+
self.snapshot.engines()
153148
}
154149
}
155150

src/lib.rs

+15-40
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::{
22
ffi::CStr,
33
fmt, ptr,
44
str::Utf8Error,
5-
sync::{Mutex, OnceLock, RwLock},
5+
sync::{Mutex, OnceLock},
66
};
77

88
use self::{
@@ -180,7 +180,7 @@ cfg_if::cfg_if! {
180180
/// ```
181181
#[inline]
182182
pub fn init() -> Gpgme {
183-
static TOKEN: OnceLock<(&str, RwLock<()>)> = OnceLock::new();
183+
static TOKEN: OnceLock<&str> = OnceLock::new();
184184
let token = TOKEN.get_or_init(|| unsafe {
185185
let offset = memoffset::offset_of!(ffi::_gpgme_signature, validity);
186186

@@ -189,24 +189,17 @@ pub fn init() -> Gpgme {
189189
!result.is_null(),
190190
"the library linked is not the correct version"
191191
);
192-
(
193-
CStr::from_ptr(result)
194-
.to_str()
195-
.expect("gpgme version string is not valid utf-8"),
196-
RwLock::default(),
197-
)
192+
CStr::from_ptr(result)
193+
.to_str()
194+
.expect("gpgme version string is not valid utf-8")
198195
});
199-
Gpgme {
200-
version: token.0,
201-
engine_lock: &token.1,
202-
}
196+
Gpgme { version: token }
203197
}
204198

205199
/// A type for managing the library's configuration.
206200
#[derive(Debug, Clone)]
207201
pub struct Gpgme {
208202
version: &'static str,
209-
engine_lock: &'static RwLock<()>,
210203
}
211204

212205
impl Gpgme {
@@ -289,31 +282,19 @@ impl Gpgme {
289282
/// [`gpgme_get_engine_info`](https://www.gnupg.org/documentation/manuals/gpgme/Engine-Information.html#index-gpgme_005fget_005fengine_005finfo)
290283
#[inline]
291284
pub fn engine_info(&self) -> Result<EngineInfoGuard> {
292-
EngineInfoGuard::new(self.engine_lock)
293-
}
294-
295-
// Requires the engine_lock to be held by the current thread when called
296-
unsafe fn get_engine_info(&self, proto: Protocol) -> ffi::gpgme_engine_info_t {
297-
let mut info = ptr::null_mut();
298-
assert_eq!(ffi::gpgme_get_engine_info(&mut info), 0);
299-
while !info.is_null() && ((*info).protocol != proto.raw()) {
300-
info = (*info).next;
301-
}
302-
info
285+
EngineInfoGuard::new()
303286
}
304287

305288
#[inline]
306289
pub fn set_engine_path(&self, proto: Protocol, path: impl CStrArgument) -> Result<()> {
307290
let path = path.into_cstr();
308-
let _lock = self
309-
.engine_lock
310-
.write()
311-
.expect("engine info lock was poisoned");
312291
unsafe {
313292
let home_dir = self
314-
.get_engine_info(proto)
293+
.engine_info()?
294+
.get(proto)
315295
.as_ref()
316-
.map_or(ptr::null(), |x| x.home_dir);
296+
.and_then(|x| x.home_dir_raw())
297+
.map_or(ptr::null(), |x| x.as_ptr());
317298
convert_err(ffi::gpgme_set_engine_info(
318299
proto.raw(),
319300
path.as_ref().as_ptr(),
@@ -326,15 +307,13 @@ impl Gpgme {
326307
#[inline]
327308
pub fn set_engine_home_dir(&self, proto: Protocol, home_dir: impl CStrArgument) -> Result<()> {
328309
let home_dir = home_dir.into_cstr();
329-
let _lock = self
330-
.engine_lock
331-
.write()
332-
.expect("engine info lock was poisoned");
333310
unsafe {
334311
let path = self
335-
.get_engine_info(proto)
312+
.engine_info()?
313+
.get(proto)
336314
.as_ref()
337-
.map_or(ptr::null(), |x| x.file_name);
315+
.and_then(|x| x.path_raw())
316+
.map_or(ptr::null(), |x| x.as_ptr());
338317
convert_err(ffi::gpgme_set_engine_info(
339318
proto.raw(),
340319
path,
@@ -360,10 +339,6 @@ impl Gpgme {
360339
.as_ref()
361340
.map_or(ptr::null(), |s| s.as_ref().as_ptr());
362341
unsafe {
363-
let _lock = self
364-
.engine_lock
365-
.write()
366-
.expect("engine info lock was poisoned");
367342
convert_err(ffi::gpgme_set_engine_info(proto.raw(), path, home_dir))?;
368343
}
369344
Ok(())

0 commit comments

Comments
 (0)