yinqiwen / ardb

A redis protocol compatible nosql, it support multiple storage engines as backend like Google's LevelDB, Facebook's RocksDB, OpenLDAP's LMDB, PerconaFT, WiredTiger, ForestDB.
BSD 3-Clause "New" or "Revised" License
1.83k stars 278 forks source link

fix segmentation fault when maxclients is reached #486

Open hotpxl opened 4 years ago

hotpxl commented 4 years ago

When maxclients is reached, and another client connects,

void SocketChannel::OnAccepted()
{
    if (aeCreateFileEvent(GetService().GetRawEventLoop(), m_fd, AE_READABLE, Channel::IOEventCallback, this) == AE_ERR)
    {
        int err = errno;
        ERROR_LOG("Failed to add event for accepted client for fd:%d for reason:%s", m_fd, strerror(err));
        Close();
        return;
    }
    m_detached = false;
    m_state = SOCK_CONNECTED;
    fire_channel_open(this);
    fire_channel_connected(this);

    //INFO_LOG("Accepted on tid:%d", Thread::CurrentThreadID());
}

aeCreateFileEvent here will return AE_ERR, and Close() is immediately called. Eventually ARDB::FreeClient is called, which in turn calls UnblockKeys(ctx, true, NULL);, and we step into this function. But because a connection is never set up, ctx.client->client is a null pointer, so it'll crash with a segmentation fault. Fixing this allows connections to be closed graciously in the event maxclients is reached.