static void command_get_children(char * token, Channel * c) { char id[256]; json_read_string(&c->inp, id, sizeof(id)); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); write_stringz(&c->out, "R"); write_stringz(&c->out, token); write_errno(&c->out, 0); write_stream(&c->out, '['); if (id[0] == 0) { LINK * qp; int cnt = 0; for (qp = context_root.next; qp != &context_root; qp = qp->next) { Context * ctx = ctxl2ctxp(qp); if (ctx->exited) continue; if (ctx->parent != NULL) continue; if (cnt > 0) write_stream(&c->out, ','); json_write_string(&c->out, container_id(ctx)); cnt++; } } else if (id[0] == 'P') { LINK * qp; int cnt = 0; pid_t ppd = 0; Context * parent = id2ctx(id); id2pid(id, &ppd); if (parent != NULL && parent->parent == NULL && ppd == 0) { if (!parent->exited && context_has_state(parent)) { if (cnt > 0) write_stream(&c->out, ','); json_write_string(&c->out, thread_id(parent)); cnt++; } for (qp = parent->children.next; qp != &parent->children; qp = qp->next) { Context * ctx = cldl2ctxp(qp); assert(!ctx->exited); assert(ctx->parent == parent); if (cnt > 0) write_stream(&c->out, ','); json_write_string(&c->out,thread_id(ctx)); cnt++; } } } write_stream(&c->out, ']'); write_stream(&c->out, 0); write_stream(&c->out, MARKER_EOM); }
static void command_get_children(char * token, Channel * c) { char id[256]; json_read_string(&c->inp, id, sizeof(id)); json_test_char(&c->inp, MARKER_EOA); json_test_char(&c->inp, MARKER_EOM); write_stringz(&c->out, "R"); write_stringz(&c->out, token); write_errno(&c->out, 0); write_stream(&c->out, '['); if (id[0] == 0) { LINK * qp; int cnt = 0; for (qp = context_root.next; qp != &context_root; qp = qp->next) { Context * ctx = ctxl2ctxp(qp); if (ctx->parent != NULL) continue; if (ctx->exited) continue; if (ctx->mem_access == 0 && list_is_empty(&ctx->children)) continue; if (cnt > 0) write_stream(&c->out, ','); json_write_string(&c->out, ctx->id); cnt++; } } else { Context * parent = id2ctx(id); if (parent != NULL) { LINK * l; int cnt = 0; for (l = parent->children.next; l != &parent->children; l = l->next) { Context * ctx = cldl2ctxp(l); assert(ctx->parent == parent); if (ctx->exited) continue; if (ctx->mem_access == 0 && list_is_empty(&ctx->children)) continue; if (cnt > 0) write_stream(&c->out, ','); json_write_string(&c->out, ctx->id); cnt++; } } } write_stream(&c->out, ']'); write_stream(&c->out, 0); write_stream(&c->out, MARKER_EOM); }
static void event_terminate(void * x) { TerminateArgs * args = (TerminateArgs *)x; Context * ctx = args->ctx; TCFBroadcastGroup * bcg = args->bcg; LINK * qp = ctx->children.next; while (qp != &ctx->children) { Context * c = cldl2ctxp(qp); if (c->intercepted) send_event_context_resumed(&bcg->out, c); c->pending_intercept = 0; c->pending_signals |= 1 << SIGKILL; qp = qp->next; } if (ctx->intercepted) send_event_context_resumed(&bcg->out, ctx); ctx->pending_intercept = 0; ctx->pending_signals |= 1 << SIGKILL; context_unlock(ctx); loc_free(args); }
static void event_pid_exited(pid_t pid, int status, int signal) { Context * ctx; ctx = context_find_from_pid(pid, 1); if (ctx == NULL) { ctx = find_pending(pid); if (ctx == NULL) { trace(LOG_EVENTS, "event: ctx not found, pid %d, exit status %d, term signal %d", pid, status, signal); } else { assert(ctx->ref_count == 0); ctx->ref_count = 1; if (EXT(ctx)->attach_callback != NULL) { if (status == 0) status = EINVAL; EXT(ctx)->attach_callback(status, ctx, EXT(ctx)->attach_data); } assert(list_is_empty(&ctx->children)); assert(ctx->parent == NULL); ctx->exited = 1; context_unlock(ctx); } } else { /* Note: ctx->exiting should be 1 here. However, PTRACE_EVENT_EXIT can be lost by PTRACE because of racing * between PTRACE_CONT (or PTRACE_SYSCALL) and SIGTRAP/PTRACE_EVENT_EXIT. So, ctx->exiting can be 0. */ if (EXT(ctx->parent)->pid == pid) ctx = ctx->parent; assert(EXT(ctx)->attach_callback == NULL); if (ctx->exited) { trace(LOG_EVENTS, "event: ctx %#lx, pid %d, exit status %d unexpected, stopped %d, exited %d", ctx, pid, status, ctx->stopped, ctx->exited); } else { trace(LOG_EVENTS, "event: ctx %#lx, pid %d, exit status %d, term signal %d", ctx, pid, status, signal); ctx->exiting = 1; if (ctx->stopped) send_context_started_event(ctx); if (!list_is_empty(&ctx->children)) { LINK * l = ctx->children.next; while (l != &ctx->children) { Context * c = cldl2ctxp(l); l = l->next; assert(c->parent == ctx); if (!c->exited) { c->exiting = 1; if (c->stopped) send_context_started_event(c); release_error_report(EXT(c)->regs_error); loc_free(EXT(c)->regs); EXT(c)->regs_error = NULL; EXT(c)->regs = NULL; send_context_exited_event(c); } } } release_error_report(EXT(ctx)->regs_error); loc_free(EXT(ctx)->regs); EXT(ctx)->regs_error = NULL; EXT(ctx)->regs = NULL; send_context_exited_event(ctx); } } }