Beispiel #1
0
void cache_wait(AbstractCache * cache) {
#else
void cache_wait_dbg(const char * file, int line, AbstractCache * cache) {
#endif
    assert(is_dispatch_thread());
    assert(current_client.client != NULL);
    if (current_client.client != NULL) {
        current_cache = cache;
        cache_miss_cnt++;
#ifndef NDEBUG
        current_client.file = file;
        current_client.line = line;
        current_client.time_stamp = time(NULL);
        if (!cache_timer_posted) {
            post_event_with_delay(cache_timer, NULL, 5000000);
            cache_timer_posted = 1;
        }
#endif
    }
#ifndef NDEBUG
    else {
        trace(LOG_ALWAYS, "Illegal cache access at %s:%d", file, line);
    }
#endif
    exception(ERR_CACHE_MISS);
}
static ChannelServer * channel_server_create(PeerServer * ps, noPollCtx * np_ctx, noPollConn * np_listener, int is_ssl) {
    ServerNP * si = (ServerNP *)loc_alloc_zero(sizeof *si);
    /* TODO: need to investigate usage of sizeof(sockaddr_storage) for address buffer size */
    si->serv.close = server_close;
    si->sock = nopoll_conn_socket(np_listener);
    si->serv.ps = ps;
    if (server_list.next == NULL) {
        list_init(&server_list);
        post_event_with_delay(refresh_all_peer_servers, NULL, PEER_DATA_REFRESH_PERIOD * 1000000);
    }
    list_add_last(&si->serv.servlink, &channel_server_root);
    shutdown_set_normal(&channel_shutdown);
    list_add_last(&si->servlink, &server_list);
    refresh_peer_server(si->sock, ps);


    si->accreq.done = np_server_accept_done;
    si->accreq.u.user.data = si;
    si->accreq.u.user.func = np_wt_accept;
    si->accreq.client_data = si;
    si->accreq.type = AsyncReqUser;

    si->np_listener = np_listener;
    si->np_ctx = np_ctx;
    si->is_ssl = is_ssl;
    async_req_post(&si->accreq);
    return &si->serv;
}
Beispiel #3
0
static int lua_post_event(lua_State *L)
{
    struct post_event_extra *p;
    unsigned long delay;

    assert(L == luastate);

    if(lua_gettop(L) > 2 || !lua_isfunction(L, 1) ||
       (lua_gettop(L) > 1 && !(lua_isnil(L, 2) || lua_isnumber(L, 2)))) {
        luaL_error(L, "wrong number or type of arguments");
    }
    p = (struct post_event_extra *)lua_newuserdata(L, sizeof *p);
    memset(p, 0, sizeof *p);
    p->L = L;
    lua_pushvalue(L, -1);
    p->self_refp = luaref_new(L, p);
    lua_pushvalue(L, 1);
    p->handler_refp = luaref_new(L, p);
    trace(LOG_LUA, "lua_post_event %d", p->handler_refp);
    luaL_getmetatable(L, "tcf_post_event");
    lua_setmetatable(L, -2);
    delay = lua_tointeger(L, 2);
    if(delay == 0) {
        post_event(lua_post_event_cb, p);
    } else {
        post_event_with_delay(lua_post_event_cb, p, delay);
    }
    return 1;
}
static void np_write_stream(OutputStream * out, int byte) {
    ChannelNP * c = channel2np(out2channel(out));
    assert(c->magic == CHANNEL_MAGIC);
    if (!c->chan.out.supports_zero_copy || c->chan.out.cur >= c->chan.out.end - 32 || byte < 0) {
        if (c->out_bin_block != NULL) np_bin_block_end(c);
        if (c->chan.out.cur == c->chan.out.end) np_flush_with_flags(c, MSG_MORE);
        if (byte < 0 || byte == ESC) {
            char esc = 0;
            *c->chan.out.cur++ = ESC;
            if (byte == ESC) esc = 0;
            else if (byte == MARKER_EOM) esc = 1;
            else if (byte == MARKER_EOS) esc = 2;
            else assert(0);
            if (c->chan.out.cur == c->chan.out.end) np_flush_with_flags(c, MSG_MORE);
            *c->chan.out.cur++ = esc;
            if (byte == MARKER_EOM) {
                c->out_eom_cnt++;
                if (c->out_flush_cnt < 2) {
                    if (c->out_flush_cnt++ == 0) np_lock(&c->chan);
                    post_event_with_delay(np_flush_event, c, 0);
                }
            }
            return;
        }
    }
    else if (c->out_bin_block == NULL) {
        np_bin_block_start(c);
    }
    *c->chan.out.cur++ = (char)byte;
}
Beispiel #5
0
static void clear_stale_peers(void * x) {
    PeerServer ** sp = &peers;
    PeerServer * s;
    time_t timenow = time(NULL);
    int keep_timer = 0;

    assert(is_dispatch_thread());
    while ((s = *sp) != NULL) {
        if (s->expiration_time <= timenow) {
            /* Delete stale entry */
            *sp = s->next;
            notify_listeners(s, PS_EVENT_REMOVED);
            s->listed = 0;
            peer_server_free(s);
        }
        else {
            keep_timer = 1;
            sp = &s->next;
        }
    }
    if (keep_timer) {
        post_event_with_delay(clear_stale_peers, NULL, PEER_DATA_REFRESH_PERIOD * 1000000);
    }
    else {
        stale_timer_active = 0;
    }
}
static void refresh_all_peer_servers(void * x) {
    LINK * l = server_list.next;
    while (l != &server_list) {
        ServerNP * si = servlink2np(l);
        refresh_peer_server(si->sock, si->serv.ps);
        l = l->next;
    }
    post_event_with_delay(refresh_all_peer_servers, NULL, PEER_DATA_REFRESH_PERIOD * 1000000);
}
Beispiel #7
0
static void check_idle_timeout(void * args) {
    if (list_is_empty(&channel_root)) {
        idle_count++;
        if (idle_count > idle_timeout) {
            trace(LOG_ALWAYS, "No connections for %d seconds, shutting down", idle_timeout);
            discovery_stop();
            cancel_event_loop();
            return;
        }
    }
    post_event_with_delay(check_idle_timeout, NULL, 1000000);
}
Beispiel #8
0
void cache_wait(AbstractCache * cache) {
#else
void cache_wait_dbg(const char * file, int line, AbstractCache * cache) {
#endif
    assert(is_dispatch_thread());
    assert(client_exited == 0);
    if (current_client.client != NULL && cache_miss_cnt == 0) {
        if (cache->wait_list_cnt >= cache->wait_list_max) {
            cache->wait_list_max += 8;
            cache->wait_list_buf = (WaitingCacheClient *)loc_realloc(cache->wait_list_buf, cache->wait_list_max * sizeof(WaitingCacheClient));
        }
        if (current_client.args != NULL && !current_client.args_copy) {
            void * mem = loc_alloc(current_client.args_size);
            memcpy(mem, current_client.args, current_client.args_size);
            current_client.args = mem;
            current_client.args_copy = 1;
        }
#ifndef NDEBUG
        current_client.file = file;
        current_client.line = line;
        current_client.time_stamp = time(NULL);
        if (!cache_timer_posted) {
            post_event_with_delay(cache_timer, NULL, 5000000);
            cache_timer_posted = 1;
        }
#endif
        if (cache->wait_list_cnt == 0) list_add_last(&cache->link, &cache_list);
        if (current_client.channel != NULL) channel_lock_with_msg(current_client.channel, channel_lock_msg);
        cache->wait_list_buf[cache->wait_list_cnt++] = current_client;
    }
#ifndef NDEBUG
    else if (current_client.client == NULL) {
        trace(LOG_ALWAYS, "Illegal cache access at %s:%d", file, line);
    }
#endif
    cache_miss_cnt++;
    exception(ERR_CACHE_MISS);
}
Beispiel #9
0
static void cache_timer(void * x) {
    LINK * l;
    time_t time_now = time(NULL);

    assert(cache_timer_posted);
    cache_timer_posted = 0;
    for (l = cache_list.next; l != &cache_list; l = l->next) {
        unsigned i;
        AbstractCache * cache = link_all2cache(l);
        assert(cache->wait_list_cnt > 0);
        for (i = 0; i < cache->wait_list_cnt; i++) {
            WaitingCacheClient * client = cache->wait_list_buf + i;
            if (time_now - client->time_stamp >= 30) {
                /* Client is waiting longer than 30 sec - it might be a bug */
                trace(LOG_ALWAYS, "Stalled cache at %s:%d", client->file, client->line);
            }
        }
    }
    if (!list_is_empty(&cache_list)) {
        post_event_with_delay(cache_timer, NULL, 5000000);
        cache_timer_posted = 1;
    }
}
Beispiel #10
0
static void pipe_write_stream(OutputStream * out, int byte) {
    ChannelPIPE * c = channel2pipe(out2channel(out));
    assert(c->magic == CHANNEL_MAGIC);
    if (c->chan->state == ChannelStateDisconnected) return;
    if (c->chan->out.cur == c->chan->out.end) pipe_flush(c);
    if (byte < 0 || byte == ESC) {
        char esc = 0;
        *c->chan->out.cur++ = ESC;
        if (byte == ESC) esc = 0;
        else if (byte == MARKER_EOM) esc = 1;
        else if (byte == MARKER_EOS) esc = 2;
        else assert(0);
        if (c->chan->state == ChannelStateDisconnected) return;
        if (c->chan->out.cur == c->chan->out.end) pipe_flush(c);
        *c->chan->out.cur++ = esc;
        if (byte == MARKER_EOM && c->out_flush_cnt < 2) {
            if (c->out_flush_cnt++ == 0) pipe_lock(c->chan);
            post_event_with_delay(pipe_flush_event, c, 0);
        }
        return;
    }
    *c->chan->out.cur++ = (char)byte;
}
Beispiel #11
0
PeerServer * peer_server_add(PeerServer * n, unsigned int stale_delta) {
    PeerServer ** sp = &peers;
    PeerServer * s;
    int type = PS_EVENT_ADDED;

    assert(!n->listed);
    assert(is_dispatch_thread());
    while ((s = *sp) != NULL) {
        if (strcmp(s->id, n->id) == 0) {
            if (((s->flags & PS_FLAG_LOCAL) && !(n->flags & PS_FLAG_LOCAL)) || is_same(s, n)) {
                /* Never replace local entries with discovered ones */
                s->expiration_time = time(NULL) + stale_delta;
                if (!(s->flags & PS_FLAG_LOCAL)) s->flags = n->flags;
                peer_server_free(n);
                notify_listeners(s, PS_EVENT_HEART_BEAT);
                return s;
            }
            *sp = s->next;
            s->listed = 0;
            peer_server_free(s);
            type = PS_EVENT_CHANGED;
            break;
        }
        sp = &s->next;
    }
    n->listed = 1;
    n->creation_time = time(NULL);
    n->expiration_time = n->creation_time + stale_delta;
    n->next = peers;
    peers = n;
    notify_listeners(n, type);
    if (!stale_timer_active) {
        stale_timer_active = 1;
        post_event_with_delay(clear_stale_peers, NULL, PEER_DATA_REFRESH_PERIOD * 1000000);
    }
    return n;
}
static void port_connection_close(PortConnection * conn) {
    PortServer * server = conn->server;
    PortConnection * prev;

    port_connection_unbind(conn);
    if (conn->connected) {
        if (server->disconnect_callback) server->disconnect_callback(server, server->callback_data);
        disconnect_port(conn);
        conn->connected = 0;
        return;
    }

    if (conn->lock_cnt > 0) return;
    if (server->list == conn) server->list = conn->next;
    else {
        prev = server->list;
        while (prev->next != conn)
            prev = prev->next;
        assert (prev->next == conn);
        prev->next = conn->next;
    }
    loc_free(conn);

    /* If the last port connection has been closed and server shutdown is
     * in progress, complete it.
     */
    if (server->list == NULL) {
        if (server->sock == -1) {
            port_server_shutdown(server);
        }
        else if (server->auto_connect) {
            /* Retry target connection */
            post_event_with_delay(port_connection_open_event, server, server->auto_connect_period * 1000000);
        }
    }
}
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);
}