Сбой после слишком большого количества сокетов - PullRequest
0 голосов
/ 28 сентября 2018

Когда клиент подключается к моему серверу через сокет (домен Unix), кажется, что все работает хорошо: соединение устанавливается, запрос обрабатывается, клиент получает ответ, и соединение закрывается.Однако после определенного количества соединений сервер вылетает.Я проверил петлю соединения и обнаружил, что идентификатор соединения, возвращаемый функцией сокета accept() (обернутый в app.newConnectionEstablished()), продолжает увеличиваться, пока не достигнет предела 1024, и программа не выйдет из строя.

Почему идентификатор соединения не всегда сбрасывается до самого низкого доступного номера?

#include <thread>
#include <mutex>
#include <condition_variable>
#include <deque>

#include "UdsServer.hpp"
#include "RequestManager.hpp"
#include "MSutils.hpp"


RequestManager service;


std::deque<std::string> requestQueue;
std::deque<int> connectionQueue;

std::mutex requestQueue_mutex;
std::condition_variable threadSwitch;

bool gotNewRequests = false;


void processRequest ()
{
    UnixDomainSocket uds;

    std::unique_lock<std::mutex> writeLock(requestQueue_mutex);

    while (true)
    {
        while (!gotNewRequests) 
            threadSwitch.wait(writeLock);

        auto currentRequest = requestQueue[0];
        auto currentConnection = connectionQueue[0];

        requestQueue.pop_front();
        connectionQueue.pop_front();

        gotNewRequests = false;

        writeLock.unlock();

        const std::string & response = service.processRequest(currentRequest);

        if (response.length())
        {
            auto ret = uds.sendMsg(currentConnection, response);

            if (!ret.isValid())
                MF::log("Could not send the response for request.");
        }

        uds.closeConnection(currentConnection);

        writeLock.lock();
    }
}


int main()
{
    UdsServer app;

    app.createServer("./App.sock");


    unsigned n_concThreads = 6;


    for (int i = 0; i < n_concThreads; ++i)
    {
        std::thread t (processRequest);
        t.detach();
    }

    int clientConnection = -1;

    while ((clientConnection = app.newConnectionEstablished()) > -1)
    {
        std::string command = app.getMsg (clientConnection);

        {
            std::unique_lock<std::mutex> writeLock(requestQueue_mutex);

            requestQueue.push_back(command);
            connectionQueue.push_back(clientConnection);
            gotNewRequests = true;
        } //Get rid of the lock before notifying the threads

        threadSwitch.notify_all(); //nothing happens here if all threads are busy
    }
}

Вот как соединения открываются и закрываются (показывая идентификатор соединения):

open 6
close 6
open 7
close 7
open 6
close 6
open 6
close 6
open 6
close 6
open 19
close 19
open 6
close 6
open 6
close 6
open 28
close 28
open 6
close 6
open 6
close 6
open 37
close 37
open 6
...
...