static int ipc_thread_exit (IDTYPE vmid, IDTYPE tid, unsigned int exitcode) { assert(vmid != cur_process.vmid); struct shim_thread * thread = __lookup_thread(tid); if (thread) { int ret = 0; //assert(thread->vmid == vmid && !thread->in_vm); thread->exit_code = -exitcode; ret = thread_exit(thread, false); put_thread(thread); return ret; } struct shim_simple_thread * sthread = __lookup_simple_thread(tid); if (!sthread) { sthread = get_new_simple_thread(); sthread->vmid = vmid; sthread->tid = tid; add_simple_thread(sthread); } sthread->is_alive = 0; sthread->exit_code = -exitcode; DkEventSet(sthread->exit_event); put_simple_thread(sthread); return 0; }
int try_process_exit (int error_code, int term_signal) { struct shim_thread * cur_thread = get_cur_thread(); cur_thread->exit_code = -error_code; cur_process.exit_code = error_code; cur_thread->term_signal = term_signal; if (cur_thread->in_vm) thread_exit(cur_thread, true); if (check_last_thread(cur_thread)) return 0; struct shim_thread * async_thread = terminate_async_helper(); if (async_thread) /* TODO: wait for the thread to exit in host. * This is tracked by the following issue. * https://github.com/oscarlab/graphene/issues/440 */ put_thread(async_thread); /* free resources of the thread */ struct shim_thread * ipc_thread; int ret = exit_with_ipc_helper(true, &ipc_thread); if (ipc_thread) /* TODO: wait for the thread to exit in host. * This is tracked by the following issue. * https://github.com/oscarlab/graphene/issues/440 */ put_thread(ipc_thread); /* free resources of the thread */ if (!ret) shim_clean(ret); else DkThreadExit(); return 0; }
pid_t shim_do_wait4 (pid_t pid, int * status, int option, struct __kernel_rusage * ru) { struct shim_thread * cur = get_cur_thread(); struct shim_thread * thread = NULL; int ret = 0; INC_PROFILE_OCCURENCE(syscall_use_ipc); if (pid > 0) { if (!(thread = lookup_thread(pid))) return -ECHILD; if (!(option & WNOHANG)) { block_pid: DkObjectsWaitAny(1, &thread->exit_event, NO_TIMEOUT); } lock(thread->lock); if (thread->is_alive) { unlock(thread->lock); if (!(option & WNOHANG)) goto block_pid; put_thread(thread); return 0; } if (!list_empty(&thread->siblings)) { struct shim_thread * parent = thread->parent; assert(parent); lock(parent->lock); list_del_init(&thread->siblings); unlock(parent->lock); put_thread(parent); put_thread(thread); thread->parent = NULL; } unlock(thread->lock); goto found; } lock(cur->lock); if (list_empty(&cur->children) && list_empty(&cur->exited_children)) { unlock(cur->lock); return -ECHILD; } if (!(option & WNOHANG)) { block: if (cur->child_exit_event) while (list_empty(&cur->exited_children)) { unlock(cur->lock); DkObjectsWaitAny(1, &cur->child_exit_event, NO_TIMEOUT); lock(cur->lock); } } if (pid == 0 || pid < -1) { if (pid == 0) pid = -cur->pgid; list_for_each_entry(thread, &cur->exited_children, siblings) if (thread->pgid == -pid) goto found_child; if (!(option & WNOHANG)) goto block; } else { if (!list_empty(&cur->exited_children)) {
static int find_thread_link (const char * name, struct shim_qstr * link, struct shim_dentry ** dentptr, struct shim_thread ** threadptr) { const char * next, * nextnext; int next_len; int pid = parse_thread_name(name, &next, &next_len, &nextnext); if (pid < 0) return pid; struct shim_thread * thread = lookup_thread(pid); struct shim_dentry * dent = NULL; int ret = 0; if (!thread) return -ENOENT; if (!thread->in_vm) { ret = -ENOENT; goto out; } lock(&thread->lock); if (next_len == static_strlen("root") && !memcmp(next, "root", next_len)) { dent = thread->root; get_dentry(dent); } if (next_len == static_strlen("cwd") && !memcmp(next, "cwd", next_len)) { dent = thread->cwd; get_dentry(dent); } if (next_len == static_strlen("exe") && !memcmp(next, "exe", next_len)) { struct shim_handle * exec = thread->exec; if (!exec->dentry) { unlock(&thread->lock); ret = -EINVAL; goto out; } dent = exec->dentry; get_dentry(dent); } unlock(&thread->lock); if (nextnext) { struct shim_dentry * next_dent = NULL; ret = path_lookupat(dent, nextnext, 0, &next_dent, dent->fs); if (ret < 0) goto out; put_dentry(dent); dent = next_dent; } if (link) { int size; char * path = dentry_get_path(dent, true, &size); qstrsetstr(link, path, size); } if (dentptr) { get_dentry(dent); *dentptr = dent; } if (threadptr) { get_thread(thread); *threadptr = thread; } ret = 0; out: if (dent) put_dentry(dent); if (thread) put_thread(thread); return ret; }