static void sig_pidwait(void *pid, void *statusp) { PROCESS_REC *rec; char *str; int status = GPOINTER_TO_INT(statusp); rec = process_find_pid(GPOINTER_TO_INT(pid)); if (rec == NULL) return; /* process exited - print the last line if there wasn't a newline at end. */ if (line_split("\n", 1, &str, &rec->databuf) > 0 && *str != '\0') signal_emit_id(signal_exec_input, 2, rec, str); if (!rec->silent) { if (WIFSIGNALED(status)) { status = WTERMSIG(status); printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE, "process %d (%s) terminated with signal %d (%s)", rec->id, rec->args, status, g_strsignal(status)); } else { status = WIFEXITED(status) ? WEXITSTATUS(status) : -1; printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE, "process %d (%s) terminated with return code %d", rec->id, rec->args, status); } } process_destroy(rec, status); }
/* * Common code for cmd_prog and cmd_shell. * * Note that this does not wait for the subprogram to finish, but * returns immediately to the menu. This is usually not what you want, * so you should have it call your system-calls-assignment waitpid * code after forking. * * Also note that because the subprogram's thread uses the "args" * array and strings, until you do this a race condition exists * between that code and the menu input code. */ static int common_prog(int nargs, char **args) { int err; int exit_code; struct process *proc; err = runprogram(nargs, args, &proc); if (err) { kprintf("runprogram failed: %s\n", strerror(err)); return err; } exit_code = process_waiton(proc); if (WIFEXITED(exit_code)) kprintf("%s exited with code %d\n", args[0], WEXITSTATUS(exit_code)); else if (WIFSIGNALED(exit_code)) kprintf("%s received a fatal signal: %d\n", args[0], WTERMSIG(exit_code)); else if (WIFSTOPPED(exit_code)) kprintf("%s stopped on signal %d\n", args[0], WSTOPSIG(exit_code)); process_destroy(proc->ps_pid); return 0; }
static void sig_pidwait(void *pid, void *statusp) { PROCESS_REC *rec; int status = GPOINTER_TO_INT(statusp); rec = process_find_pid(GPOINTER_TO_INT(pid)); if (rec == NULL) return; /* process exited */ if (!rec->silent) { if (WIFSIGNALED(status)) { status = WTERMSIG(status); printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE, "process %d (%s) terminated with signal %d (%s)", rec->id, rec->args, status, g_strsignal(status)); } else { status = WIFEXITED(status) ? WEXITSTATUS(status) : -1; printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE, "process %d (%s) terminated with return code %d", rec->id, rec->args, status); } } process_destroy(rec, status); }
int process_run(char **argv, const int keep_fds[], size_t n_keep_fds, const int null_fds[], size_t n_null_fds, int *status) { struct process *p; int retval; COVERAGE_INC(process_run); retval = process_start(argv, keep_fds, n_keep_fds, null_fds, n_null_fds, &p); if (retval) { *status = 0; return retval; } while (!process_exited(p)) { process_wait(p); poll_block(); } *status = process_status(p); process_destroy(p); return 0; }
void collect_children() { for(int i=PID_MIN;i<=PID_MAX;i++) { if(parentprocesslist[i] == INIT_PROCESS && freepidlist[i] == P_ZOMBIE) { process_destroy(i); } } }
void remove_process(Process *proc) { debug(DEBUG_FUNCTION, "remove_proc(pid=%d)", proc->pid); if (proc->leader == proc) each_task(proc, NULL, &clear_leader, NULL); unlist_process(proc); process_removed(proc); process_destroy(proc); free(proc); }
int proc_do_collect(size_t pid, int *retval) { Process *proc = proc_get_by_id(pid); if (!proc) { return 0; } if (proc->parent != current_process) { return 0; } *retval = process_destroy(proc); assert(list_size(&proc_normal_queue) || list_size(&proc_normal_noticks_queue)); return 1; }
bool process_check_destroy(pid_t pid) { struct process *p = process_get(pid); // check whether the process has exited if (process_checkon(p) == -1) return false; process_destroy(p->ps_pid); // returning true removes pid from the pid_set // during pid_set_map() return true; }
void zmq::own_t::check_term_acks () { if (_terminating && _processed_seqnum == _sent_seqnum.get () && _term_acks == 0) { // Sanity check. There should be no active children at this point. zmq_assert (_owned.empty ()); // The root object has nobody to confirm the termination to. // Other nodes will confirm the termination to the owner. if (_owner) send_term_ack (_owner); // Deallocate the resources. process_destroy (); } }
void fe_exec_deinit(void) { if (processes != NULL) { processes_killall(SIGTERM); sleep(1); processes_killall(SIGKILL); while (processes != NULL) process_destroy(processes->data, -1); } command_unbind("exec", (SIGNAL_FUNC) cmd_exec); signal_remove("pidwait", (SIGNAL_FUNC) sig_pidwait); signal_remove("exec input", (SIGNAL_FUNC) sig_exec_input); signal_remove("window destroyed", (SIGNAL_FUNC) sig_window_destroyed); signal_remove("send text", (SIGNAL_FUNC) event_text); }
/* Called by waitpid() */ int process_wait(pid_t pidToWait, pid_t pidToWaitFor) { (void)pidToWait; int exitCode; processtable_biglock_acquire(); struct process *notifier = get_process(pidToWaitFor); if(freepidlist[pidToWaitFor] == P_ZOMBIE) { //The process we're waiting for already exited. //Return to sys_waitpid to collect the exit code. exitCode = exitcodelist[pidToWaitFor]; processtable_biglock_release(); } else { processtable_biglock_release(); P(notifier->p_waitsem); exitCode = exitcodelist[pidToWaitFor]; } process_destroy(notifier->p_id); return exitCode; }
void gram_SYSTEM() { char *cmd; parser_push_fun("SYSTEM"); cmd = parser_parlist(&parser, COLLECT_SET); if (message_show(MSG_NOTICE)) message("SYSTEM %s", string_short(cmd)); if (!check_live_data(cmd)) free(cmd); else { Process process; process_construct(&process, "SYSTEM", cmd, NULL); process_system(&process); process_destroy(&process); } parser_pop_fun(); }
int main(int argc, char *argv[]) { static struct option long_options[] = { {"listen", required_argument, 0, 'l'}, {"port", required_argument, 0, 'p'}, {"help", no_argument, 0, 'h'}, {"verbose", no_argument, 0, 'v'}, {"ping-parent", no_argument, 0, 'x'}, {"gcc-command", required_argument, 0, 'g'}, {"vx32sdk", required_argument, 0, 's'}, {"tmpdir", required_argument, 0, 't'}, {"engine", required_argument, 0, 'e'}, {"no-vx32", no_argument, 0, 'n'}, {0, 0, 0, 0} }; struct server *server = (struct server*)st_calloc(1, sizeof(struct server)); server->info_handler = &info_handler; server->quit_handler = &quit_handler; server->process_multi= &process_multi; INIT_LIST_HEAD(&server->root); server->host = "127.0.0.1"; server->port = 22122; struct config *config = (struct config*)st_calloc(1, sizeof(struct config)); server->userdata = config; config->tmpdir = "/tmp"; config->vx32sdk_path = "./untrusted/"; config->vx32sdk_gcc_command = strdup(flatten_argv(NELEM(default_vx32sdk_gcc_command), default_vx32sdk_gcc_command, " ")); config->syscall_limit = 4; /* 4 syscalls per request allowed */ int option_index; int arg; char *engine_name = NULL; while((arg = getopt_long_only(argc, argv, "hxvnl:p:g:s:t:e:", long_options, &option_index)) != EOF) { switch(arg) { case 'h': print_help(server, config); exit(-1); break; case 'v': server->trace = 1; break; case 'x': server->ping_parent = 1; break; case 'l': server->host = optarg; break; case 'p': server->port = atoi(optarg); if(server->port < 0 || server->port > 65536) fatal("Port number broken: %i", server->port); break; case 'g': free(config->vx32sdk_gcc_command); config->vx32sdk_gcc_command = strdup(optarg); break; case 's': config->vx32sdk_path = optarg; break; case 't': config->tmpdir = optarg; break; case 'e': engine_name = optarg; break; case 'n': config->vx32_disabled = 1; break; case 0: default: fatal("\nUnknown option: \"%s\"\n", argv[optind-1]); } } int i; storage_engine_create *engine_create = NULL; storage_engine_destroy *engine_destroy = NULL; for(i=0; i<NELEM(engines); i++) { if(engine_name && 0 == strcmp(engine_name, engines[i].name)) { engine_create = engines[i].create; engine_destroy = engines[i].destroy; } } if(NULL == engine_create) fatal("\nYou must specify a storage engine:" " --engine=[%s]\n", flatten_engine_names() ); log_info("Process pid %i", getpid()); signal(SIGPIPE, SIG_IGN); commands_initialize(); process_initialize(config); char *params = flatten_argv(argc-optind, &argv[optind], ", "); log_info("Loading database engine \"%s\" with parameters \"%s\"", engine_name, params); config->api = engine_create(argc-optind, &argv[optind]); do_event_loop(server); log_info("Quit"); process_destroy(); commands_destroy(); pool_free(); engine_destroy(config->api); free(config->vx32sdk_gcc_command); free(config); free(server); exit(0); return(0); }
int main(int argc, char **argv) { String *cmd = string_new(0); String *input = NULL; if (argc == 1) { fprintf(stderr, "Usage: %s [-s] prog [arg(s)]\n" " -s: use system call, not std-input\n" " prog: program or system call to execute\n" " arg(s): optional arguments to prog\n" "Input to prog is read from stdin, unless -s was specified\n" " (don't make this too long, it's stored in a String first)\n" "\n", argv[0]); exit(1); } bool syscall = !strcmp(argv[1], "-s"); if (syscall) { argc--; argv++; } else { input = string_new(0); char buffer[100]; fprintf(stderr, "Reading input from stdin...\n"); while (fgets(buffer, 100, stdin)) string_addstr(input, buffer); fprintf(stderr, "Input will be:\n" "`%s'\n", string_str(input)); } while (*++argv) { string_addstr(cmd, *argv); string_addchar(cmd, ' '); } fprintf(stderr, "Command will be:\n" "`%s'\n", string_str(cmd)); message_setseverity(MSG_ALL); message(MSG_NOTICE, "Creating Process"); Process process; process_construct(&process, "process-demo", cmd, input); if (syscall) process_system(&process); else process_fork(&process); String const *out = process_output(&process); fprintf(stderr, "Output from process: '\n" "%s\n" "'\n", string_str(out)); process_destroy(&process); return 0; }
/* * Load program and start running it in usermode * in a new thread. * This is essentially an amalgam of fork() and execv(). */ int runprogram(int nargs, char **args, struct process **created_proc) { if (nargs > ARGNUM_MAX) return E2BIG; struct vnode *v; int result; struct process *proc; // copy the string, since vfs_open() will modify it char *progname = kstrdup(args[0]); if (progname == NULL) return ENOMEM; /* Open the file. */ result = vfs_open(progname, O_RDONLY, 0, &v); if (result) { return result; } // We no longer need the duplicate program name kfree(progname); // set up new process structure proc = process_create(args[0]); if (proc == NULL) { vfs_close(v); return ENOMEM; } // Get a PID for the process. ENPROC is // the error code for "no more processes allowed // in the system." pid_t pid = process_identify(proc); if (pid == 0) { process_cleanup(proc); vfs_close(v); return ENPROC; } // Create a new file descriptor table proc->ps_fdt = fdt_create(); if (proc->ps_fdt == NULL) { process_destroy(pid); vfs_close(v); return ENOMEM; } // Open FDs for stdin, stdout, and stderr result = setup_inouterr(proc->ps_fdt); if (result) { process_destroy(pid); vfs_close(v); return result; } // Create a new address space proc->ps_addrspace = as_create(); if (proc->ps_addrspace==NULL) { process_destroy(pid); vfs_close(v); return ENOMEM; } struct new_process_context *ctxt = kmalloc(sizeof(struct new_process_context)); if (ctxt == NULL) { as_activate(NULL); process_destroy(pid); return ENOMEM; } ctxt->nargs = nargs; ctxt->args = args; ctxt->proc = proc; ctxt->executable = v; // Start a new thread to warp to user mode result = thread_fork("user process", run_process, ctxt, 0, NULL); if (result) { kfree(ctxt); as_activate(NULL); process_destroy(pid); return result; } // pass process to caller and return *created_proc = proc; return 0; }
int main(int argc, char ** argv) { options_t options; int master_fd, slave_fd; pid_t relay_pid, timer_pid, solution_pid, pid; int status; if (!options_get(argc, argv, &options)) return EXITCODE_USAGE_ERROR; options_display(stderr, &options); /* Open a pseudo terminal. Start the child in a new process; it uses the * pseudo terminal for its stdin, stdout, and stderr. Start a process whose * job it is to relay data bidirectionally between our stdin/out and the * child's. Start a timer to enforce the user time limit. */ if ( !pty_open_raw(&master_fd, &slave_fd) || !start_child(&solution_pid, master_fd, slave_fd, &options) || !start_relay(&relay_pid, master_fd, slave_fd) || !start_timer(&timer_pid, master_fd, slave_fd, options.resource_limits.max_user_time_in_seconds) ) return EXITCODE_INTERNAL_ERROR; close(master_fd); close(slave_fd); /* Wait for a child to end, but wait again if the first we see happens to * be the relay (seeing the relay end is inconclusive). The real race is * between the timer and child processes. */ do { pid = wait(&status); if (pid == -1) return EXITCODE_INTERNAL_ERROR; } while (pid == relay_pid); if (pid == timer_pid) { /* The timer ended first, which means the child took too much user * time. */ process_destroy(solution_pid); process_destroy(relay_pid); return EXITCODE_USER_TIME_LIMIT_EXCEEDED; } if (pid == solution_pid) { process_destroy(timer_pid); process_destroy(relay_pid); /* The child ended first. If it exited normally, communicate that to * the caller. */ if (WIFEXITED(status)) return EXITCODE_PROGRAM_EXITED; /* It didn't exit normally. Maybe it got killed by the kernel with * SIGKILL for taking too much CPU time, or killed by some other signal * we didn't expect. */ if (WIFSIGNALED(status)) return WTERMSIG(status) == SIGKILL ? EXITCODE_CPU_TIME_LIMIT_EXCEEDED : exitcode_for_fatal_signal(WTERMSIG(status)); } /* Something strange happened. */ return EXITCODE_INTERNAL_ERROR; }
/* Starts the process whose arguments are given in the null-terminated array * 'argv' and waits for it to exit. On success returns 0 and stores the * process exit value (suitable for passing to process_status_msg()) in * '*status'. On failure, returns a positive errno value and stores 0 in * '*status'. * * If 'stdout_log' is nonnull, then the subprocess's output to stdout (up to a * limit of PROCESS_MAX_CAPTURE bytes) is captured in a memory buffer, which * when this function returns 0 is stored as a null-terminated string in * '*stdout_log'. The caller is responsible for freeing '*stdout_log' (by * passing it to free()). When this function returns an error, '*stdout_log' * is set to NULL. * * If 'stderr_log' is nonnull, then it is treated like 'stdout_log' except * that it captures the subprocess's output to stderr. */ int process_run_capture(char **argv, char **stdout_log, char **stderr_log, int *status) { struct stream s_stdout, s_stderr; sigset_t oldsigs; pid_t pid; int error; COVERAGE_INC(process_run_capture); if (stdout_log) { *stdout_log = NULL; } if (stderr_log) { *stderr_log = NULL; } *status = 0; error = process_prestart(argv); if (error) { return error; } error = stream_open(&s_stdout); if (error) { return error; } error = stream_open(&s_stderr); if (error) { stream_close(&s_stdout); return error; } block_sigchld(&oldsigs); pid = fork(); if (pid < 0) { int error = errno; unblock_sigchld(&oldsigs); VLOG_WARN("fork failed: %s", strerror(error)); stream_close(&s_stdout); stream_close(&s_stderr); *status = 0; return error; } else if (pid) { /* Running in parent process. */ struct process *p; p = process_register(argv[0], pid); unblock_sigchld(&oldsigs); close(s_stdout.fds[1]); close(s_stderr.fds[1]); while (!process_exited(p)) { stream_read(&s_stdout); stream_read(&s_stderr); stream_wait(&s_stdout); stream_wait(&s_stderr); process_wait(p); poll_block(); } stream_read(&s_stdout); stream_read(&s_stderr); if (stdout_log) { *stdout_log = ds_steal_cstr(&s_stdout.log); } if (stderr_log) { *stderr_log = ds_steal_cstr(&s_stderr.log); } stream_close(&s_stdout); stream_close(&s_stderr); *status = process_status(p); process_destroy(p); return 0; } else { /* Running in child process. */ int max_fds; int i; fatal_signal_fork(); unblock_sigchld(&oldsigs); dup2(get_null_fd(), 0); dup2(s_stdout.fds[1], 1); dup2(s_stderr.fds[1], 2); max_fds = get_max_fds(); for (i = 3; i < max_fds; i++) { close(i); } execvp(argv[0], argv); fprintf(stderr, "execvp(\"%s\") failed: %s\n", argv[0], strerror(errno)); exit(EXIT_FAILURE); } }
pid_t sys_fork(const struct trapframe *parent_tf, int *err) { struct process *parent = curthread->t_proc; // set up new process structure struct process *child = process_create(parent->ps_name); if (child == NULL) { *err = ENOMEM; return -1; } // Get a PID for the child. ENPROC is // the error code for "no more processes allowed // in the system." pid_t child_pid = process_identify(child); if (child_pid == 0) { *err = ENPROC; process_cleanup(child); return -1; } // copy the file descriptor table of the parent child->ps_fdt = fdt_copy(parent->ps_fdt); if (child->ps_fdt == NULL) { *err = ENOMEM; process_destroy(child_pid); return -1; } // copy the address space of the parent *err = as_copy(parent->ps_addrspace, &child->ps_addrspace); if (*err) { process_destroy(child_pid); return -1; } // add PID to children now. That way, if we fail to // allocate memory, we have not yet forked a thread *err = pid_set_add(parent->ps_children, child_pid); if (*err) { process_destroy(child_pid); return -1; } // allocate space for child trapframe in the kernel heap struct trapframe *child_tf = kmalloc(sizeof(struct trapframe)); if (child_tf == NULL) { process_destroy(child_pid); pid_set_remove(parent->ps_children, child_pid); *err = ENOMEM; return -1; } // copy trapframe memcpy(child_tf, parent_tf, sizeof(struct trapframe)); // abuse child_tf->TF_RET (which will be set to 0) // to pass the process struct to the child thread // this cast and assignment will always work, // as pointers always fit in machine registers child_tf->TF_RET = (uintptr_t)child; // child thread sets up child return value // and ps_thread/t_proc *err = thread_fork("user process", enter_forked_process, child_tf, 0, NULL); if (*err) { process_destroy(child_pid); kfree(child_tf); pid_set_remove(parent->ps_children, child_pid); return -1; } return child_pid; }
static void handle_exec(const char *args, GHashTable *optlist, WI_ITEM_REC *item) { PROCESS_REC *rec; char *target, *level; int notice, signum, interactive, target_nick, target_channel; /* check that there's no unknown options. we allowed them because signals can be used as options, but there should be only one unknown option: the signal name/number. */ signum = cmd_options_get_signal("exec", optlist); if (signum == -2) return; if (*args == '\0') { exec_show_list(); return; } target = NULL; notice = FALSE; if (g_hash_table_lookup(optlist, "in") != NULL) { rec = process_find(g_hash_table_lookup(optlist, "in"), TRUE); if (rec != NULL) { net_sendbuffer_send(rec->out, args, strlen(args)); net_sendbuffer_send(rec->out, "\n", 1); } return; } /* check if args is a process ID or name. if it's ID but not found, complain about it and fail immediately */ rec = process_find(args, *args == '%'); if (*args == '%' && rec == NULL) return; /* common options */ target_channel = target_nick = FALSE; if (g_hash_table_lookup(optlist, "out") != NULL) { /* redirect output to active channel/query */ if (item == NULL) cmd_return_error(CMDERR_NOT_JOINED); target = (char *) window_item_get_target(item); target_channel = IS_CHANNEL(item); target_nick = IS_QUERY(item); } else if (g_hash_table_lookup(optlist, "msg") != NULL) { /* redirect output to /msg <nick> */ target = g_hash_table_lookup(optlist, "msg"); } else if (g_hash_table_lookup(optlist, "notice") != NULL) { target = g_hash_table_lookup(optlist, "notice"); notice = TRUE; } /* options that require process ID/name as argument */ if (rec == NULL && (signum != -1 || g_hash_table_lookup(optlist, "close") != NULL)) { printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Unknown process name: %s", args); return; } if (g_hash_table_lookup(optlist, "close") != NULL) { /* forcibly close the process */ process_destroy(rec, -1); return; } if (signum != -1) { /* send a signal to process */ kill(rec->pid, signum); return; } interactive = g_hash_table_lookup(optlist, "interactive") != NULL; if (*args == '%') { /* do something to already existing process */ char *name; if (target != NULL) { /* redirect output to target */ g_free_and_null(rec->target); rec->target = g_strdup(target); rec->notice = notice; } name = g_hash_table_lookup(optlist, "name"); if (name != NULL) { /* change window name */ g_free_not_null(rec->name); rec->name = *name == '\0' ? NULL : g_strdup(name); } else if (target == NULL && (rec->target_item == NULL || interactive)) { /* no parameters given, redirect output to the active window */ g_free_and_null(rec->target); rec->target_win = active_win; if (rec->target_item != NULL) exec_wi_destroy(rec->target_item); if (interactive) { rec->target_item = exec_wi_create(active_win, rec); } } return; } /* starting a new process */ rec = g_new0(PROCESS_REC, 1); rec->pid = -1; rec->shell = g_hash_table_lookup(optlist, "nosh") == NULL; process_exec(rec, args); if (rec->pid == -1) { /* pipe() or fork() failed */ g_free(rec); cmd_return_error(CMDERR_ERRNO); } rec->id = process_get_new_id(); rec->target = g_strdup(target); rec->target_win = active_win; rec->target_channel = target_channel; rec->target_nick = target_nick; rec->args = g_strdup(args); rec->notice = notice; rec->silent = g_hash_table_lookup(optlist, "-") != NULL; rec->quiet = g_hash_table_lookup(optlist, "quiet") != NULL; rec->name = g_strdup(g_hash_table_lookup(optlist, "name")); level = g_hash_table_lookup(optlist, "level"); rec->level = level == NULL ? MSGLEVEL_CLIENTCRAP : level2bits(level); rec->read_tag = g_input_add(rec->in, G_INPUT_READ, (GInputFunction) sig_exec_input_reader, rec); processes = g_slist_append(processes, rec); if (rec->target == NULL && interactive) rec->target_item = exec_wi_create(active_win, rec); signal_emit("exec new", 1, rec); }
int main (int argc, char *argv[]) { pid_t pid; int status = 1; struct tracer *tracer = NULL; struct process *process = NULL; if (argc < 2) return 1; pid = fork (); if (pid < 0) { perror ("fork"); return 2; } if (pid == 0) fork_and_trace_child (argv); if (wait_for_stopped (pid, false, &status)) { fprintf (stderr, "child process unexpectedly dead\n"); return 3; } /* When delivering syscall traps, set bit 7 in the signal number (i.e., deliver SIGTRAP | 0x80). This makes it easy for the tracer to tell the difference between normal traps and those caused by a syscall. (PTRACE_O_TRACESYSGOOD may not work on all architectures.) */ if (ptrace (PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) == -1) return 5; status = 1; if (!(tracer = tracer_alloc ())) { fprintf (stderr, "Can not allocate tracer\n"); goto end; } if (!(process = process_alloc (pid))) { fprintf (stderr, "Can not allocate process\n"); goto end; } if (tracer_add_process (tracer, process) == -1) { fprintf (stderr, "Cannot add process to tracer\n"); goto end; } /* process = NULL should be here (!) */ for (;;) { struct user_regs_struct state1; struct user_regs_struct state2; if (wait_for_break (pid, &state1, &status)) break; if (wait_for_break (pid, &state2, &status)) break; trace_syscall (process, &state1, &state2); } process = NULL; status &= 0xff; end: if (process) process_destroy (process); if (tracer) tracer_destroy (tracer); return status; }