/* terminate the currenct proccess into ZOMBIE, and tell its parent. * the struct proc is freed by each proc's parent. * */ int do_exit(int ret){ struct file *fp; struct proc *p; uint fd, nr; cu->p_ret = ret; // clear all the signal handlers for (nr=0; nr<NSIG; nr++) { cu->p_sigact[nr].sa_handler = SIG_DFL; cu->p_sigact[nr].sa_flags = 0; } // close all the opened files, and iput the directories. for (fd=0; fd<NOFILE; fd++){ fp = cu->p_ofile[fd]; if (fp != NULL) { do_close(fd); } cu->p_ofile[fd] = NULL; } iput(cu->p_iroot); iput(cu->p_wdir); // tell its parent sigsend(cu->p_ppid, SIGCHLD, 1); // free the address space vm_clear(&cu->p_vm); kfree(cu->p_vm.vm_pgd, PAGE); // make this process Zombie, give all the children to proc[1] // and tell its parent cu->p_chan = 0; cu->p_stat = SZOMB; for (nr=1; nr<NPROC; nr++) { if ((p=proc[nr]) && p!=cu && (p->p_ppid==cu->p_pid)) { p->p_ppid = 1; } } // wakeup proc[1] and its parent p = proc[cu->p_ppid]; wakeup(p); wakeup(proc[1]); return 0; }
/* initialize a new struct vm according to an a.out executable * image. * returns NULL on fail. * the user stack initialized like this: * |--------------- esp * | argc * |--------------- * | argv * |--------------- * | argv[0] "..." * | argv[1] "..." * | ... * | argv[n] "..." * --------------- VM_STACK * note: ignored envp yet. * */ int do_exec(char *path, char **argv){ struct inode *ip; struct buf *bp; struct sigaction *sa; struct ahead *ah; struct page *pg; struct vm *vm; struct vma *vp; struct file *fp; uint bn, fd, argc, esp, nr; char **tmp; ip = namei(path, 0); if (ip==NULL) { return syserr(ENOENT); } // read the first block of file to get the a.out header. bn = bmap(ip, 0, 0); if (bn == 0) { syserr(EINVAL); goto _badf; } bp = bread(ip->i_dev, bn); ah = (struct ahead*)bp->b_data; // check this a.out header. if (ah->a_magic != NMAGIC) { syserr(EINVAL); goto _badf; } // restore the path and argv temporarily tmp = store_argv(path, argv); // dettach the previous address space, and initialize a new one vm = &cu->p_vm; vm_clear(vm); vm_renew(vm, ah, ip); // push arguments to the end of user stack, which always the same address. esp = VM_STACK; argc = upush_argv(&esp, tmp); if (argc<0) panic("exec(): bad mem"); upush(&esp, &argc, sizeof(uint)); // free_argv(tmp); // close all the file descriptors with FD_CLOEXEC for (fd=0; fd<NOFILE; fd++) { fp = cu->p_ofile[fd]; if ((fp!=NULL) && (fp->f_fdflag & FD_CLOEXEC)) { do_close(fd); } } // clear all sigactions for (nr=0; nr<NSIG; nr++){ sa = &cu->p_sigact[nr]; sa->sa_handler = SIG_DFL; sa->sa_mask = 0; sa->sa_flags = 0; sa->sa_restorer = NULL; } // never forget this: brelse(bp); iput(ip); // enter user mode _retu(vm->vm_entry, esp); return 0; _badf: brelse(bp); iput(ip); return -1; }
int colm_delete_program( program_t *prg ) { tree_t **sp = prg->stack_root; int exit_status = prg->exit_status; colm_tree_downref( prg, sp, prg->return_val ); colm_clear_heap( prg, sp ); colm_tree_downref( prg, sp, prg->error ); #if DEBUG long kid_lost = kid_num_lost( prg ); long tree_lost = tree_num_lost( prg ); long parse_tree_lost = parse_tree_num_lost( &prg->parse_tree_pool ); long head_lost = head_num_lost( prg ); long location_lost = location_num_lost( prg ); if ( kid_lost ) message( "warning: lost kids: %ld\n", kid_lost ); if ( tree_lost ) message( "warning: lost trees: %ld\n", tree_lost ); if ( parse_tree_lost ) message( "warning: lost parse trees: %ld\n", parse_tree_lost ); if ( head_lost ) message( "warning: lost heads: %ld\n", head_lost ); if ( location_lost ) message( "warning: lost locations: %ld\n", location_lost ); #endif kid_clear( prg ); tree_clear( prg ); head_clear( prg ); parse_tree_clear( &prg->parse_tree_pool ); location_clear( prg ); struct run_buf *rb = prg->alloc_run_buf; while ( rb != 0 ) { struct run_buf *next = rb->next; free( rb ); rb = next; } vm_clear( prg ); if ( prg->stream_fns ) { char **ptr = prg->stream_fns; while ( *ptr != 0 ) { free( *ptr ); ptr += 1; } free( prg->stream_fns ); } free( prg ); return exit_status; }