Log when processes exit unexpected
Unexpected exits are anything that isn't:
1. Status::Exit
2. An expected reason:
* `:normal`
* `:shutdown`
* `{:shutdown, term()}`
@@ -7,17 +7,19 @@ use hashbrown::HashMap;
use liblumen_core::locks::{Mutex, RwLock};
+use liblumen_alloc::erts::exception::runtime;
use liblumen_alloc::erts::process::code::Code;
#[cfg(test)]
use liblumen_alloc::erts::process::Priority;
-use liblumen_alloc::erts::process::ProcessControlBlock;
+use liblumen_alloc::erts::process::{ProcessControlBlock, Status};
pub use liblumen_alloc::erts::scheduler::{id, ID};
-use liblumen_alloc::erts::term::{reference, Atom, Reference, Term};
+use liblumen_alloc::erts::term::{reference, Atom, Reference, Term, TypedTerm};
use crate::process;
use crate::registry::put_pid_to_process;
use crate::run;
use crate::run::Run;
+use crate::system;
use crate::timer::Hierarchy;
pub trait Scheduled {
@@ -123,8 +125,25 @@ impl Scheduler {
}
match self.run_queues.write().requeue(arc_process) {
- // TODO exit logging
- Some(_exiting_arc_process) => {}
+ Some(exiting_arc_process) => match *exiting_arc_process.status.read() {
+ Status::Exiting(ref exception) => match exception.class {
+ runtime::Class::Exit => {
+ let reason = exception.reason;
+
+ if !is_expected_exit_reason(reason) {
+ system::io::puts(&format!(
+ "** (EXIT from {:?}) exited with reason: {:?}",
+ exiting_arc_process, reason
+ ));
+ }
+ }
+ runtime::Class::Error { .. } => {
+ system::io::puts(&format!("** (EXIT from {:?}) exited with reason: an exception was raised: {:?}", exiting_arc_process, exception.reason))
+ }
+ _ => unimplemented!("{:?}", exception),
+ },
+ _ => unreachable!(),
+ },
None => (),
};
@@ -288,6 +307,27 @@ lazy_static! {
Mutex::new(Default::default());
}
+fn is_expected_exit_reason(reason: Term) -> bool {
+ match reason.to_typed_term().unwrap() {
+ TypedTerm::Atom(atom) => match atom.name() {
+ "normal" | "shutdown" => true,
+ _ => false,
+ },
+ TypedTerm::Boxed(boxed) => match boxed.to_typed_term().unwrap() {
+ TypedTerm::Tuple(tuple) => {
+ tuple.len() == 2 && {
+ match tuple[0].to_typed_term().unwrap() {
+ TypedTerm::Atom(atom) => atom.name() == "shutdown",
+ _ => false,
+ }
+ }
+ }
+ _ => false,
+ },
+ _ => false,
+ }
+}
+
#[cfg(test)]
pub fn with_process<F>(f: F)
where
