/* * Deliver the received signal to curthread */ static void deliver_signal() { int sig = pid_get_signal(curthread->t_pid); KASSERT(sig >= 0); /* the ignored signals */ if (sig & 1 << SIGWINCH || sig & 1 << SIGINFO) { DEBUG(DB_THREADS, "\ndelivering SIGINCH/INFO to pid %d.\n", curthread->t_pid); return; } /* thread terminating signal */ if (sig & 1 << SIGKILL || sig & 1 << SIGSTOP || sig & 1 << SIGINT || sig & 1 << SIGQUIT) { DEBUG(DB_THREADS, "\ndelivering SIGKILL/INFO/INT/QUIT to pid %d.\n", curthread->t_pid); thread_exit(_MKWAIT_SIG(0)); panic("panic when delivering signal\n"); } if (sig & 1 << SIGSTOP) { DEBUG(DB_THREADS, "\ndelivering SIGSTOP to pid %d.\n", curthread->t_pid); lock_acquire(sleeplock); cv_wait(sleepers, sleeplock); lock_release(sleeplock); } }
void sys_exit(int exitcode, bool is_sig){ lock_acquire(curproc->exitlock); for (int fd = 0; fd < OPEN_MAX; fd++) { int err; sys_close(fd, &err); } curproc->exit_flag = true; if (is_sig) { curproc->exit_code = _MKWAIT_SIG(exitcode); } else { curproc->exit_code = _MKWAIT_EXIT(exitcode); } if (proc_ids[curproc->ppid]->exit_flag == false) { cv_broadcast(curproc->exitcv, curproc->exitlock); lock_release(curproc->exitlock); } else { /* Clean Up */ lock_release(curproc->exitlock); cv_destroy(curproc->exitcv); as_destroy(curproc->p_addrspace); kfree(proc_ids[curproc->pid]->p_name); curproc->p_addrspace = NULL; kfree(proc_ids[curproc->pid]); proc_ids[curproc->pid] = NULL; lock_destroy(curproc->exitlock); } thread_exit(); }
/* * Function called when user-level code hits a fatal fault. */ static void kill_curthread(vaddr_t epc, unsigned code, vaddr_t vaddr) { int sig = 0; KASSERT(code < NTRAPCODES); switch (code) { case EX_IRQ: case EX_IBE: case EX_DBE: case EX_SYS: /* should not be seen */ KASSERT(0); sig = SIGABRT; break; case EX_MOD: case EX_TLBL: case EX_TLBS: sig = SIGSEGV; break; case EX_ADEL: case EX_ADES: sig = SIGBUS; break; case EX_BP: sig = SIGTRAP; break; case EX_RI: sig = SIGILL; break; case EX_CPU: sig = SIGSEGV; break; case EX_OVF: sig = SIGFPE; break; } /* * You will probably want to change this. */ kprintf("Fatal user mode trap %u sig %d (%s, epc 0x%x, vaddr 0x%x)\n", code, sig, trapcodenames[code], epc, vaddr); //panic("I don't know how to handle this\n"); thread_exit(_MKWAIT_SIG(sig)); }
/* Handle the signal for a thread with given pid. */ void pid_handlesignal(pid_t pid) { /* Obtain process information of target thread. */ struct pidinfo *pinfo; lock_acquire(pidlock); pinfo = pi_get(pid); /* Check if the thread associated with pid was found */ KASSERT(pinfo != NULL); /* Handle signal. */ if (pinfo->sigkill > 0) { /* Order the thread to exit */ lock_release(pidlock); thread_exit(_MKWAIT_SIG(pinfo->sigkill)); } else if (pinfo->sigstop) { /* Order the thread to sleep, and set the sigstop * flag to false when woken up */ cv_wait(pinfo->pi_signal_cv, pidlock); pinfo->sigstop = false; } lock_release(pidlock); }
void run_process(void *ptr, unsigned long num) { (void)num; int result; vaddr_t entrypoint, stackptr; // extract and free passed-in context struct new_process_context *ctxt = (struct new_process_context *)ptr; struct process *proc = ctxt->proc; struct vnode *v = ctxt->executable; int nargs = ctxt->nargs; char **args = ctxt->args; kfree(ctxt); // attach process to thread curthread->t_proc = proc; proc->ps_thread = curthread; // Activate address space as_activate(proc->ps_addrspace); // Load the executable result = load_elf(v, &entrypoint); if (result) { vfs_close(v); kprintf("runprogram failed: %s\n", strerror(result)); // alert the kernel menu that the process aborted process_finish(proc, _MKWAIT_SIG(SIGABRT)); return; } // Done with the file now vfs_close(v); // Define the user stack in the address space result = as_define_stack(proc->ps_addrspace, &stackptr); if (result) { kprintf("runprogram failed: %s\n", strerror(result)); // alert the kernel menu that the process aborted process_finish(proc, _MKWAIT_SIG(SIGABRT)); return; } // Copy out arguments userptr_t uargv[nargs + 1]; for (int i = 0; i < nargs; i++) { int aligned_length = WORD_ALIGN(strlen(args[i]) + 1); stackptr -= aligned_length; uargv[i] = (userptr_t)stackptr; size_t arg_len; result = copyoutstr(args[i], uargv[i], strlen(args[i]) + 1, &arg_len); if (result) { kprintf("runprogram failed: %s\n", strerror(result)); // alert the kernel menu that the process aborted process_finish(proc, _MKWAIT_SIG(SIGABRT)); return; } } uargv[nargs] =(userptr_t)NULL; // Copy out the argv array itself stackptr -= (nargs + 1) * sizeof(userptr_t); result = copyout(uargv, (userptr_t)stackptr, (nargs + 1) * sizeof(userptr_t)); if (result) { kprintf("runprogram failed: %s\n", strerror(result)); // alert the kernel menu that the process aborted process_finish(proc, _MKWAIT_SIG(SIGABRT)); return; } enter_new_process(nargs, (userptr_t)stackptr, stackptr, entrypoint); // enter_new_process() does not return panic("enter_new_process returned\n"); }
/* * Function called when user-level code hits a fatal fault. */ static void kill_curthread(vaddr_t epc, unsigned code, vaddr_t vaddr) { int sig = 0; KASSERT(code < NTRAPCODES); switch (code) { case EX_IRQ: case EX_IBE: case EX_DBE: case EX_SYS: /* should not be seen */ KASSERT(0); sig = SIGABRT; break; case EX_MOD: case EX_TLBL: case EX_TLBS: sig = SIGSEGV; break; case EX_ADEL: case EX_ADES: sig = SIGBUS; break; case EX_BP: sig = SIGTRAP; break; case EX_RI: sig = SIGILL; break; case EX_CPU: sig = SIGSEGV; break; case EX_OVF: sig = SIGFPE; break; } /* * You will probably want to change this. */ #if OPT_A3 (void)epc; (void)vaddr; struct addrspace *as; struct proc *p = curproc; int parentLocation = locatePid(p->p_pid); struct procStruct *parentProcStr = array_get(procStructArray, parentLocation); parentProcStr->exitcode = _MKWAIT_SIG(sig); cleanChildren(parentLocation); V(parentProcStr->proc_sem); KASSERT(curproc->p_addrspace != NULL); as_deactivate(); /* * clear p_addrspace before calling as_destroy. Otherwise if * as_destroy sleeps (which is quite possible) when we * come back we'll be calling as_activate on a * half-destroyed address space. This tends to be * messily fatal. */ as = curproc_setas(NULL); as_destroy(as); /* detach this thread from its process */ /* note: curproc cannot be used after this call */ proc_remthread(curthread); /* if this is the last user process in the system, proc_destroy() will wake up the kernel menu thread */ proc_destroy(p); thread_exit(); /* thread_exit() does not return, so we should never get here */ panic("return from thread_exit in sys_exit\n"); #else kprintf("Fatal user mode trap %u sig %d (%s, epc 0x%x, vaddr 0x%x)\n", code, sig, trapcodenames[code], epc, vaddr); panic("I don't know how to handle this\n"); #endif }