ATF_TC_BODY(symbol_lookup_fail, tc) { char symname[32]; GElf_Sym sym; struct proc_handle *phdl; prmap_t *map; int error; phdl = start_prog(tc, false); /* Initialize the rtld_db handle. */ (void)proc_rdagent(phdl); map = proc_name2map(phdl, target_prog_file); ATF_REQUIRE_MSG(map != NULL, "failed to look up map for '%s'", target_prog_file); /* * We shouldn't be able to find symbols at the beginning of a mapped * file. */ error = proc_addr2sym(phdl, map->pr_vaddr, symname, sizeof(symname), &sym); ATF_REQUIRE_MSG(error != 0, "unexpectedly found a symbol"); ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); proc_free(phdl); }
ATF_TC_BODY(symbol_lookup, tc) { GElf_Sym main_sym, r_debug_state_sym; struct proc_handle *phdl; u_long saved; int error; phdl = start_prog(tc, false); error = proc_name2sym(phdl, target_prog_file, "main", &main_sym, NULL); ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main'"); error = proc_name2sym(phdl, ldelf_object, "r_debug_state", &r_debug_state_sym, NULL); ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'r_debug_state'"); set_bkpt(phdl, r_debug_state_sym.st_value, &saved); ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); verify_bkpt(phdl, &r_debug_state_sym, "r_debug_state", ldelf_object); remove_bkpt(phdl, r_debug_state_sym.st_value, saved); set_bkpt(phdl, main_sym.st_value, &saved); ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); verify_bkpt(phdl, &main_sym, "main", target_prog_file); remove_bkpt(phdl, main_sym.st_value, saved); ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); proc_free(phdl); }
int sys_kill(int pid){ //t=t; printf("killing %d.",pid); ProcStruct *proc=(procs+pid-1); proc_free(proc); remove_page(proc->cr3); remove_page((uint64_t*)PADDR((uint64_t)proc->mm)); ProcStruct* parent =((ProcStruct*)procs+proc->parent_id-1); if(parent) parent->num_child--; if((parent) && (parent->status == WAITING) && (parent->waitingfor == proc->proc_id || parent->waitingfor == 0 || (parent->num_child==0))) { parent->status=RUNNABLE; parent->waitingfor=-1; } printf("Killed %d ",proc->proc_id); // kmemset((void*)proc,0,sizeof(ProcStruct)); proc->status = FREE; //proccount-- return 0; }
unsigned int proc_pid_cpu(pid_t pid) { unsigned int total_pre, part_pre, total_post, part_post; proc_base *test = proc_create(); proc_pid *testinit = proc_pid_create(pid); proc_poll(test); proc_pid_poll(testinit); total_pre = proc_total(test); part_pre = proc_pid_total(testinit); sleep(1); proc_poll(test); proc_pid_poll(testinit); total_post = proc_total(test); part_post = proc_pid_total(testinit); proc_free(test); proc_pid_free(testinit); dprintf("total_pre = %u\n", total_pre); dprintf("part_pre = %u\n", part_pre); dprintf("total_post = %u\n", total_post); dprintf("part_post = %u\n", part_post); return ((part_post - part_pre) * 10000) / (total_post - total_pre); }
ATF_TC_BODY(symbol_lookup, tc) { GElf_Sym main_sym, r_debug_state_sym; struct proc_handle *phdl; proc_breakpoint_t saved; int error; phdl = start_prog(tc, false); error = proc_name2sym(phdl, target_prog_file, "main", &main_sym, NULL); ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main'"); error = proc_name2sym(phdl, ldelf_object, r_debug_state, &r_debug_state_sym, NULL); ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up '%s'", r_debug_state); set_bkpt(phdl, (uintptr_t)r_debug_state_sym.st_value, &saved); ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); verify_bkpt(phdl, &r_debug_state_sym, r_debug_state, ldelf_object); remove_bkpt(phdl, (uintptr_t)r_debug_state_sym.st_value, &saved); set_bkpt(phdl, (uintptr_t)main_sym.st_value, &saved); ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); verify_bkpt(phdl, &main_sym, "main", target_prog_file); remove_bkpt(phdl, (uintptr_t)main_sym.st_value, &saved); ATF_CHECK_EQ_MSG(proc_detach(phdl, PRELEASE_HANG), 0, "failed to detach"); proc_free(phdl); }
void sys_exit(uint64_t error_code){ // printf("Exiting Process%p %d",curproc,curproc->proc_id); if(curproc) { proc_free(curproc); remove_page(curproc->cr3); remove_page((uint64_t*)PADDR((uint64_t)curproc->mm)); ProcStruct* parent =((ProcStruct*)procs+curproc->parent_id-1); if(parent) parent->num_child--; if((parent) && (parent->status == WAITING) && (parent->waitingfor == curproc->proc_id || parent->waitingfor == 0 || (parent->num_child==0))) { parent->status=RUNNABLE; parent->waitingfor=-1; } printf("Exited%d ",curproc->proc_id); // kmemset((void*)proc,0,sizeof(ProcStruct)); curproc->status = FREE; //proccount-- } }
int syscall_exit(int arg1) { int pid; (void) arg1; if (current_process == NULL) return -1; set_translation_table_base((uint32_t) V2P(kernel_vm)); __asm__ volatile("ldr sp, =kernel_stack_start"); for (pid = 0; pid < PROCESS_COUNT_MAX; pid++) { struct Process *proc = &process_table[pid]; if (proc->state == SLEEPING && proc->wait_pid == current_process->pid) { proc->wait_pid = -1; proc->state = READY; } } proc_free(current_process); current_process = NULL; schedule(); return 0; }
ATF_TC_BODY(map_alias_name2sym, tc) { GElf_Sym sym1, sym2; prsyminfo_t si1, si2; struct proc_handle *phdl; int error; phdl = start_prog(tc, false); /* Initialize the rtld_db handle. */ (void)proc_rdagent(phdl); /* * Make sure that "target_prog:main" and "a.out:main" return the same * symbol. */ error = proc_name2sym(phdl, target_prog_file, "main", &sym1, &si1); ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main' via %s", target_prog_file); error = proc_name2sym(phdl, aout_object, "main", &sym2, &si2); ATF_REQUIRE_EQ_MSG(error, 0, "failed to look up 'main' via %s", aout_object); ATF_CHECK_EQ(memcmp(&sym1, &sym2, sizeof(sym1)), 0); ATF_CHECK_EQ(si1.prs_id, si2.prs_id); ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); proc_free(phdl); }
ATF_TC_BODY(signal_forward, tc) { struct proc_handle *phdl; int state, status; phdl = start_prog(tc, true); ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); /* The process should have been interrupted by a signal. */ state = proc_wstatus(phdl); ATF_REQUIRE_EQ_MSG(state, PS_STOP, "process has unexpected state %d", state); /* Continue execution and allow the signal to be delivered. */ ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); /* * Make sure the process exited with status 0. If it didn't receive the * SIGUSR1 that it sent to itself, it'll exit with a non-zero exit * status, causing the test to fail. */ state = proc_wstatus(phdl); ATF_REQUIRE_EQ_MSG(state, PS_UNDEAD, "process has unexpected state %d", state); status = proc_getwstat(phdl); ATF_REQUIRE(status >= 0); ATF_REQUIRE(WIFEXITED(status)); ATF_REQUIRE_EQ(WEXITSTATUS(status), 0); proc_free(phdl); }
void job_free(struct job *j) { struct proc *p, *next; for(p = j->proc; p; p = next){ next = p->next; proc_free(p); } ufree_argvp(j->argvp); free(j->cmd); free(j); }
/* start a new process */ extern process * noshell_proc_start(char **av, stream *inp, stream *outp, stream *errp, int newpg, char *who) { process *pp; int i, n; if ((pp = (process *)malloc(sizeof(process))) == 0) { if (inp != 0) stream_free(inp); if (outp != 0) stream_free(outp); if (errp != 0) stream_free(errp); return 0; } pp->std[0] = inp; pp->std[1] = outp; pp->std[2] = errp; switch (pp->pid = fork()) { case -1: proc_free(pp); return 0; case 0: if(newpg) sysdetach(); for (i=0; i<3; i++) if (pp->std[i] != 0){ close(Bfildes(pp->std[i]->fp)); while(pp->std[i]->fd < 3) pp->std[i]->fd = dup(pp->std[i]->fd, -1); } for (i=0; i<3; i++) if (pp->std[i] != 0) dup(pp->std[i]->fd, i); for (n = sysfiles(); i < n; i++) close(i); if(who) become(av, who); exec(av[0], av); perror("proc_start"); exits("proc_start"); default: for (i=0; i<3; i++) if (pp->std[i] != 0) { close(pp->std[i]->fd); pp->std[i]->fd = -1; } return pp; } }
int proc_attach(pid_t pid, int flags, struct proc_handle **pphdl) { struct proc_handle *phdl; int error = 0; int status; if (pid == 0 || pid == getpid()) return (EINVAL); /* * Allocate memory for the process handle, a structure containing * all things related to the process. */ if ((phdl = malloc(sizeof(struct proc_handle))) == NULL) return (ENOMEM); memset(phdl, 0, sizeof(struct proc_handle)); phdl->pid = pid; phdl->flags = flags; phdl->status = PS_RUN; elf_version(EV_CURRENT); if (ptrace(PT_ATTACH, phdl->pid, 0, 0) != 0) { error = errno; DPRINTF("ERROR: cannot ptrace child process %d", pid); goto out; } /* Wait for the child process to stop. */ if (waitpid(pid, &status, WUNTRACED) == -1) { error = errno; DPRINTF("ERROR: child process %d didn't stop as expected", pid); goto out; } /* Check for an unexpected status. */ if (WIFSTOPPED(status) == 0) DPRINTFX("ERROR: child process %d status 0x%x", pid, status); else phdl->status = PS_STOP; out: if (error) proc_free(phdl); else *pphdl = phdl; return (error); }
void scheduler() { for (;;) { struct process *proc = current_proc ? current_proc->next : list_head.next; /* Find a runnable process */ while (proc == &list_head || proc->state != PROC_STATE_RUNNING) { if (proc != &list_head && proc->state == PROC_STATE_DEAD) { /* Release the dead process */ struct process *dead = proc; proc = proc->next; sched_remove(dead); proc_free(dead); } else { proc = proc->next; } } close_int(); current_proc = proc; /* Update TSS */ tss.ss0 = KERNEL_DATA_SELECTOR; tss.esp0 = proc->kernel_stack; flush_tss(); /* Change to process virtual address space */ set_cr3(CAST_VIRTUAL_TO_PHYSICAL(proc->page_dir)); if (!proc->context) init_context(proc); switch_kcontext(&sched_context, proc->context); /* Call schedule task */ if (sched_task) { sched_task(current_proc); sched_task = NULL; } } }
int t1_bkpt_d() { struct proc_handle *phdl; char *targv[] = { "t1-bkpt-t", NULL}; unsigned long saved; proc_create("./t1-bkpt", targv, NULL, NULL, &phdl); assert(proc_bkptset(phdl, (uintptr_t)t1_bkpt_t, &saved) == 0); proc_continue(phdl); assert(proc_wstatus(phdl) == PS_STOP); proc_bkptexec(phdl, saved); proc_continue(phdl); proc_wstatus(phdl); proc_free(phdl); }
PUBLIC int do_procctl() { endpoint_t who = mm_msg.PCTL_WHO; int param = mm_msg.PCTL_PARAM; int retval = 0; struct proc * p = proc_table + who; switch (param) { case PCTL_CLEARPROC: if (mm_msg.source != TASK_FS) retval = EPERM; else if (!list_empty(&(p->mem_regions))) retval = proc_free(p); break; default: retval = EINVAL; break; } return retval; }
void verify(String *path) { char *p, *q; char *av[4]; if(rejectcheck()) return; if(shellchars(s_to_c(path))){ reply("503 5.1.3 Bad character in address %s.\r\n", s_to_c(path)); return; } av[0] = s_to_c(mailer); av[1] = "-x"; av[2] = s_to_c(path); av[3] = 0; pp = noshell_proc_start(av, (stream *)0, outstream(), (stream *)0, 1, 0); if (pp == 0) { reply("450 4.3.2 We're busy right now, try later\r\n"); return; } p = Brdline(pp->std[1]->fp, '\n'); if(p == 0){ reply("550 5.1.0 String does not match anything.\r\n"); } else { p[Blinelen(pp->std[1]->fp)-1] = 0; if(strchr(p, ':')) reply("550 5.1.0 String does not match anything.\r\n"); else{ q = strrchr(p, '!'); if(q) p = q+1; reply("250 2.0.0 %s <%s@%s>\r\n", s_to_c(path), p, dom); } } proc_wait(pp); proc_free(pp); pp = 0; }
ATF_TC_BODY(map_prefix_name2map, tc) { struct proc_handle *phdl; prmap_t *map1, *map2; phdl = start_prog(tc, false); /* Initialize the rtld_db handle. */ (void)proc_rdagent(phdl); /* Make sure that "ld-elf" and "ld-elf.so" return the same map. */ map1 = proc_name2map(phdl, "ld-elf"); ATF_REQUIRE_MSG(map1 != NULL, "failed to look up map for 'ld-elf'"); map2 = proc_name2map(phdl, "ld-elf.so"); ATF_REQUIRE_MSG(map2 != NULL, "failed to look up map for 'ld-elf.so'"); ATF_CHECK_EQ(strcmp(map1->pr_mapname, map2->pr_mapname), 0); ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); proc_free(phdl); }
/* pipe an address through a command to translate it */ extern dest * translate(dest *dp) { process *pp; String *line; dest *rv; char *cp; int n; pp = proc_start(s_to_c(dp->repl1), (stream *)0, outstream(), outstream(), 1, 0); if (pp == 0) { dp->status = d_resource; return 0; } line = s_new(); for(;;) { cp = Brdline(pp->std[1]->fp, '\n'); if(cp == 0) break; if(strncmp(cp, "_nosummary_", 11) == 0){ nosummary = 1; continue; } n = Blinelen(pp->std[1]->fp); cp[n-1] = ' '; s_nappend(line, cp, n); } rv = s_to_dest(s_restart(line), dp); s_restart(line); while(s_read_line(pp->std[2]->fp, line)) ; if ((dp->pstat = proc_wait(pp)) != 0) { dp->repl2 = line; rv = 0; } else s_free(line); proc_free(pp); return rv; }
/* * Run a command to authorize or refuse entry. Return status 0 means * authorize, -1 means refuse. */ void authorize(dest *dp) { process *pp; String *errstr; dp->authorized = 1; pp = proc_start(s_to_c(dp->repl1), (stream *)0, (stream *)0, outstream(), 1, 0); if (pp == 0){ dp->status = d_noforward; return; } errstr = s_new(); while(s_read_line(pp->std[2]->fp, errstr)) ; if ((dp->pstat = proc_wait(pp)) != 0) { dp->repl2 = errstr; dp->status = d_noforward; } else s_free(errstr); proc_free(pp); }
/* * Top-level module proc entries */ int proc_register (struct klife_status *klife) { struct proc_dir_entry *version, *status, *create, *destroy; root = proc_mkdir (KLIFE_PROC_ROOT, NULL); if (unlikely (!root)) goto err; version = create_proc_read_entry (KLIFE_PROC_VERSION, 0644, root, &proc_version_read, klife); status = create_proc_read_entry (KLIFE_PROC_STATUS, 0644, root, &proc_status_read, klife); boards = proc_mkdir (KLIFE_PROC_BOARDS, root); if (unlikely (!boards)) goto err; create = create_proc_entry (KLIFE_PROC_CREATE, 0644, boards); if (likely (create)) { create->write_proc = proc_create_write; create->data = klife; } else goto err; destroy = create_proc_entry (KLIFE_PROC_DESTROY, 0644, boards); if (likely (destroy)) { destroy->write_proc = proc_destroy_write; destroy->data = klife; } else goto err; return 0; err: proc_free (); return 1; }
ATF_TC_BODY(map_alias_name2map, tc) { struct proc_handle *phdl; prmap_t *map1, *map2; phdl = start_prog(tc, false); /* Initialize the rtld_db handle. */ (void)proc_rdagent(phdl); /* Ensure that "target_prog" and "a.out" return the same map. */ map1 = proc_name2map(phdl, target_prog_file); ATF_REQUIRE_MSG(map1 != NULL, "failed to look up map for '%s'", target_prog_file); map2 = proc_name2map(phdl, aout_object); ATF_REQUIRE_MSG(map2 != NULL, "failed to look up map for '%s'", aout_object); ATF_CHECK_EQ(strcmp(map1->pr_mapname, map2->pr_mapname), 0); ATF_CHECK_EQ_MSG(proc_continue(phdl), 0, "failed to resume execution"); proc_free(phdl); }
/** * Frees simulator resources by invoking the CPU and OS module release routines. */ void sim_free(void) { mem_free(); swapfile_free(); proc_free(); tlb_free(); }
void data(void) { int status, nbytes; char *cp, *ep; char errx[ERRMAX]; Link *l; String *cmd, *err; if(rejectcheck()) return; if(senders.last == 0){ reply("503 2.5.2 Data without MAIL FROM:\r\n"); rejectcount++; return; } if(rcvers.last == 0){ reply("503 2.5.2 Data without RCPT TO:\r\n"); rejectcount++; return; } if(!trusted && sendermxcheck()){ rerrstr(errx, sizeof errx); if(strncmp(errx, "rejected:", 9) == 0) reply("554 5.7.1 %s\r\n", errx); else reply("450 4.7.0 %s\r\n", errx); for(l=rcvers.first; l; l=l->next) syslog(0, "smtpd", "[%s/%s] %s -> %s sendercheck: %s", him, nci->rsys, s_to_c(senders.first->p), s_to_c(l->p), errx); rejectcount++; return; } cmd = startcmd(); if(cmd == 0) return; reply("354 Input message; end with <CRLF>.<CRLF>\r\n"); if(debug){ seek(2, 0, 2); stamp(); fprint(2, "# sent 354; accepting DATA %s\n", thedate()); } /* * allow 145 more minutes to move the data */ alarm(145*60*1000); status = pipemsg(&nbytes); /* * read any error messages */ err = s_new(); if (debug) { stamp(); fprint(2, "waiting for upas/send to close stderr\n"); } while(s_read_line(pp->std[2]->fp, err)) ; alarm(0); atnotify(catchalarm, 0); if (debug) { stamp(); fprint(2, "waiting for upas/send to exit\n"); } status |= proc_wait(pp); if(debug){ seek(2, 0, 2); stamp(); fprint(2, "# %d upas/send status %#ux at %s\n", getpid(), status, thedate()); if(*s_to_c(err)) fprint(2, "# %d error %s\n", getpid(), s_to_c(err)); } /* * if process terminated abnormally, send back error message */ if(status){ int code; char *ecode; if(strstr(s_to_c(err), "mail refused")){ syslog(0, "smtpd", "++[%s/%s] %s %s refused: %s", him, nci->rsys, s_to_c(senders.first->p), s_to_c(cmd), firstline(s_to_c(err))); code = 554; ecode = "5.0.0"; } else { syslog(0, "smtpd", "++[%s/%s] %s %s %s%s%sreturned %#q %s", him, nci->rsys, s_to_c(senders.first->p), s_to_c(cmd), piperror? "error during pipemsg: ": "", piperror? piperror: "", piperror? "; ": "", pp->waitmsg->msg, firstline(s_to_c(err))); code = 450; ecode = "4.0.0"; } for(cp = s_to_c(err); ep = strchr(cp, '\n'); cp = ep){ *ep++ = 0; reply("%d-%s %s\r\n", code, ecode, cp); } reply("%d %s mail process terminated abnormally\r\n", code, ecode); } else { /* * if a message appeared on stderr, despite good status, * log it. this can happen if rewrite.in contains a bad * r.e., for example. */ if(*s_to_c(err)) syslog(0, "smtpd", "%s returned good status, but said: %s", s_to_c(mailer), s_to_c(err)); if(filterstate == BLOCKED) reply("554 5.7.1 we believe this is spam. " "we don't accept it.\r\n"); else if(filterstate == DELAY) reply("450 4.3.0 There will be a delay in delivery " "of this message.\r\n"); else { reply("250 2.5.0 sent\r\n"); logcall(nbytes); if(debug){ seek(2, 0, 2); stamp(); fprint(2, "# %d sent 250 reply %s\n", getpid(), thedate()); } } } proc_free(pp); pp = 0; s_free(cmd); s_free(err); listfree(&senders); listfree(&rcvers); }
pid_t proc_fork(void) { /* * http://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html */ KERROR_DBG("%s(%u)\n", __func__, curproc->pid); struct proc_info * const old_proc = curproc; struct proc_info * new_proc; pid_t retval = 0; /* Check that the old process is in valid state. */ if (!old_proc || old_proc->state == PROC_STATE_INITIAL) return -EINVAL; new_proc = clone_proc_info(old_proc); if (!new_proc) return -ENOMEM; /* Clear some things required to be zeroed at this point */ new_proc->state = PROC_STATE_INITIAL; new_proc->exit_ksiginfo = NULL; new_proc->files = NULL; new_proc->pgrp = NULL; /* Must be NULL so we don't free the old ref. */ memset(&new_proc->tms, 0, sizeof(new_proc->tms)); /* ..and then start to fix things. */ /* * Process group. */ PROC_LOCK(); proc_pgrp_insert(old_proc->pgrp, new_proc); PROC_UNLOCK(); /* * Initialize the mm struct. */ retval = vm_mm_init(&new_proc->mm, old_proc->mm.nr_regions); if (retval) goto out; /* * Clone the master page table. * This is probably something we would like to get rid of but we are * stuck with because it's the easiest way to keep some static kernel * mappings valid between processes. */ if (mmu_ptcpy(&new_proc->mm.mpt, &old_proc->mm.mpt)) { retval = -EAGAIN; goto out; } /* * Clone L2 page tables. */ if (vm_ptlist_clone(&new_proc->mm.ptlist_head, &new_proc->mm.mpt, &old_proc->mm.ptlist_head) < 0) { retval = -ENOMEM; goto out; } retval = clone_code_region(new_proc, old_proc); if (retval) goto out; /* * Clone stack region. */ retval = clone_stack(new_proc, old_proc); if (retval) { KERROR_DBG("Cloning stack region failed.\n"); goto out; } /* * Clone other regions. */ retval = clone_regions_from(new_proc, old_proc, MM_HEAP_REGION); if (retval) goto out; /* * Set break values. */ new_proc->brk_start = (void *)( (*new_proc->mm.regions)[MM_HEAP_REGION]->b_mmu.vaddr + (*new_proc->mm.regions)[MM_HEAP_REGION]->b_bcount); new_proc->brk_stop = (void *)( (*new_proc->mm.regions)[MM_HEAP_REGION]->b_mmu.vaddr + (*new_proc->mm.regions)[MM_HEAP_REGION]->b_bufsize); /* fork() signals */ ksignal_signals_fork_reinit(&new_proc->sigs); /* * Copy file descriptors. */ KERROR_DBG("Copy file descriptors\n"); int nofile_max = old_proc->rlim[RLIMIT_NOFILE].rlim_max; if (nofile_max < 0) { #if configRLIMIT_NOFILE < 0 #error configRLIMIT_NOFILE can't be negative. #endif nofile_max = configRLIMIT_NOFILE; } new_proc->files = fs_alloc_files(nofile_max, nofile_max); if (!new_proc->files) { KERROR_DBG( "\tENOMEM when tried to allocate memory for file descriptors\n"); retval = -ENOMEM; goto out; } /* Copy and ref old file descriptors */ for (int i = 0; i < old_proc->files->count; i++) { new_proc->files->fd[i] = old_proc->files->fd[i]; fs_fildes_ref(new_proc->files, i, 1); /* null pointer safe */ } KERROR_DBG("All file descriptors copied\n"); /* * Select PID. */ new_proc->pid = proc_get_next_pid(); if (new_proc->cwd) { KERROR_DBG("Increment refcount for the cwd\n"); vref(new_proc->cwd); /* Increment refcount for the cwd */ } /* Update inheritance attributes */ set_proc_inher(old_proc, new_proc); /* Insert the new process into the process array */ procarr_insert(new_proc); /* * A process shall be created with a single thread. If a multi-threaded * process calls fork(), the new process shall contain a replica of the * calling thread. * We left main_thread null if calling process has no main thread. */ KERROR_DBG("Handle main_thread\n"); if (old_proc->main_thread) { KERROR_DBG("Call thread_fork() to get a new main thread for the fork.\n"); if (!(new_proc->main_thread = thread_fork(new_proc->pid))) { KERROR_DBG("\tthread_fork() failed\n"); retval = -EAGAIN; goto out; } KERROR_DBG("\tthread_fork() fork OK\n"); /* * We set new proc's mpt as the current mpt because the new main thread * is going to return directly to the user space. */ new_proc->main_thread->curr_mpt = &new_proc->mm.mpt; new_proc->state = PROC_STATE_READY; KERROR_DBG("Set the new main_thread (%d) ready\n", new_proc->main_thread->id); thread_ready(new_proc->main_thread->id); } else { KERROR_DBG("No thread to fork.\n"); new_proc->main_thread = NULL; new_proc->state = PROC_STATE_READY; } KERROR_DBG("Fork %d -> %d created.\n", old_proc->pid, new_proc->pid); retval = new_proc->pid; out: if (unlikely(retval < 0)) { proc_free(new_proc); } return retval; }
int proc_create(const char *file, char * const *argv, proc_child_func *pcf, void *child_arg, struct proc_handle **pphdl) { struct proc_handle *phdl; int error = 0; int status; pid_t pid; /* * Allocate memory for the process handle, a structure containing * all things related to the process. */ if ((phdl = malloc(sizeof(struct proc_handle))) == NULL) return (ENOMEM); elf_version(EV_CURRENT); /* Fork a new process. */ if ((pid = vfork()) == -1) error = errno; else if (pid == 0) { /* The child expects to be traced. */ if (ptrace(PT_TRACE_ME, 0, 0, 0) != 0) _exit(1); if (pcf != NULL) (*pcf)(child_arg); /* Execute the specified file: */ execvp(file, argv); /* Couldn't execute the file. */ _exit(2); } else { /* The parent owns the process handle. */ memset(phdl, 0, sizeof(struct proc_handle)); phdl->pid = pid; phdl->status = PS_IDLE; /* Wait for the child process to stop. */ if (waitpid(pid, &status, WUNTRACED) == -1) { error = errno; DPRINTF("ERROR: child process %d didn't stop as expected", pid); goto bad; } /* Check for an unexpected status. */ if (WIFSTOPPED(status) == 0) { error = errno; DPRINTFX("ERROR: child process %d status 0x%x", pid, status); goto bad; } else phdl->status = PS_STOP; } bad: if (error) proc_free(phdl); else *pphdl = phdl; return (error); }