mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-03 11:18:31 +00:00
Small journal logic + lint fixes
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
/// Various triggers that will cause the runtime to take snapshot
|
/// Various triggers that will cause the runtime to take snapshot
|
||||||
@@ -81,3 +83,28 @@ impl FromStr for SnapshotTrigger {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for SnapshotTrigger {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}",
|
||||||
|
match self {
|
||||||
|
Self::Bootstrap => "bootstrap",
|
||||||
|
Self::Explicit => "explicit",
|
||||||
|
Self::FirstEnviron => "first-environ",
|
||||||
|
Self::FirstListen => "first-listen",
|
||||||
|
Self::FirstSigint => "first-sigint",
|
||||||
|
Self::FirstStdin => "first-stdin",
|
||||||
|
Self::Idle => "idle",
|
||||||
|
Self::NonDeterministicCall => "non-deterministic-call",
|
||||||
|
Self::PeriodicInterval => "periodic-interval",
|
||||||
|
Self::Sigalrm => "sigalrm",
|
||||||
|
Self::Sigint => "sigint",
|
||||||
|
Self::Sigtstp => "sigtstp",
|
||||||
|
Self::Sigstop => "sigstop",
|
||||||
|
Self::Transaction => "transaction",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -607,6 +607,21 @@ impl WasiProcess {
|
|||||||
self.wait_for_checkpoint_finish()
|
self.wait_for_checkpoint_finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Takes a snapshot of the process and shuts it down after the snapshot
|
||||||
|
/// is taken.
|
||||||
|
///
|
||||||
|
/// Note: If you ignore the returned future the checkpoint will still
|
||||||
|
/// occur but it will execute asynchronously
|
||||||
|
pub fn snapshot_and_stop(
|
||||||
|
&self,
|
||||||
|
trigger: SnapshotTrigger,
|
||||||
|
) -> std::pin::Pin<Box<dyn futures::Future<Output = ()> + Send + Sync>> {
|
||||||
|
let mut guard = self.inner.0.lock().unwrap();
|
||||||
|
guard.stop_running_after_checkpoint = true;
|
||||||
|
guard.checkpoint = WasiProcessCheckpoint::Snapshot { trigger };
|
||||||
|
self.wait_for_checkpoint_finish()
|
||||||
|
}
|
||||||
|
|
||||||
/// Takes a snapshot of the process
|
/// Takes a snapshot of the process
|
||||||
///
|
///
|
||||||
/// Note: If you ignore the returned future the checkpoint will still
|
/// Note: If you ignore the returned future the checkpoint will still
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use webc::metadata::annotations::Wasi as WasiAnnotation;
|
|||||||
use crate::{
|
use crate::{
|
||||||
bin_factory::BinaryPackage,
|
bin_factory::BinaryPackage,
|
||||||
capabilities::Capabilities,
|
capabilities::Capabilities,
|
||||||
journal::{DynJournal, DynReadableJournal, SnapshotTrigger},
|
journal::{self, DynJournal, DynReadableJournal, SnapshotTrigger},
|
||||||
WasiEnvBuilder,
|
WasiEnvBuilder,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -97,6 +97,23 @@ impl CommonWasiOptions {
|
|||||||
|
|
||||||
builder.add_imports(&self.additional_imports);
|
builder.add_imports(&self.additional_imports);
|
||||||
|
|
||||||
|
#[cfg(feature = "journal")]
|
||||||
|
{
|
||||||
|
for journal in &self.read_only_journals {
|
||||||
|
builder.add_read_only_journal(journal.clone());
|
||||||
|
}
|
||||||
|
for journal in &self.writable_journals {
|
||||||
|
builder.add_writable_journal(journal.clone());
|
||||||
|
}
|
||||||
|
for trigger in &self.snapshot_on {
|
||||||
|
builder.add_snapshot_trigger(trigger.clone());
|
||||||
|
}
|
||||||
|
if let Some(interval) = self.snapshot_interval {
|
||||||
|
builder.with_snapshot_interval(interval);
|
||||||
|
}
|
||||||
|
builder.with_stop_running_after_snapshot(self.stop_running_after_snapshot);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1022,6 +1022,7 @@ impl WasiEnvBuilder {
|
|||||||
extra_tracing: true,
|
extra_tracing: true,
|
||||||
#[cfg(feature = "journal")]
|
#[cfg(feature = "journal")]
|
||||||
snapshot_on: self.snapshot_on,
|
snapshot_on: self.snapshot_on,
|
||||||
|
#[cfg(feature = "journal")]
|
||||||
stop_running_after_snapshot: self.stop_running_after_snapshot,
|
stop_running_after_snapshot: self.stop_running_after_snapshot,
|
||||||
skip_stdio_during_bootstrap: self.skip_stdio_during_bootstrap,
|
skip_stdio_during_bootstrap: self.skip_stdio_during_bootstrap,
|
||||||
additional_imports: self.additional_imports,
|
additional_imports: self.additional_imports,
|
||||||
|
|||||||
@@ -295,6 +295,7 @@ impl WasiEnvInit {
|
|||||||
extra_tracing: false,
|
extra_tracing: false,
|
||||||
#[cfg(feature = "journal")]
|
#[cfg(feature = "journal")]
|
||||||
snapshot_on: self.snapshot_on.clone(),
|
snapshot_on: self.snapshot_on.clone(),
|
||||||
|
#[cfg(feature = "journal")]
|
||||||
stop_running_after_snapshot: self.stop_running_after_snapshot,
|
stop_running_after_snapshot: self.stop_running_after_snapshot,
|
||||||
skip_stdio_during_bootstrap: self.skip_stdio_during_bootstrap,
|
skip_stdio_during_bootstrap: self.skip_stdio_during_bootstrap,
|
||||||
additional_imports: self.additional_imports.clone(),
|
additional_imports: self.additional_imports.clone(),
|
||||||
|
|||||||
@@ -11,15 +11,23 @@ impl<'a, 'c> JournalSyscallPlayer<'a, 'c> {
|
|||||||
) -> Result<(), WasiRuntimeError> {
|
) -> Result<(), WasiRuntimeError> {
|
||||||
tracing::trace!(%fd, %offset, "Replay journal - FdWrite");
|
tracing::trace!(%fd, %offset, "Replay journal - FdWrite");
|
||||||
if self.stdout_fds.contains(&fd) {
|
if self.stdout_fds.contains(&fd) {
|
||||||
self.stdout
|
if let Some(x) = self.stdout.as_mut() {
|
||||||
.as_mut()
|
x.push(JournalStdIoWrite {
|
||||||
.map(|x| x.push((offset, data, is_64bit)));
|
offset,
|
||||||
|
data,
|
||||||
|
is_64bit,
|
||||||
|
});
|
||||||
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
if self.stderr_fds.contains(&fd) {
|
if self.stderr_fds.contains(&fd) {
|
||||||
self.stderr
|
if let Some(x) = self.stdout.as_mut() {
|
||||||
.as_mut()
|
x.push(JournalStdIoWrite {
|
||||||
.map(|x| x.push((offset, data, is_64bit)));
|
offset,
|
||||||
|
data,
|
||||||
|
is_64bit,
|
||||||
|
});
|
||||||
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ mod update_memory;
|
|||||||
|
|
||||||
use crate::journal::JournalEffector;
|
use crate::journal::JournalEffector;
|
||||||
use crate::syscalls::anyhow_err_to_runtime_err;
|
use crate::syscalls::anyhow_err_to_runtime_err;
|
||||||
use crate::syscalls::JournalSyscallPlayer;
|
use crate::syscalls::{JournalStdIoWrite, JournalSyscallPlayer};
|
||||||
use crate::RewindState;
|
use crate::RewindState;
|
||||||
use crate::WasiRuntimeError;
|
use crate::WasiRuntimeError;
|
||||||
use crate::WasiThreadId;
|
use crate::WasiThreadId;
|
||||||
|
|||||||
@@ -8,11 +8,15 @@ impl<'a, 'c> JournalSyscallPlayer<'a, 'c> {
|
|||||||
tracing::trace!("Replay journal - ClearEthereal");
|
tracing::trace!("Replay journal - ClearEthereal");
|
||||||
self.spawn_threads.clear();
|
self.spawn_threads.clear();
|
||||||
|
|
||||||
self.stdout.as_mut().map(|x| x.clear());
|
if let Some(x) = self.stdout.as_mut() {
|
||||||
|
x.clear();
|
||||||
|
}
|
||||||
self.stdout_fds.clear();
|
self.stdout_fds.clear();
|
||||||
self.stdout_fds.insert(1 as WasiFd);
|
self.stdout_fds.insert(1 as WasiFd);
|
||||||
|
|
||||||
self.stderr.as_mut().map(|x| x.clear());
|
if let Some(x) = self.stderr.as_mut() {
|
||||||
|
x.clear();
|
||||||
|
}
|
||||||
self.stderr_fds.clear();
|
self.stderr_fds.clear();
|
||||||
self.stderr_fds.insert(2 as WasiFd);
|
self.stderr_fds.insert(2 as WasiFd);
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,12 @@ use std::{collections::BTreeMap, ops::Range};
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
pub struct JournalStdIoWrite<'a> {
|
||||||
|
pub offset: u64,
|
||||||
|
pub data: Cow<'a, [u8]>,
|
||||||
|
pub is_64bit: bool,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct JournalSyscallPlayer<'a, 'c> {
|
pub struct JournalSyscallPlayer<'a, 'c> {
|
||||||
pub ctx: FunctionEnvMut<'c, WasiEnv>,
|
pub ctx: FunctionEnvMut<'c, WasiEnv>,
|
||||||
pub bootstrapping: bool,
|
pub bootstrapping: bool,
|
||||||
@@ -45,8 +51,8 @@ pub struct JournalSyscallPlayer<'a, 'c> {
|
|||||||
pub differ_memory: Vec<(Range<u64>, Cow<'a, [u8]>)>,
|
pub differ_memory: Vec<(Range<u64>, Cow<'a, [u8]>)>,
|
||||||
|
|
||||||
// We capture the stdout and stderr while we replay
|
// We capture the stdout and stderr while we replay
|
||||||
pub stdout: Option<Vec<(u64, Cow<'a, [u8]>, bool)>>,
|
pub stdout: Option<Vec<JournalStdIoWrite<'a>>>,
|
||||||
pub stderr: Option<Vec<(u64, Cow<'a, [u8]>, bool)>>,
|
pub stderr: Option<Vec<JournalStdIoWrite<'a>>>,
|
||||||
pub stdout_fds: HashSet<u32>,
|
pub stdout_fds: HashSet<u32>,
|
||||||
pub stderr_fds: HashSet<u32>,
|
pub stderr_fds: HashSet<u32>,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,12 @@ pub unsafe fn restore_snapshot(
|
|||||||
// Now output the stdout and stderr
|
// Now output the stdout and stderr
|
||||||
if let Some(stdout) = runner.stdout {
|
if let Some(stdout) = runner.stdout {
|
||||||
tracing::trace!("replaying stdout");
|
tracing::trace!("replaying stdout");
|
||||||
for (offset, data, is_64bit) in stdout {
|
for JournalStdIoWrite {
|
||||||
|
offset,
|
||||||
|
data,
|
||||||
|
is_64bit,
|
||||||
|
} in stdout
|
||||||
|
{
|
||||||
if is_64bit {
|
if is_64bit {
|
||||||
JournalEffector::apply_fd_write::<Memory64>(&mut runner.ctx, 1, offset, data)
|
JournalEffector::apply_fd_write::<Memory64>(&mut runner.ctx, 1, offset, data)
|
||||||
} else {
|
} else {
|
||||||
@@ -48,7 +53,12 @@ pub unsafe fn restore_snapshot(
|
|||||||
|
|
||||||
if let Some(stderr) = runner.stderr {
|
if let Some(stderr) = runner.stderr {
|
||||||
tracing::trace!("replaying stderr");
|
tracing::trace!("replaying stderr");
|
||||||
for (offset, data, is_64bit) in stderr {
|
for JournalStdIoWrite {
|
||||||
|
offset,
|
||||||
|
data,
|
||||||
|
is_64bit,
|
||||||
|
} in stderr
|
||||||
|
{
|
||||||
if is_64bit {
|
if is_64bit {
|
||||||
JournalEffector::apply_fd_write::<Memory64>(&mut runner.ctx, 2, offset, data)
|
JournalEffector::apply_fd_write::<Memory64>(&mut runner.ctx, 2, offset, data)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -42,7 +42,12 @@ pub(crate) fn fd_renumber_internal(
|
|||||||
let (_, mut state) = unsafe { env.get_memory_and_wasi_state(&ctx, 0) };
|
let (_, mut state) = unsafe { env.get_memory_and_wasi_state(&ctx, 0) };
|
||||||
|
|
||||||
if state.fs.get_fd(to).is_ok() {
|
if state.fs.get_fd(to).is_ok() {
|
||||||
wasi_try_ok!(__asyncify_light(env, None, state.fs.flush(to))?);
|
match __asyncify_light(env, None, state.fs.flush(to))? {
|
||||||
|
Ok(_) | Err(Errno::Isdir) | Err(Errno::Io) | Err(Errno::Access) => {}
|
||||||
|
Err(e) => {
|
||||||
|
return Ok(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
wasi_try_ok!(state.fs.close_fd(to));
|
wasi_try_ok!(state.fs.close_fd(to));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ use crate::syscalls::*;
|
|||||||
pub fn proc_snapshot<M: MemorySize>(
|
pub fn proc_snapshot<M: MemorySize>(
|
||||||
mut ctx: FunctionEnvMut<'_, WasiEnv>,
|
mut ctx: FunctionEnvMut<'_, WasiEnv>,
|
||||||
) -> Result<Errno, WasiError> {
|
) -> Result<Errno, WasiError> {
|
||||||
wasi_try_ok!(maybe_snapshot_once::<M>(ctx, SnapshotTrigger::Explicit)?);
|
// If we have an Explicit trigger, process that...
|
||||||
|
ctx = wasi_try_ok!(maybe_snapshot_once::<M>(ctx, SnapshotTrigger::Explicit)?);
|
||||||
|
// ... if not, we may still have an external request for a snapshot, so do that as well
|
||||||
|
ctx = wasi_try_ok!(maybe_snapshot::<M>(ctx)?);
|
||||||
Ok(Errno::Success)
|
Ok(Errno::Success)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user