Repository: valkey-io/valkey
File: src/networking.c (C)

Code before:
    if (c->name) decrRefCount(c->name);
    if (c->lib_name) decrRefCount(c->lib_name);
    if (c->lib_ver) decrRefCount(c->lib_ver);
    freeClientMultiState(c);
    sdsfree(c->peerid);
    sdsfree(c->sockname);
    zfree(c);
}

/* Schedule a client to free it at a safe time in the beforeSleep() function.
 * This function is useful when we need to terminate a client but we are in
 * a context where calling freeClient() is not possible, because the client
 * should be valid for the continuation of the flow of the program. */
void freeClientAsync(client *c) {
    if (c->flag.close_asap || c->flag.script) return;
    c->flag.close_asap = 1;
    debugServerAssertWithInfo(c, NULL, listSearchKey(server.clients_to_close, c) == NULL);
    listAddNodeTail(server.clients_to_close, c);
}

/* Log errors for invalid use and free the client in async way.
 * We will add additional information about the client to the message. */
void logInvalidUseAndFreeClientAsync(client *c, const char *fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    sds info = sdscatvprintf(sdsempty(), fmt, ap);
    va_end(ap);

    sds client = catClientInfoString(sdsempty(), c, server.hide_user_data_from_log);
    serverLog(LL_WARNING, "%s, disconnecting it: %s", info, client);

    sdsfree(info);
    sdsfree(client);
    freeClientAsync(c);
}

/* Resets the shared query buffer used by the given client.
 * If any data remained in the buffer, the client will take ownership of the buffer
 * and a new empty buffer will be allocated for the shared buffer. */
void resetSharedQueryBuf(client *c) {
    serverAssert(c->querybuf == thread_shared_qb);
    size_t remaining = sdslen(c->querybuf) - c->qb_pos;

    if (remaining > 0) {
        /* Let the client take ownership of the shared buffer. */
        initSharedQueryBuf();
        return;
    }

    c->querybuf = NULL;
    sdsclear(thread_shared_qb);

Review comment (suggestion):
Just thinking... There's a difference between `server.current_client` and `server.executing_client`. In most cases they're the same, but in scripts the executing client is a fake client and current client is the real client.

Is it possible to call `ACL LOAD` or `resetchannels` from a Lua script? Maybe we should test it.

Code after:
    if (c->name) decrRefCount(c->name);
    if (c->lib_name) decrRefCount(c->lib_name);
    if (c->lib_ver) decrRefCount(c->lib_ver);
    freeClientMultiState(c);
    sdsfree(c->peerid);
    sdsfree(c->sockname);
    zfree(c);
}

/* Schedule a client to free it at a safe time in the beforeSleep() function.
 * This function is useful when we need to terminate a client but we are in
 * a context where calling freeClient() is not possible, because the client
 * should be valid for the continuation of the flow of the program. */
void freeClientAsync(client *c) {
    if (c->flag.close_asap || c->flag.script) return;
    c->flag.close_asap = 1;
    debugServerAssertWithInfo(c, NULL, listSearchKey(server.clients_to_close, c) == NULL);
    listAddNodeTail(server.clients_to_close, c);
}
/* Helper function to free a client or flag it for closure after current command.
 * We can't free the current client right now because that would trigger an
 * assert in prepareClientToWrite() when the server tries to write the response.
 * So instead flag it for closure after the current command completes. */
void freeClientOrCloseLater(client *c, int async) {
    if (c == server.current_client) {
        c->flag.close_after_command = 1;
    } else {
        if (async) {
            freeClientAsync(c);
        } else {
            freeClient(c);
        }
    }
}


/* Log errors for invalid use and free the client in async way.
 * We will add additional information about the client to the message. */
void logInvalidUseAndFreeClientAsync(client *c, const char *fmt, ...) {
    va_list ap;
    va_start(ap, fmt);
    sds info = sdscatvprintf(sdsempty(), fmt, ap);
    va_end(ap);

    sds client = catClientInfoString(sdsempty(), c, server.hide_user_data_from_log);
    serverLog(LL_WARNING, "%s, disconnecting it: %s", info, client);

    sdsfree(info);
    sdsfree(client);
    freeClientAsync(c);
}