void pa_shutdown(){
    if(source_names != NULL){
        delete source_names;
    }
    context_stop();
}
static void run_safe_events(void * arg) {
    LINK * qp;
    pid_t mem;

    if ((uintptr_t)arg != safe_event_generation) return;
    assert(safe_event_list != NULL);
    assert(are_channels_suspended(suspend_group));

    safe_event_pid_count = 0;
    mem = safe_event_list->mem;

    for (qp = context_root.next; qp != &context_root; qp = qp->next) {
        Context * ctx = ctxl2ctxp(qp);
        if (ctx->exited || ctx->exiting || ctx->stopped || !context_has_state(ctx)) {
            ctx->pending_safe_event = 0;
            continue;
        }
        if (mem > 0 && ctx->mem != mem) {
            ctx->pending_safe_event = 0;
            continue;
        }
        if (!ctx->pending_step || ctx->pending_safe_event >= STOP_ALL_MAX_CNT / 2) {
            if (context_stop(ctx) < 0) {
                int error = errno;
#ifdef _WRS_KERNEL
                if (error == S_vxdbgLib_INVALID_CTX) {
                    /* Most often this means that context has exited,
                     * but exit event is not delivered yet.
                     * Not an error. */
                    error = 0;
                }
#endif
                if (error) {
                    trace(LOG_ALWAYS, "error: can't temporary stop pid %d; error %d: %s",
                        ctx->pid, error, errno_to_str(error));
                }
            }
            assert(!ctx->stopped);
        }
        if (ctx->pending_safe_event >= STOP_ALL_MAX_CNT) {
            trace(LOG_ALWAYS, "error: can't temporary stop pid %d; error: timeout", ctx->pid);
            ctx->exiting = 1;
            ctx->pending_safe_event = 0;
        }
        else {
            ctx->pending_safe_event++;
            safe_event_pid_count++;
        }
    }

    while (safe_event_list) {
        Trap trap;
        SafeEvent * i = safe_event_list;
        assert((uintptr_t)arg == safe_event_generation);
        if (safe_event_pid_count > 0) {
            post_event_with_delay(run_safe_events, (void *)++safe_event_generation, STOP_ALL_TIMEOUT);
            return;
        }
        if (mem > 0 && i->mem != mem) {
            post_event(run_safe_events, (void *)++safe_event_generation);
            return;
        }
        assert(is_all_stopped(i->mem));
        safe_event_list = i->next;
        if (set_trap(&trap)) {
            i->done(i->arg);
            clear_trap(&trap);
        }
        else {
            trace(LOG_ALWAYS, "Unhandled exception in \"safe\" event dispatch: %d %s",
                  trap.error, errno_to_str(trap.error));
        }
        loc_free(i);
        if ((uintptr_t)arg != safe_event_generation) return;
    }

    channels_resume(suspend_group);
    cmdline_resume();
    /* Lazily continue execution of temporary stopped contexts */
    post_event(continue_temporary_stopped, (void *)safe_event_generation);
}