static void cleanup() { debug("Cleaning up..."); process_cleanup(); comm_cleanup(); protocol_cleanup(); injectable_cleanup(); debug("Cleanup complete."); }
/* * Tears down the process, removing it from the pid table. * Frees ALL associated memory and structures. */ void process_destroy(pid_t pid) { rw_wlock(pidt_rw); struct process *p = pid_table[pid]; KASSERT(p->ps_thread == NULL); pid_table[pid] = NULL; rw_wdone(pidt_rw); // orphan all children if not already done in process_finish() // (this is important because kill_curthread() calls // process_destroy() on a process that has not properly exited.) if (!pid_set_empty(p->ps_children)) { int x = splhigh(); pid_set_map(p->ps_children, process_orphan); splx(x); } process_cleanup(p); }
int run_test(const char* test, int timeout, int benchmark_output, int test_count) { char errmsg[1024] = "no error"; process_info_t processes[1024]; process_info_t *main_proc; task_entry_t* task; int process_count; int result; int status; int i; status = 255; main_proc = NULL; process_count = 0; #ifndef _WIN32 /* Clean up stale socket from previous run. */ remove(TEST_PIPENAME); #endif /* If it's a helper the user asks for, start it directly. */ for (task = TASKS; task->main; task++) { if (task->is_helper && strcmp(test, task->process_name) == 0) { return task->main(); } } /* Start the helpers first. */ for (task = TASKS; task->main; task++) { if (strcmp(test, task->task_name) != 0) { continue; } /* Skip the test itself. */ if (!task->is_helper) { continue; } if (process_start(task->task_name, task->process_name, &processes[process_count], 1 /* is_helper */) == -1) { snprintf(errmsg, sizeof errmsg, "Process `%s` failed to start.", task->process_name); goto out; } process_count++; } /* Give the helpers time to settle. Race-y, fix this. */ uv_sleep(250); /* Now start the test itself. */ for (task = TASKS; task->main; task++) { if (strcmp(test, task->task_name) != 0) { continue; } if (task->is_helper) { continue; } if (process_start(task->task_name, task->process_name, &processes[process_count], 0 /* !is_helper */) == -1) { snprintf(errmsg, sizeof errmsg, "Process `%s` failed to start.", task->process_name); goto out; } main_proc = &processes[process_count]; process_count++; break; } if (main_proc == NULL) { snprintf(errmsg, sizeof errmsg, "No test with that name: %s", test); goto out; } result = process_wait(main_proc, 1, timeout); if (result == -1) { FATAL("process_wait failed"); } else if (result == -2) { /* Don't have to clean up the process, process_wait() has killed it. */ snprintf(errmsg, sizeof errmsg, "timeout"); goto out; } status = process_reap(main_proc); if (status != 0) { snprintf(errmsg, sizeof errmsg, "exit code %d", status); goto out; } if (benchmark_output) { /* Give the helpers time to clean up their act. */ uv_sleep(1000); } out: /* Reap running processes except the main process, it's already dead. */ for (i = 0; i < process_count - 1; i++) { process_terminate(&processes[i]); } if (process_count > 0 && process_wait(processes, process_count - 1, -1) < 0) { FATAL("process_wait failed"); } /* Show error and output from processes if the test failed. */ if (status != 0 || task->show_output) { if (tap_output) { LOGF("not ok %d - %s\n#", test_count, test); } else if (status != 0) { LOGF("\n`%s` failed: %s\n", test, errmsg); } else { LOGF("\n"); } for (i = 0; i < process_count; i++) { switch (process_output_size(&processes[i])) { case -1: LOGF("Output from process `%s`: (unavailable)\n", process_get_name(&processes[i])); break; case 0: LOGF("Output from process `%s`: (no output)\n", process_get_name(&processes[i])); break; default: LOGF("Output from process `%s`:\n", process_get_name(&processes[i])); process_copy_output(&processes[i], fileno(stderr)); break; } } if (!tap_output) { LOG("=============================================================\n"); } /* In benchmark mode show concise output from the main process. */ } else if (benchmark_output) { switch (process_output_size(main_proc)) { case -1: LOGF("%s: (unavailable)\n", test); break; case 0: LOGF("%s: (no output)\n", test); break; default: for (i = 0; i < process_count; i++) { process_copy_output(&processes[i], fileno(stderr)); } break; } } else if (tap_output) { LOGF("ok %d - %s\n", test_count, test); } /* Clean up all process handles. */ for (i = 0; i < process_count; i++) { process_cleanup(&processes[i]); } return status; }
/* * 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; }
/* * Runs all processes associated with a particular test or benchmark. * It returns 1 if the test succeeded, 0 if it failed. * If the test fails it prints diagnostic information. * If benchmark_output is nonzero, the output from the main process is * always shown. */ int run_task(task_entry_t *test, int timeout, int benchmark_output) { int i, result, success; char errmsg[256]; task_entry_t *helper; int process_count; process_info_t processes[MAX_PROCESSES]; process_info_t *main_process; success = 0; process_count = 0; /* Start all helpers for this test first. */ for (helper = (task_entry_t*)&TASKS; helper->main; helper++) { if (helper->is_helper && strcmp(test->task_name, helper->task_name) == 0) { if (process_start(helper->process_name, &processes[process_count]) == -1) { snprintf((char*)&errmsg, sizeof(errmsg), "process `%s` failed to start.", helper->process_name); goto finalize; } process_count++; } } /* Wait a little bit to allow servers to start. Racy. */ uv_sleep(50); /* Start the main test process. */ if (process_start(test->process_name, &processes[process_count]) == -1) { snprintf((char*)&errmsg, sizeof(errmsg), "process `%s` failed to start.", test->process_name); goto finalize; } main_process = &processes[process_count]; process_count++; /* Wait for the main process to terminate. */ result = process_wait(main_process, 1, timeout); if (result == -1) { FATAL("process_wait failed"); } else if (result == -2) { snprintf((char*)&errmsg, sizeof(errmsg), "timeout."); goto finalize; } /* Reap the main process. */ result = process_reap(main_process); if (result != 0) { snprintf((char*)&errmsg, sizeof(errmsg), "exit code %d.", result); goto finalize; } /* Yes! did it. */ success = 1; finalize: /* Kill all (helper) processes that are still running. */ for (i = 0; i < process_count; i++) { /* If terminate fails the process is probably already closed. */ process_terminate(&processes[i]); } /* Wait until all processes have really terminated. */ if (process_wait((process_info_t*)&processes, process_count, -1) < 0) { FATAL("process_wait failed"); } /* Show error and output from processes if the test failed. */ if (!success) { LOGF("\n`%s` failed: %s\n", test->task_name, errmsg); for (i = 0; i < process_count; i++) { switch (process_output_size(&processes[i])) { case -1: LOGF("Output from process `%s`: (unavailable)\n", process_get_name(&processes[i])); break; case 0: LOGF("Output from process `%s`: (no output)\n", process_get_name(&processes[i])); break; default: LOGF("Output from process `%s`:\n", process_get_name(&processes[i])); process_copy_output(&processes[i], fileno(stderr)); break; } } LOG("=============================================================\n"); /* In benchmark mode show concise output from the main process. */ } else if (benchmark_output) { switch (process_output_size(main_process)) { case -1: LOGF("%s: (unavailabe)\n", test->task_name); break; case 0: LOGF("%s: (no output)\n", test->task_name); break; default: //LOGF("%s: ", test->task_name); process_copy_output(main_process, fileno(stderr)); break; } } /* Clean up all process handles. */ for (i = 0; i < process_count; i++) { process_cleanup(&processes[i]); } return success; }
int main(int argc, char *argv[]) { const char client_name[] = "SteelSeries Sound Illuminator"; const char *client_name_real; jack_status_t status; J2STL j2stl; int ret; /* Memory initialization */ memset(&j2stl, 0, sizeof(j2stl)); pthread_mutex_init(&j2stl.memsync.mutex, NULL); pthread_cond_init(&j2stl.memsync.cond, NULL); j2stl.status.progname = basename(argv[0]); /* Options parsing */ opt_parse(argc, argv, &j2stl.status); if (j2stl.status.verbose) opt_dump(&j2stl.status); /* Stlseries init */ if (stlseries_open(&j2stl.kbd.stlseries)) { fprintf(stderr, "Unable to open steelseries keyboard.\n"); exit(EXIT_FAILURE); } /* Jack init */ j2stl.jack.client = jack_client_open(client_name, JackNoStartServer, &status, NULL); if (j2stl.jack.client == NULL) { fprintf(stderr, "Unable to create jack client, status = " "0x%2.0x<\n", status); if (status & JackServerFailed) fprintf(stderr, "Unable to establish a connection to " "the server\n"); exit(EXIT_FAILURE); } if (status & JackNameNotUnique) { client_name_real = jack_get_client_name(j2stl.jack.client); fprintf(stderr, "Name assigned to the client: %s\n", client_name_real); } else { client_name_real = client_name; if (j2stl.status.verbose) fprintf(stderr, "Jack client name: %s\n", client_name_real); } /* Set jack callbacks */ jack_set_process_callback(j2stl.jack.client, jack_process, &j2stl); jack_on_shutdown(j2stl.jack.client, jack_shutdown, NULL); /* Retrieve audio format from jack */ j2stl.audio.sample_rate = jack_get_sample_rate(j2stl.jack.client); j2stl.audio.size = lrint((j2stl.status.sampling / 1000.0) * j2stl.audio.sample_rate); j2stl.audio.data = malloc(sizeof(jack_default_audio_sample_t) * j2stl.audio.size); if (j2stl.audio.data == NULL) { fprintf(stderr, "Unable to allocate memory for sound buffers: " "%s\n", strerror(errno)); exit(EXIT_FAILURE); } if (j2stl.status.verbose) fprintf(stderr, "Jack sample rate: %u\n", j2stl.audio.sample_rate); /* jack: port creation */ j2stl.jack.input_port = jack_port_register(j2stl.jack.client, "input", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); if (j2stl.jack.input_port == NULL) { fprintf(stderr, "No port available.\n"); exit(EXIT_FAILURE); } /* Threads launch */ if ((ret = pthread_create(&j2stl.status.fftw_thread, NULL, fftw_thread, &j2stl))) { fprintf(stderr, "Unable to spawn fftw thread: %s\n", strerror(ret)); exit(EXIT_FAILURE); } if (jack_activate(j2stl.jack.client) != 0) { fprintf(stderr, "Unable to activate client\n"); exit(EXIT_FAILURE); } if (j2stl.status.verbose) fprintf(stderr, "Jack client thread launched\n"); if (j2stl.status.timeout) sleep(j2stl.status.timeout); else for(;;); process_cleanup(&j2stl); return EXIT_SUCCESS; }
void jack_shutdown(void *arg) { process_cleanup((J2STL *)arg); exit(EXIT_FAILURE); }
static void syscall_exit (int status) { process_cleanup (status); syscall_release_files (); thread_exit (); }
bool __TI_process_descriptors(_Unwind_Phase phase, _Unwind_Exception *uexcep, _Unwind_Context *context, _Unwind_PR_Kind pr_kind, _UINT32 *descr_ptr, _Unwind_Reason_Code *reason, bool *ph2_call_unexpected) { bool reason_code_valid = false; #ifdef DEBUG_PR printf("PD: descriptor @ %p\n", descr_ptr); #endif /* DEBUG_PR */ /*-------------------------------------------------------------------*/ /* Process each descriptor. The descriptor list is terminated by a */ /* 0 word (first word of a valid descriptor, length, is never 0) */ /*-------------------------------------------------------------------*/ while (*descr_ptr) { _UINT32 length; _UINT32 offset; /*---------------------------------------------------------------*/ /* Based of PR kind, read in length and offset (16/32 bit) */ /*---------------------------------------------------------------*/ switch (pr_kind) { case _UPK_Su16: case _UPK_Lu16: case _UPK_PR3: case _UPK_PR4: length = ((_PR_Scope16 *)descr_ptr)->length; offset = ((_PR_Scope16 *)descr_ptr)->offset; descr_ptr += sizeof(_PR_Scope16)/sizeof(_UINT32); break; case _UPK_Lu32: length = ((_PR_Scope32 *)descr_ptr)->length; offset = ((_PR_Scope32 *)descr_ptr)->offset; descr_ptr += sizeof(_PR_Scope32)/sizeof(_UINT32); break; default: *reason = _URC_FAILURE; reason_code_valid = true; break; } /*---------------------------------------------------------------*/ /* Use LSB of length and offset to determine descriptor type */ /* 0,0 => cleanup, 0,1 => func espec, 1,0 => catch */ /*---------------------------------------------------------------*/ switch (((length & 1) << 1) | (offset & 1)) { case 0: /* Process a Cleanup Descriptor*/ { if (process_cleanup(uexcep, phase, context,&descr_ptr, length, offset)) { *reason = _URC_INSTALL_CONTEXT; reason_code_valid = true; } break; } case 1: /* Process a Function Exception Spec Descriptor */ { offset -= 1; /* Clear LSB */ if (process_fespec(uexcep, phase, context,&descr_ptr, length, offset, reason, ph2_call_unexpected)) reason_code_valid = true; break; } case 2: /* Process a Catch Descriptor*/ { length -= 1; /* Clear LSB */ if (process_catch(uexcep, phase, context,&descr_ptr, length, offset, reason)) reason_code_valid = true; break; } default: *reason = _URC_FAILURE; reason_code_valid = true; break; } if (reason_code_valid == true) break; } return reason_code_valid; }
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; }