ProcessStarting exception

This commit is contained in:
Ben Pig Chu 2020-07-16 18:00:15 +08:00
parent 24f5a4bbf0
commit 641181bdb8
6 changed files with 42 additions and 13 deletions

View File

@ -172,13 +172,19 @@ kcounter!(EXCEPTIONS_USER, "exceptions.user");
kcounter!(EXCEPTIONS_TIMER, "exceptions.timer");
kcounter!(EXCEPTIONS_PGFAULT, "exceptions.pgfault");
fn spawn(thread: Arc<Thread>) {
fn spawn(thread: Arc<Thread>,first_thread:bool) {
let vmtoken = thread.proc().vmar().table_phys();
let future = async move {
kernel_hal::Thread::set_tid(thread.id(), thread.proc().id());
let mut exit=false;
if first_thread {
let proc_start_exception=Exception::create(thread.clone(), ExceptionType::ProcessStarting,None);
if !proc_start_exception.handle_with_exceptionates(false,JobDebuggerIterator::new(thread.proc().job()),true).await{
exit=true;
}
};
let start_exception=Exception::create(thread.clone(), ExceptionType::ThreadStarting,None);
if !start_exception.handle_with_exceptionates(false,Some(thread.proc().get_debug_exceptionate())).await {
if !start_exception.handle_with_exceptionates(false,Some(thread.proc().get_debug_exceptionate()),false).await {
exit=true;
}
while !exit {

View File

@ -252,13 +252,15 @@ impl Exception {
/// Note that it's possible that this may returns before exception was send to any exception channel
/// This happens only when the thread is killed before we send the exception
pub async fn handle(self: &Arc<Self>,fatal:bool) -> bool {
self.handle_with_exceptionates(fatal,ExceptionateIterator::new(self)).await
self.handle_with_exceptionates(fatal,ExceptionateIterator::new(self),false).await
}
/// Same as handle, but use a customed iterator
pub async fn handle_with_exceptionates(self: &Arc<Self>,fatal:bool,exceptionates:impl IntoIterator<Item=Arc<Exceptionate>>) -> bool {
/// If first_only is true, this will only send exception to the first one that recieved the exception
/// even when the exception is not handled
pub async fn handle_with_exceptionates(self: &Arc<Self>,fatal:bool,exceptionates:impl IntoIterator<Item=Arc<Exceptionate>>,first_only:bool) -> bool {
self.thread.set_exception(Some(self.clone()));
let future = self.handle_internal(exceptionates);
let future = self.handle_internal(exceptionates,first_only);
pin_mut!(future);
let result: ZxResult = self
.thread
@ -288,7 +290,7 @@ impl Exception {
true
}
async fn handle_internal(self: &Arc<Self>,exceptionates:impl IntoIterator<Item=Arc<Exceptionate>>) -> ZxResult {
async fn handle_internal(self: &Arc<Self>,exceptionates:impl IntoIterator<Item=Arc<Exceptionate>>,first_only:bool) -> ZxResult {
for exceptionate in exceptionates.into_iter() {
let closed = match exceptionate.send_exception(self) {
Ok(receiver) => receiver,
@ -304,7 +306,7 @@ impl Exception {
inner.current_channel_type = ExceptionChannelType::None;
inner.handled
};
if handled {
if handled | first_only {
return Ok(());
}
}
@ -431,3 +433,23 @@ impl<'a> Iterator for ExceptionateIterator<'a> {
}
}
}
/// This is only used by ProcessStarting exceptions
pub struct JobDebuggerIterator {
job: Option<Arc<Job>>
}
impl JobDebuggerIterator {
pub fn new(job: Arc<Job>)->Self {
JobDebuggerIterator{job:Some(job)}
}
}
impl Iterator for JobDebuggerIterator {
type Item = Arc<Exceptionate>;
fn next(&mut self) -> Option<Self::Item> {
let result=self.job.as_ref().map(|job|job.get_debug_exceptionate());
self.job=self.job.as_ref().and_then(|job|job.parent());
result
}
}

View File

@ -141,7 +141,7 @@ impl Process {
stack: usize,
arg1: Option<Handle>,
arg2: usize,
spawn_fn: fn(thread: Arc<Thread>),
spawn_fn: fn(thread: Arc<Thread>,bool),
) -> ZxResult {
let handle_value;
{
@ -155,7 +155,7 @@ impl Process {
inner.status = Status::Running;
handle_value = arg1.map_or(INVALID_HANDLE, |handle| inner.add_handle(handle));
}
match thread.start(entry, stack, handle_value as usize, arg2, spawn_fn) {
match thread.start(entry, stack, handle_value as usize, arg2, spawn_fn,true) {
Ok(_) => Ok(()),
Err(err) => {
let mut inner = self.inner.lock();

View File

@ -179,7 +179,8 @@ impl Thread {
stack: usize,
arg1: usize,
arg2: usize,
spawn_fn: fn(thread: Arc<Thread>),
spawn_fn: fn(thread: Arc<Thread>,bool),
first_thread: bool
) -> ZxResult {
{
let mut inner = self.inner.lock();
@ -202,7 +203,7 @@ impl Thread {
inner.state = ThreadState::Running;
self.base.signal_set(Signal::THREAD_RUNNING);
}
spawn_fn(self.clone());
spawn_fn(self.clone(),first_thread);
Ok(())
}

View File

@ -50,7 +50,7 @@ use consts::SyscallType as Sys;
pub struct Syscall<'a> {
pub regs: &'a mut GeneralRegs,
pub thread: Arc<Thread>,
pub spawn_fn: fn(thread: Arc<Thread>),
pub spawn_fn: fn(thread: Arc<Thread>,first_thread:bool),
pub exit: bool,
}

View File

@ -153,7 +153,7 @@ impl Syscall<'_> {
if thread.proc().status() != Status::Running {
return Err(ZxError::BAD_STATE);
}
thread.start(entry, stack, arg1, arg2, self.spawn_fn)?;
thread.start(entry, stack, arg1, arg2, self.spawn_fn,false)?;
Ok(())
}