prepare worker: Catch unexpected unwinds (#4304)

* prepare worker: Catch unexpected unwinds

* Use more specific wording for unknown panic payload
This commit is contained in:
Sergei Shulepov
2021-11-18 19:11:13 +01:00
committed by GitHub
parent be85d5cb96
commit bd422af092
2 changed files with 31 additions and 10 deletions
+5 -2
View File
@@ -26,6 +26,8 @@ pub enum PrepareError {
Prevalidation(String), Prevalidation(String),
/// Compilation failed for the given PVF. /// Compilation failed for the given PVF.
Preparation(String), Preparation(String),
/// An unexpected panic has occured in the preparation worker.
Panic(String),
/// Failed to prepare the PVF due to the time limit. /// Failed to prepare the PVF due to the time limit.
TimedOut, TimedOut,
/// This state indicates that the process assigned to prepare the artifact wasn't responsible /// This state indicates that the process assigned to prepare the artifact wasn't responsible
@@ -77,8 +79,9 @@ pub enum InvalidCandidate {
impl From<PrepareError> for ValidationError { impl From<PrepareError> for ValidationError {
fn from(error: PrepareError) -> Self { fn from(error: PrepareError) -> Self {
let error_str = match error { let error_str = match error {
PrepareError::Prevalidation(err) => err, PrepareError::Prevalidation(err) => format!("prevalidation: {}", err),
PrepareError::Preparation(err) => err, PrepareError::Preparation(err) => format!("preparation: {}", err),
PrepareError::Panic(err) => format!("panic: {}", err),
PrepareError::TimedOut => "preparation timeout".to_owned(), PrepareError::TimedOut => "preparation timeout".to_owned(),
PrepareError::DidNotMakeIt => "communication error".to_owned(), PrepareError::DidNotMakeIt => "communication error".to_owned(),
}; };
+19 -1
View File
@@ -30,7 +30,7 @@ use async_std::{
}; };
use parity_scale_codec::{Decode, Encode}; use parity_scale_codec::{Decode, Encode};
use sp_core::hexdisplay::HexDisplay; use sp_core::hexdisplay::HexDisplay;
use std::{sync::Arc, time::Duration}; use std::{any::Any, panic, sync::Arc, time::Duration};
const NICENESS_BACKGROUND: i32 = 10; const NICENESS_BACKGROUND: i32 = 10;
const NICENESS_FOREGROUND: i32 = 0; const NICENESS_FOREGROUND: i32 = 0;
@@ -318,6 +318,7 @@ pub fn worker_entrypoint(socket_path: &str) {
} }
fn prepare_artifact(code: &[u8]) -> Result<CompiledArtifact, PrepareError> { fn prepare_artifact(code: &[u8]) -> Result<CompiledArtifact, PrepareError> {
panic::catch_unwind(|| {
let blob = match crate::executor_intf::prevalidate(code) { let blob = match crate::executor_intf::prevalidate(code) {
Err(err) => return Err(PrepareError::Prevalidation(format!("{:?}", err))), Err(err) => return Err(PrepareError::Prevalidation(format!("{:?}", err))),
Ok(b) => b, Ok(b) => b,
@@ -327,4 +328,21 @@ fn prepare_artifact(code: &[u8]) -> Result<CompiledArtifact, PrepareError> {
Ok(compiled_artifact) => Ok(CompiledArtifact::new(compiled_artifact)), Ok(compiled_artifact) => Ok(CompiledArtifact::new(compiled_artifact)),
Err(err) => Err(PrepareError::Preparation(format!("{:?}", err))), Err(err) => Err(PrepareError::Preparation(format!("{:?}", err))),
} }
})
.map_err(|panic_payload| PrepareError::Panic(stringify_panic_payload(panic_payload)))
.and_then(|inner_result| inner_result)
}
/// Attempt to convert an opaque panic payload to a string.
///
/// This is a best effort, and is not guaranteed to provide the most accurate value.
fn stringify_panic_payload(payload: Box<dyn Any + Send + 'static>) -> String {
match payload.downcast::<&'static str>() {
Ok(msg) => msg.to_string(),
Err(payload) => match payload.downcast::<String>() {
Ok(msg) => *msg,
// At least we tried...
Err(_) => "unkown panic payload".to_string(),
},
}
} }