Skip to content

Commit 00956f3

Browse files
authoredNov 6, 2023
worker/swirl/runner: Simplify AssertUnwindSafe usage (#7453)
rust-lang/rust#40628, rust-lang/rust#65717 and rust-lang/rfcs#3260 all show that unwind safety isn't particularly ergonomic to use and implement, and ultimately leads to people slapping `AssertUnwindSafe` everywhere until the compiler stops complaining. This situation has led to built-in test framework using `catch_unwind(AssertUnwindSafe(...))` (see https://github.com/rust-lang/rust/blob/1.73.0/library/test/src/lib.rs#L649) and libraries like tower-http doing the same (see https://docs.rs/tower-http/0.4.4/src/tower_http/catch_panic.rs.html#198). As people have mentioned in the threads above, trying to implement this correctly is akin to fighting windmills at the moment. Since the above cases demonstrated that `catch_unwind(AssertUnwindSafe(...))` is currently the easiest way to deal with this situation, this commit does the same and refactors our background job runner code accordingly.
1 parent ccccb82 commit 00956f3

File tree

3 files changed

+21
-27
lines changed

3 files changed

+21
-27
lines changed
 

‎src/cloudfront.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@ use aws_sdk_cloudfront::types::{InvalidationBatch, Paths};
55
use aws_sdk_cloudfront::{Client, Config};
66
use retry::delay::{jitter, Exponential};
77
use retry::OperationResult;
8-
use std::panic::AssertUnwindSafe;
98
use std::time::Duration;
109
use tokio::runtime::Runtime;
1110

1211
pub struct CloudFront {
13-
client: AssertUnwindSafe<Client>,
12+
client: Client,
1413
distribution_id: String,
1514
}
1615

@@ -27,7 +26,7 @@ impl CloudFront {
2726
.credentials_provider(credentials)
2827
.build();
2928

30-
let client = AssertUnwindSafe(Client::from_conf(config));
29+
let client = Client::from_conf(config);
3130

3231
Some(Self {
3332
client,

‎src/worker/environment.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,14 @@ use crate::storage::Storage;
44
use crate::worker::swirl::PerformError;
55
use crates_io_index::Repository;
66
use reqwest::blocking::Client;
7-
use std::panic::AssertUnwindSafe;
87
use std::sync::{Arc, Mutex, MutexGuard, PoisonError};
98

109
pub struct Environment {
1110
index: Mutex<Repository>,
12-
http_client: AssertUnwindSafe<Client>,
11+
http_client: Client,
1312
cloudfront: Option<CloudFront>,
1413
fastly: Option<Fastly>,
15-
pub storage: AssertUnwindSafe<Arc<Storage>>,
14+
pub storage: Arc<Storage>,
1615
}
1716

1817
impl Environment {
@@ -25,10 +24,10 @@ impl Environment {
2524
) -> Self {
2625
Self {
2726
index: Mutex::new(index),
28-
http_client: AssertUnwindSafe(http_client),
27+
http_client,
2928
cloudfront,
3029
fastly,
31-
storage: AssertUnwindSafe(storage),
30+
storage,
3231
}
3332
}
3433

‎src/worker/swirl/runner.rs

+15-19
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use parking_lot::RwLock;
77
use std::any::Any;
88
use std::collections::HashMap;
99
use std::error::Error;
10-
use std::panic::{catch_unwind, AssertUnwindSafe, PanicInfo, UnwindSafe};
10+
use std::panic::{catch_unwind, AssertUnwindSafe, PanicInfo};
1111
use std::sync::mpsc::{sync_channel, SyncSender};
1212
use std::sync::Arc;
1313
use std::time::Duration;
@@ -29,15 +29,15 @@ fn runnable<J: BackgroundJob>(
2929
}
3030

3131
/// The core runner responsible for locking and running jobs
32-
pub struct Runner<Context: Clone + Send + UnwindSafe + 'static> {
32+
pub struct Runner<Context: Clone + Send + 'static> {
3333
connection_pool: DieselPool,
3434
thread_pool: ThreadPool,
3535
job_registry: Arc<RwLock<HashMap<String, RunTaskFn<Context>>>>,
3636
environment: Context,
3737
job_start_timeout: Duration,
3838
}
3939

40-
impl<Context: Clone + Send + UnwindSafe + 'static> Runner<Context> {
40+
impl<Context: Clone + Send + 'static> Runner<Context> {
4141
pub fn new(connection_pool: DieselPool, environment: Context) -> Self {
4242
Self {
4343
connection_pool,
@@ -110,7 +110,7 @@ impl<Context: Clone + Send + UnwindSafe + 'static> Runner<Context> {
110110
fn run_single_job(&self, sender: SyncSender<Event>) {
111111
use diesel::result::Error::RollbackTransaction;
112112

113-
let job_registry = AssertUnwindSafe(self.job_registry.clone());
113+
let job_registry = self.job_registry.clone();
114114
let environment = self.environment.clone();
115115

116116
// The connection may not be `Send` so we need to clone the pool instead
@@ -155,11 +155,8 @@ impl<Context: Clone + Send + UnwindSafe + 'static> Runner<Context> {
155155
|| {
156156
conn.transaction(|conn| {
157157
let pool = pool.to_real_pool();
158-
let state = AssertUnwindSafe(PerformState { conn, pool });
159-
catch_unwind(|| {
160-
// Ensure the whole `AssertUnwindSafe(_)` is moved
161-
let state = state;
162-
158+
let state = PerformState { conn, pool };
159+
catch_unwind(AssertUnwindSafe(|| {
163160
let job_registry = job_registry.read();
164161
let run_task_fn =
165162
job_registry.get(&job.job_type).ok_or_else(|| {
@@ -169,8 +166,8 @@ impl<Context: Clone + Send + UnwindSafe + 'static> Runner<Context> {
169166
))
170167
})?;
171168

172-
run_task_fn(environment, state.0, job.data)
173-
})
169+
run_task_fn(environment, state, job.data)
170+
}))
174171
.map_err(|e| try_to_extract_panic_info(&e))
175172
})
176173
// TODO: Replace with flatten() once that stabilizes
@@ -294,7 +291,6 @@ mod tests {
294291
use crates_io_test_db::TestDatabase;
295292
use diesel::r2d2;
296293
use diesel::r2d2::ConnectionManager;
297-
use std::panic::AssertUnwindSafe;
298294
use std::sync::{Arc, Barrier};
299295

300296
fn job_exists(id: i64, conn: &mut PgConnection) -> bool {
@@ -323,8 +319,8 @@ mod tests {
323319
fn jobs_are_locked_when_fetched() {
324320
#[derive(Clone)]
325321
struct TestContext {
326-
job_started_barrier: Arc<AssertUnwindSafe<Barrier>>,
327-
assertions_finished_barrier: Arc<AssertUnwindSafe<Barrier>>,
322+
job_started_barrier: Arc<Barrier>,
323+
assertions_finished_barrier: Arc<Barrier>,
328324
}
329325

330326
#[derive(Serialize, Deserialize)]
@@ -344,8 +340,8 @@ mod tests {
344340
let test_database = TestDatabase::new();
345341

346342
let test_context = TestContext {
347-
job_started_barrier: Arc::new(AssertUnwindSafe(Barrier::new(2))),
348-
assertions_finished_barrier: Arc::new(AssertUnwindSafe(Barrier::new(2))),
343+
job_started_barrier: Arc::new(Barrier::new(2)),
344+
assertions_finished_barrier: Arc::new(Barrier::new(2)),
349345
};
350346

351347
let runner =
@@ -409,7 +405,7 @@ mod tests {
409405
fn failed_jobs_do_not_release_lock_before_updating_retry_time() {
410406
#[derive(Clone)]
411407
struct TestContext {
412-
job_started_barrier: Arc<AssertUnwindSafe<Barrier>>,
408+
job_started_barrier: Arc<Barrier>,
413409
}
414410

415411
#[derive(Serialize, Deserialize)]
@@ -428,7 +424,7 @@ mod tests {
428424
let test_database = TestDatabase::new();
429425

430426
let test_context = TestContext {
431-
job_started_barrier: Arc::new(AssertUnwindSafe(Barrier::new(2))),
427+
job_started_barrier: Arc::new(Barrier::new(2)),
432428
};
433429

434430
let runner =
@@ -495,7 +491,7 @@ mod tests {
495491
assert_eq!(tries, 1);
496492
}
497493

498-
fn runner<Context: Clone + Send + UnwindSafe + 'static>(
494+
fn runner<Context: Clone + Send + 'static>(
499495
database_url: &str,
500496
context: Context,
501497
) -> Runner<Context> {

0 commit comments

Comments
 (0)