Make exit status interpretable by CommandConfigurator (#2723)
* Make exit status interpretable by CommandConfigurator * Fix import issues * Fix default implementation for non-unix environment * Make docs only available on unix if the entry is only for unix * Revert "Fix default implementation for non-unix environment" This reverts commit 5457f6f7376c2a3a4d4c8459de46d6b54bb0d44f. * Fix the invalid link in the example
This commit is contained in:
parent
94fa4014ac
commit
0d0bbf0c5d
@ -38,7 +38,9 @@ use typed_builder::TypedBuilder;
|
|||||||
|
|
||||||
use super::HasTimeout;
|
use super::HasTimeout;
|
||||||
#[cfg(all(feature = "std", unix))]
|
#[cfg(all(feature = "std", unix))]
|
||||||
use crate::executors::{Executor, ExitKind};
|
use crate::executors::Executor;
|
||||||
|
#[cfg(all(feature = "std", any(unix, doc)))]
|
||||||
|
use crate::executors::ExitKind;
|
||||||
use crate::{
|
use crate::{
|
||||||
corpus::Corpus,
|
corpus::Corpus,
|
||||||
executors::{hooks::ExecutorHooksTuple, HasObservers},
|
executors::{hooks::ExecutorHooksTuple, HasObservers},
|
||||||
@ -337,8 +339,6 @@ where
|
|||||||
OT: Debug + ObserversTuple<I, S>,
|
OT: Debug + ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
fn execute_input_with_command(&mut self, state: &mut S, input: &I) -> Result<ExitKind, Error> {
|
fn execute_input_with_command(&mut self, state: &mut S, input: &I) -> Result<ExitKind, Error> {
|
||||||
use std::os::unix::prelude::ExitStatusExt;
|
|
||||||
|
|
||||||
use wait_timeout::ChildExt;
|
use wait_timeout::ChildExt;
|
||||||
|
|
||||||
*state.executions_mut() += 1;
|
*state.executions_mut() += 1;
|
||||||
@ -346,29 +346,21 @@ where
|
|||||||
|
|
||||||
let mut child = self.configurer.spawn_child(input)?;
|
let mut child = self.configurer.spawn_child(input)?;
|
||||||
|
|
||||||
let res = match child
|
let exit_kind = child
|
||||||
.wait_timeout(self.configurer.exec_timeout())
|
.wait_timeout(self.configurer.exec_timeout())
|
||||||
.expect("waiting on child failed")
|
.expect("waiting on child failed")
|
||||||
.map(|status| status.signal())
|
.map(|status| self.configurer.exit_kind_from_status(&status))
|
||||||
{
|
.unwrap_or_else(|| {
|
||||||
// for reference: https://www.man7.org/linux/man-pages/man7/signal.7.html
|
|
||||||
Some(Some(9)) => Ok(ExitKind::Oom),
|
|
||||||
Some(Some(_)) => Ok(ExitKind::Crash),
|
|
||||||
Some(None) => Ok(ExitKind::Ok),
|
|
||||||
None => {
|
|
||||||
// if this fails, there is not much we can do. let's hope it failed because the process finished
|
// if this fails, there is not much we can do. let's hope it failed because the process finished
|
||||||
// in the meantime.
|
// in the meantime.
|
||||||
drop(child.kill());
|
drop(child.kill());
|
||||||
// finally, try to wait to properly clean up system resources.
|
// finally, try to wait to properly clean up system resources.
|
||||||
drop(child.wait());
|
drop(child.wait());
|
||||||
Ok(ExitKind::Timeout)
|
ExitKind::Timeout
|
||||||
}
|
});
|
||||||
};
|
|
||||||
|
|
||||||
if let Ok(exit_kind) = res {
|
self.observers
|
||||||
self.observers
|
.post_exec_child_all(state, input, &exit_kind)?;
|
||||||
.post_exec_child_all(state, input, &exit_kind)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(h) = &mut self.configurer.stdout_observer() {
|
if let Some(h) = &mut self.configurer.stdout_observer() {
|
||||||
let mut stdout = Vec::new();
|
let mut stdout = Vec::new();
|
||||||
@ -392,7 +384,7 @@ where
|
|||||||
let obs = observers.index_mut(h);
|
let obs = observers.index_mut(h);
|
||||||
obs.observe_stderr(&stderr);
|
obs.observe_stderr(&stderr);
|
||||||
}
|
}
|
||||||
res
|
Ok(exit_kind)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -809,7 +801,7 @@ impl CommandExecutorBuilder {
|
|||||||
/// MyExecutor.into_executor(())
|
/// MyExecutor.into_executor(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(all(feature = "std", any(unix, doc)))]
|
#[cfg(all(feature = "std", unix))]
|
||||||
pub trait CommandConfigurator<I, C = Child>: Sized {
|
pub trait CommandConfigurator<I, C = Child>: Sized {
|
||||||
/// Get the stdout
|
/// Get the stdout
|
||||||
fn stdout_observer(&self) -> Option<Handle<StdOutObserver>> {
|
fn stdout_observer(&self) -> Option<Handle<StdOutObserver>> {
|
||||||
@ -828,6 +820,18 @@ pub trait CommandConfigurator<I, C = Child>: Sized {
|
|||||||
/// Set the timeout duration for execution of the child process.
|
/// Set the timeout duration for execution of the child process.
|
||||||
fn exec_timeout_mut(&mut self) -> &mut Duration;
|
fn exec_timeout_mut(&mut self) -> &mut Duration;
|
||||||
|
|
||||||
|
/// Maps the exit status of the child process to an `ExitKind`.
|
||||||
|
#[inline]
|
||||||
|
fn exit_kind_from_status(&self, status: &std::process::ExitStatus) -> ExitKind {
|
||||||
|
use crate::std::os::unix::process::ExitStatusExt;
|
||||||
|
match status.signal() {
|
||||||
|
// for reference: https://www.man7.org/linux/man-pages/man7/signal.7.html
|
||||||
|
Some(9) => ExitKind::Oom,
|
||||||
|
Some(_) => ExitKind::Crash,
|
||||||
|
None => ExitKind::Ok,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Create an `Executor` from this `CommandConfigurator`.
|
/// Create an `Executor` from this `CommandConfigurator`.
|
||||||
fn into_executor<OT, S>(self, observers: OT) -> CommandExecutor<OT, S, Self, (), C>
|
fn into_executor<OT, S>(self, observers: OT) -> CommandExecutor<OT, S, Self, (), C>
|
||||||
where
|
where
|
||||||
|
@ -5,7 +5,7 @@ use alloc::vec::Vec;
|
|||||||
use core::{fmt::Debug, time::Duration};
|
use core::{fmt::Debug, time::Duration};
|
||||||
|
|
||||||
pub use combined::CombinedExecutor;
|
pub use combined::CombinedExecutor;
|
||||||
#[cfg(all(feature = "std", any(unix, doc)))]
|
#[cfg(all(feature = "std", unix))]
|
||||||
pub use command::CommandExecutor;
|
pub use command::CommandExecutor;
|
||||||
pub use differential::DiffExecutor;
|
pub use differential::DiffExecutor;
|
||||||
#[cfg(all(feature = "std", feature = "fork", unix))]
|
#[cfg(all(feature = "std", feature = "fork", unix))]
|
||||||
@ -23,7 +23,7 @@ pub use with_observers::WithObservers;
|
|||||||
use crate::{state::UsesState, Error};
|
use crate::{state::UsesState, Error};
|
||||||
|
|
||||||
pub mod combined;
|
pub mod combined;
|
||||||
#[cfg(all(feature = "std", any(unix, doc)))]
|
#[cfg(all(feature = "std", unix))]
|
||||||
pub mod command;
|
pub mod command;
|
||||||
pub mod differential;
|
pub mod differential;
|
||||||
#[cfg(all(feature = "std", feature = "fork", unix))]
|
#[cfg(all(feature = "std", feature = "fork", unix))]
|
||||||
|
@ -2,7 +2,10 @@
|
|||||||
//!
|
//!
|
||||||
//! The [`StdOutObserver`] and [`StdErrObserver`] observers look at the stdout of a program
|
//! The [`StdOutObserver`] and [`StdErrObserver`] observers look at the stdout of a program
|
||||||
//! The executor must explicitly support these observers.
|
//! The executor must explicitly support these observers.
|
||||||
//! For example, they are supported on the [`crate::executors::CommandExecutor`].
|
#![cfg_attr(
|
||||||
|
all(feature = "std", unix),
|
||||||
|
doc = r"For example, they are supported on the [`crate::executors::CommandExecutor`]."
|
||||||
|
)]
|
||||||
|
|
||||||
use alloc::borrow::Cow;
|
use alloc::borrow::Cow;
|
||||||
use std::vec::Vec;
|
use std::vec::Vec;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user