int shim_do_getsid (pid_t pid) { struct shim_thread * thread = pid ? lookup_thread(pid) : get_cur_thread(); if (!thread) return -ESRCH; return thread->pgid; }
void signal_alarm (IDTYPE target, void * arg) { debug("alarm goes off, signaling thread %u\n", target); struct shim_thread * thread = lookup_thread(target); if (!thread) return; append_signal(thread, SIGALRM, NULL, true); }
void signal_io (IDTYPE target, void * arg) { debug("detecting input, signaling thread %u\n", target); struct shim_thread * thread = lookup_thread(target); if (!thread) return; append_signal(thread, SIGIO, NULL, true); }
/* If *phdl is returned on success, the ref count is incremented */ static int parse_thread_fd (const char * name, const char ** rest, struct shim_handle ** phdl) { const char * next, * nextnext; int next_len; int pid = parse_thread_name(name, &next, &next_len, &nextnext); if (!pid) return pid; if (!next || !nextnext || memcmp(next, "fd", next_len)) return -EINVAL; const char * p = nextnext; int fd = 0; for ( ; *p && *p != '/' ; p++) { if (*p < '0' || *p > '9') return -ENOENT; fd = fd * 10 + *p - '0'; if (fd >= __rlim[RLIMIT_NOFILE].rlim_cur) return -ENOENT; } struct shim_thread * thread = lookup_thread(pid); if (!thread) return -ENOENT; struct shim_handle_map * handle_map = get_cur_handle_map(thread); lock(&handle_map->lock); if (fd >= handle_map->fd_top || handle_map->map[fd] == NULL || handle_map->map[fd]->handle == NULL) { unlock(&handle_map->lock); return -ENOENT; } if (phdl) { *phdl = handle_map->map[fd]->handle; get_handle(*phdl); } unlock(&handle_map->lock); if (rest) *rest = *p ? p + 1 : NULL; return 0; }
int shim_do_setpgid (pid_t pid, pid_t pgid) { struct shim_thread * thread = pid ? lookup_thread(pid) : get_cur_thread(); if (!pid) assert(thread); if (!thread) return -ESRCH; thread->pgid = pgid ? : thread->tgid; return 0; }
static int proc_list_thread_each_fd (const char * name, struct shim_dirent ** buf, int count) { const char * next; int next_len; int pid = parse_thread_name(name, &next, &next_len, NULL); if (!pid) return pid; if (!next || memcmp(next, "fd", next_len)) return -EINVAL; struct shim_thread * thread = lookup_thread(pid); if (!thread) return -ENOENT; struct shim_handle_map * handle_map = get_cur_handle_map(thread); int err = 0, bytes = 0; struct shim_dirent * dirent = *buf, ** last = NULL; lock(&handle_map->lock); for (int i = 0 ; i < handle_map->fd_size ; i++) if (handle_map->map[i] && handle_map->map[i]->handle) { int d = i, l = 0; for ( ; d ; d /= 10, l++); l = l ? : 1; bytes += sizeof(struct shim_dirent) + l + 1; if (bytes > count) { err = -ENOMEM; break; } dirent->next = (void *) (dirent + 1) + l + 1; dirent->ino = 1; dirent->type = LINUX_DT_LNK; dirent->name[0] = '0'; dirent->name[l--] = 0; for (d = i ; d ; d /= 10) dirent->name[l--] = '0' + d % 10; last = &dirent->next; dirent = dirent->next; }
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; }