Exemple #1
0
/*
 * 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);
	}
}
Exemple #2
0
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));

}
Exemple #4
0
/* 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");
}
Exemple #6
0
/*
 * 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
}