mirror of
https://github.com/urbit/ares.git
synced 2024-11-22 15:08:54 +03:00
Add SIGINT handler
This commit is contained in:
parent
0072e09a85
commit
ae674c1372
@ -35,7 +35,7 @@
|
||||
:: %mean hint
|
||||
~_ [%leaf "I am a %mean hint via ~_ from +wack"]
|
||||
:: %hela hint
|
||||
:: ~> %hela
|
||||
~> %hela
|
||||
:: %memo hint
|
||||
~+
|
||||
?~ m +(n)
|
||||
@ -47,13 +47,23 @@
|
||||
!.
|
||||
|= [m=@ud n=@ud]
|
||||
:: %hela hint
|
||||
:: ~> %hela
|
||||
~> %hela
|
||||
:: %memo hint
|
||||
~+
|
||||
?~ m +(n)
|
||||
?~ n
|
||||
(wack (dec m) 1)
|
||||
(wack (dec m) $(n (dec n)))
|
||||
++ slow
|
||||
|= x=@ud
|
||||
!:
|
||||
(slow-help x 0)
|
||||
++ slow-help
|
||||
|= [x=@ud y=@ud]
|
||||
!.
|
||||
?: .= x y
|
||||
x
|
||||
$(y .+(y))
|
||||
-- =>
|
||||
::
|
||||
|%
|
||||
@ -65,19 +75,23 @@
|
||||
^- ^
|
||||
::
|
||||
?. ?=(?(%crud %wack %wyrd) p.card.ovo)
|
||||
~> %slog.[0 leaf+(scow %ud (wack 1 1))]
|
||||
~> %slog.[0 leaf+(scow %ud (slow (bex 23)))]
|
||||
[~ ..poke]
|
||||
::
|
||||
=/ buz
|
||||
~> %mean.'pith: bad wasp'
|
||||
;;(wasp card.ovo)
|
||||
?+ -.buz
|
||||
~> %slog.[0 leaf+"default $wasp"]
|
||||
~> %slog.[0 leaf+(scow %ud (wack 1 1))]
|
||||
[~ ..poke]
|
||||
::
|
||||
%crud
|
||||
~> %slog.[0 goof.buz]
|
||||
[~ ..poke]
|
||||
=/ tang tang.goof.buz
|
||||
|-
|
||||
?~ tang
|
||||
[~ ..poke]
|
||||
~> %slog.[0 -.tang]
|
||||
$(tang +.tang)
|
||||
==
|
||||
--
|
||||
::
|
||||
|
21
rust/ares/Cargo.lock
generated
21
rust/ares/Cargo.lock
generated
@ -20,11 +20,13 @@ dependencies = [
|
||||
"either",
|
||||
"ibig",
|
||||
"intmap",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"memmap",
|
||||
"murmur3",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
"signal-hook",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
@ -569,6 +571,25 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"signal-hook-registry",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
|
@ -11,18 +11,20 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
ares_macros = { path = "../ares_macros" }
|
||||
bitvec = "1.0.0"
|
||||
either = "1.9.0"
|
||||
libc = "0.2.126"
|
||||
murmur3 = { git = "https://github.com/tloncorp/murmur3", rev = "7878a0f" }
|
||||
memmap = "0.7.0"
|
||||
intmap = "1.1.0"
|
||||
num-traits = "0.2"
|
||||
num-derive = "0.3"
|
||||
criterion = "0.4"
|
||||
static_assertions = "1.1.0"
|
||||
ibig = { path = "../ibig-rs" }
|
||||
assert_no_alloc = "1.1.2"
|
||||
bitvec = "1.0.0"
|
||||
criterion = "0.4"
|
||||
either = "1.9.0"
|
||||
ibig = { path = "../ibig-rs" }
|
||||
intmap = "1.1.0"
|
||||
lazy_static = "1.4.0"
|
||||
libc = "0.2.126"
|
||||
memmap = "0.7.0"
|
||||
murmur3 = { git = "https://github.com/tloncorp/murmur3", rev = "7878a0f" }
|
||||
num-derive = "0.3"
|
||||
num-traits = "0.2"
|
||||
signal-hook = "0.3"
|
||||
static_assertions = "1.1.0"
|
||||
|
||||
[build-dependencies]
|
||||
cc = "1.0.79"
|
||||
|
@ -7,10 +7,13 @@ use crate::mem::NockStack;
|
||||
use crate::newt::Newt;
|
||||
use crate::noun;
|
||||
use crate::noun::{tape, Atom, Cell, IndirectAtom, Noun, Slots, D, T};
|
||||
use crate::serf::TERMINATOR;
|
||||
use ares_macros::tas;
|
||||
use assert_no_alloc::assert_no_alloc;
|
||||
use bitvec::prelude::{BitSlice, Lsb0};
|
||||
use either::Either::*;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
|
||||
crate::gdb!();
|
||||
|
||||
@ -265,10 +268,12 @@ pub fn interpret(
|
||||
mut subject: Noun,
|
||||
formula: Noun,
|
||||
) -> Result<Noun, Tone> {
|
||||
let terminator = Arc::clone(&TERMINATOR);
|
||||
let mut res: Noun = D(0);
|
||||
let mut cache = Hamt::<Noun>::new();
|
||||
// XX: Should this come after initial frame_push()?
|
||||
let virtual_frame = stack.get_frame_pointer();
|
||||
let virtual_trace = stack.get_mean_stack();
|
||||
|
||||
stack.frame_push(0);
|
||||
unsafe {
|
||||
@ -323,6 +328,7 @@ pub fn interpret(
|
||||
res = noun;
|
||||
stack.pop::<NockWork>();
|
||||
} else {
|
||||
// Axis invalid for input Noun
|
||||
break Err(NockErr::Deterministic);
|
||||
}
|
||||
}
|
||||
@ -330,37 +336,43 @@ pub fn interpret(
|
||||
res = once.noun;
|
||||
stack.pop::<NockWork>();
|
||||
}
|
||||
NockWork::Work2(mut vale) => match vale.todo {
|
||||
Todo2::ComputeSubject => {
|
||||
vale.todo = Todo2::ComputeFormula;
|
||||
*stack.top() = NockWork::Work2(vale);
|
||||
push_formula(stack, vale.subject, false)?;
|
||||
NockWork::Work2(mut vale) => {
|
||||
if (*terminator).load(Ordering::Relaxed) {
|
||||
break Err(NockErr::NonDeterministic);
|
||||
}
|
||||
Todo2::ComputeFormula => {
|
||||
vale.todo = Todo2::ComputeResult;
|
||||
vale.subject = res;
|
||||
*stack.top() = NockWork::Work2(vale);
|
||||
push_formula(stack, vale.formula, false)?;
|
||||
}
|
||||
Todo2::ComputeResult => {
|
||||
if vale.tail {
|
||||
stack.pop::<NockWork>();
|
||||
subject = vale.subject;
|
||||
push_formula(stack, res, true)?;
|
||||
} else {
|
||||
vale.todo = Todo2::RestoreSubject;
|
||||
std::mem::swap(&mut vale.subject, &mut subject);
|
||||
|
||||
match vale.todo {
|
||||
Todo2::ComputeSubject => {
|
||||
vale.todo = Todo2::ComputeFormula;
|
||||
*stack.top() = NockWork::Work2(vale);
|
||||
stack.frame_push(0);
|
||||
*stack.push() = NockWork::Ret;
|
||||
push_formula(stack, res, true)?;
|
||||
push_formula(stack, vale.subject, false)?;
|
||||
}
|
||||
Todo2::ComputeFormula => {
|
||||
vale.todo = Todo2::ComputeResult;
|
||||
vale.subject = res;
|
||||
*stack.top() = NockWork::Work2(vale);
|
||||
push_formula(stack, vale.formula, false)?;
|
||||
}
|
||||
Todo2::ComputeResult => {
|
||||
if vale.tail {
|
||||
stack.pop::<NockWork>();
|
||||
subject = vale.subject;
|
||||
push_formula(stack, res, true)?;
|
||||
} else {
|
||||
vale.todo = Todo2::RestoreSubject;
|
||||
std::mem::swap(&mut vale.subject, &mut subject);
|
||||
*stack.top() = NockWork::Work2(vale);
|
||||
stack.frame_push(0);
|
||||
*stack.push() = NockWork::Ret;
|
||||
push_formula(stack, res, true)?;
|
||||
}
|
||||
}
|
||||
Todo2::RestoreSubject => {
|
||||
subject = vale.subject;
|
||||
stack.pop::<NockWork>();
|
||||
}
|
||||
}
|
||||
Todo2::RestoreSubject => {
|
||||
subject = vale.subject;
|
||||
stack.pop::<NockWork>();
|
||||
}
|
||||
},
|
||||
}
|
||||
NockWork::Work3(mut thee) => match thee.todo {
|
||||
Todo3::ComputeChild => {
|
||||
thee.todo = Todo3::ComputeType;
|
||||
@ -481,37 +493,43 @@ pub fn interpret(
|
||||
stack.pop::<NockWork>();
|
||||
}
|
||||
},
|
||||
NockWork::Work9(mut kale) => match kale.todo {
|
||||
Todo9::ComputeCore => {
|
||||
kale.todo = Todo9::ComputeResult;
|
||||
*stack.top() = NockWork::Work9(kale);
|
||||
push_formula(stack, kale.core, false)?;
|
||||
NockWork::Work9(mut kale) => {
|
||||
if (*terminator).load(Ordering::Relaxed) {
|
||||
break Err(NockErr::NonDeterministic);
|
||||
}
|
||||
Todo9::ComputeResult => {
|
||||
if let Ok(formula) = res.slot_atom(kale.axis) {
|
||||
if kale.tail {
|
||||
stack.pop::<NockWork>();
|
||||
subject = res;
|
||||
push_formula(stack, formula, true)?;
|
||||
|
||||
match kale.todo {
|
||||
Todo9::ComputeCore => {
|
||||
kale.todo = Todo9::ComputeResult;
|
||||
*stack.top() = NockWork::Work9(kale);
|
||||
push_formula(stack, kale.core, false)?;
|
||||
}
|
||||
Todo9::ComputeResult => {
|
||||
if let Ok(formula) = res.slot_atom(kale.axis) {
|
||||
if kale.tail {
|
||||
stack.pop::<NockWork>();
|
||||
subject = res;
|
||||
push_formula(stack, formula, true)?;
|
||||
} else {
|
||||
kale.todo = Todo9::RestoreSubject;
|
||||
kale.core = subject;
|
||||
*stack.top() = NockWork::Work9(kale);
|
||||
subject = res;
|
||||
stack.frame_push(0);
|
||||
*stack.push() = NockWork::Ret;
|
||||
push_formula(stack, formula, true)?;
|
||||
}
|
||||
} else {
|
||||
kale.todo = Todo9::RestoreSubject;
|
||||
kale.core = subject;
|
||||
*stack.top() = NockWork::Work9(kale);
|
||||
subject = res;
|
||||
stack.frame_push(0);
|
||||
*stack.push() = NockWork::Ret;
|
||||
push_formula(stack, formula, true)?;
|
||||
// Axis into core must be atom
|
||||
break Err(NockErr::Deterministic);
|
||||
}
|
||||
} else {
|
||||
// Axis into core must be atom
|
||||
break Err(NockErr::Deterministic);
|
||||
}
|
||||
Todo9::RestoreSubject => {
|
||||
subject = kale.core;
|
||||
stack.pop::<NockWork>();
|
||||
}
|
||||
}
|
||||
Todo9::RestoreSubject => {
|
||||
subject = kale.core;
|
||||
stack.pop::<NockWork>();
|
||||
}
|
||||
},
|
||||
}
|
||||
NockWork::Work10(mut diet) => {
|
||||
match diet.todo {
|
||||
Todo10::ComputeTree => {
|
||||
@ -623,7 +641,13 @@ pub fn interpret(
|
||||
|
||||
match nock {
|
||||
Ok(res) => Ok(res),
|
||||
Err(err) => Err(exit_early(stack, &mut cache, virtual_frame, err)),
|
||||
Err(err) => Err(exit_early(
|
||||
stack,
|
||||
&mut cache,
|
||||
virtual_frame,
|
||||
virtual_trace,
|
||||
err,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -830,6 +854,7 @@ pub fn exit_early(
|
||||
stack: &mut NockStack,
|
||||
cache: &mut Hamt<Noun>,
|
||||
virtual_frame: *const u64,
|
||||
virtual_trace: Noun,
|
||||
error: NockErr,
|
||||
) -> Tone {
|
||||
let mut trace = stack.get_mean_stack();
|
||||
@ -839,6 +864,9 @@ pub fn exit_early(
|
||||
stack.preserve(cache);
|
||||
stack.frame_pop();
|
||||
}
|
||||
while !stack.get_mean_stack().raw_equals(virtual_trace) {
|
||||
stack.trace_pop();
|
||||
}
|
||||
};
|
||||
Tone::Error(error, trace)
|
||||
}
|
||||
@ -1026,6 +1054,11 @@ fn match_hint_pre_nock(
|
||||
Ok(None)
|
||||
}
|
||||
tas!(b"hand") | tas!(b"hunk") | tas!(b"lose") | tas!(b"mean") | tas!(b"spot") => {
|
||||
let terminator = Arc::clone(&TERMINATOR);
|
||||
if (*terminator).load(Ordering::Relaxed) {
|
||||
return Err(NockErr::NonDeterministic);
|
||||
}
|
||||
|
||||
let trace = T(stack, &[tag.as_noun(), res.ok_or(NockErr::Deterministic)?]);
|
||||
stack.trace_push(trace);
|
||||
Ok(None)
|
||||
|
@ -10,7 +10,7 @@ use crate::noun::{Noun, D, T};
|
||||
|
||||
crate::gdb!();
|
||||
|
||||
// XX: interpret should accept optional scry function and potentially produce blocked
|
||||
// XX: interpret should accept optional scry function and potentially produce blocked
|
||||
pub fn jet_mink(
|
||||
stack: &mut NockStack,
|
||||
newt: &mut Option<&mut Newt>,
|
||||
@ -23,6 +23,7 @@ pub fn jet_mink(
|
||||
let v_formula = slot(arg, 5)?;
|
||||
let _scry = slot(arg, 3)?;
|
||||
|
||||
// XX: no partial traces; all of our traces go down to the "home road"
|
||||
match interpret(stack, newt, v_subject, v_formula) {
|
||||
Ok(res) => Ok(T(stack, &[D(0), res])),
|
||||
Err(err) => match err {
|
||||
@ -61,11 +62,6 @@ pub mod util {
|
||||
let tag = tone.head().as_direct()?;
|
||||
let original_list = tone.tail();
|
||||
|
||||
// if tag.data() < 2 {
|
||||
// return Ok(tone);
|
||||
// } else if tag.data() > 2 {
|
||||
// return Err(JetErr::Deterministic);
|
||||
// }
|
||||
match tag.data() {
|
||||
x if x < 2 => return Ok(tone),
|
||||
x if x > 2 => return Err(JetErr::Deterministic),
|
||||
@ -260,6 +256,21 @@ pub mod util {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::jets::util::test::{assert_jet, init_stack};
|
||||
use crate::serf::TERMINATOR;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[test]
|
||||
fn init() {
|
||||
// This needs to be done because TERMINATOR is lazy allocated, and if you don't
|
||||
// do it before you call the unit tests it'll get allocated on the Rust heap
|
||||
// inside an assert_no_alloc block.
|
||||
//
|
||||
// Also Rust has no primitive for pre-test setup / post-test teardown, so we
|
||||
// do it in a test that we rely on being called before any other in this file,
|
||||
// since we're already using single-threaded test mode to avoid race conditions
|
||||
// (because Rust doesn't support test order dependencies either).
|
||||
let _ = Arc::clone(&TERMINATOR);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mink_success() {
|
||||
|
@ -1,5 +1,7 @@
|
||||
extern crate num_derive;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
#[macro_use]
|
||||
extern crate static_assertions;
|
||||
pub mod interpreter;
|
||||
pub mod jets;
|
||||
|
@ -7,12 +7,14 @@ use crate::newt::Newt;
|
||||
use crate::noun::{Cell, Noun, Slots, D, T};
|
||||
use crate::snapshot::{self, Snapshot};
|
||||
use ares_macros::tas;
|
||||
use signal_hook;
|
||||
use signal_hook::consts::SIGINT;
|
||||
use std::fs::create_dir_all;
|
||||
use std::io;
|
||||
use std::path::PathBuf;
|
||||
use std::result::Result;
|
||||
use std::thread::sleep;
|
||||
use std::time;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
crate::gdb!();
|
||||
|
||||
@ -23,12 +25,20 @@ const POKE_AXIS: u64 = 23;
|
||||
#[allow(dead_code)]
|
||||
const WISH_AXIS: u64 = 10;
|
||||
|
||||
// Necessary because Arc::new is not const
|
||||
lazy_static! {
|
||||
pub static ref TERMINATOR: Arc<AtomicBool> = Arc::new(AtomicBool::new(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* This is suitable for talking to the king process. To test, change the arg_c[0] line in
|
||||
* u3_lord_init in vere to point at this binary and start vere like normal.
|
||||
*/
|
||||
pub fn serf() -> io::Result<()> {
|
||||
sleep(time::Duration::from_secs(0));
|
||||
// Register SIGTERM signal hook to set flag first time, shutdown second time
|
||||
signal_hook::flag::register_conditional_shutdown(SIGINT, 1, Arc::clone(&TERMINATOR))?;
|
||||
signal_hook::flag::register(SIGINT, Arc::clone(&TERMINATOR))?;
|
||||
|
||||
let snap_path_string = std::env::args()
|
||||
.nth(2)
|
||||
.ok_or(io::Error::new(io::ErrorKind::Other, "no pier path"))?;
|
||||
@ -157,7 +167,9 @@ pub fn serf() -> io::Result<()> {
|
||||
// TODO: on decryption failure in aes_siv, should bail as fast as
|
||||
// possible, without rendering stack trace or injecting crud event. See
|
||||
// c3__evil in vere.
|
||||
//
|
||||
|
||||
clear_interrupt();
|
||||
|
||||
// crud = [+(now) [%$ %arvo ~] [%crud goof ovo]]
|
||||
let job_cell = job.as_cell().expect("serf: work: job not a cell");
|
||||
let now = inc(
|
||||
@ -197,6 +209,8 @@ pub fn serf() -> io::Result<()> {
|
||||
}
|
||||
_ => panic!("got message with unknown tag {}", tag),
|
||||
};
|
||||
|
||||
clear_interrupt();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -231,8 +245,9 @@ pub fn soft(
|
||||
let tang = mook(stack, &mut Some(newt), tone, false)
|
||||
.expect("serf: soft: +mook crashed on bail")
|
||||
.tail();
|
||||
// TODO: shouldn't always be exit, look at the comment by u3m_bail to see how vere
|
||||
// handles this
|
||||
// XX: noun::Tone or noun::NockErr should use a bail enum system similar to u3m_bail motes;
|
||||
// might be able to replace NockErr with mote and map determinism to individual motes;
|
||||
// for, always set to %exit
|
||||
let goof = T(stack, &[D(tas!(b"exit")), tang]);
|
||||
Err(goof)
|
||||
}
|
||||
@ -244,3 +259,7 @@ fn slot(noun: Noun, axis: u64) -> io::Result<Noun> {
|
||||
noun.slot(axis)
|
||||
.map_err(|_e| io::Error::new(io::ErrorKind::InvalidInput, "Bad axis"))
|
||||
}
|
||||
|
||||
fn clear_interrupt() {
|
||||
(*TERMINATOR).store(false, Ordering::Relaxed);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user