Сокеты и многопоточность


У меня есть интересная (для меня) проблема... Существует два потока, один для захвата данных из std-входа и отправки их через сокет на сервер, а другой, который получает данные из блокирующего сокета. Итак, когда нет ответа от сервера, вызов recv () ждет неопределенно долго, верно? Но вместо того, чтобы блокировать только его вызывающий поток, он блокирует весь процесс! Почему это происходит?

boost::mutex     nvtMutex;
boost::mutex    strMutex;
boost::mutex    quitMutex;
bool        quit = false;

void *processServerOutput(void *arg)
{
    NVT *nvt = (NVT*)arg;
    while(1)
    {
        // Lock the quitMutex before trying to access to quit variable
        quitMutex.lock();
        if(quit)
        {
            quitMutex.unlock();
            pthread_exit(NULL);
        }
        else
            quitMutex.unlock();

        // Receive output from server
        nvtMutex.lock();
        nvt->receive();
        cout << Util::Instance()->iconv("koi8-r", "utf-8", nvt->getOutBuffer());
        nvtMutex.unlock();

        // Delay
        sleep(1);
    }
}

void *processUserInput(void *arg)
{
    NVT *nvt = (NVT*)arg;

    while(1)
    {
        // Get user's input
        //cin.getline(str, 1023);

        sleep(3);
        strcpy(str, "hello");

        // If we type 'quit', exit from thread
        if(strcmp(str, "quit") == 0)
        {
            // Lock quit variable before trying to modify it
            quitMutex.lock();
            quit = true;
            quitMutex.unlock();

            // Exit from thread
            pthread_exit(NULL);
        }

        // Send the input to server
        nvtMutex.lock();
        nvt->writeUserCommand(Util::Instance()->iconv("utf-8", "koi8-r", str));
        nvt->send();
        nvtMutex.unlock();
    }
}
2 2

2 ответа:

Вы держите nvtMutex внутри вызова NVT::recv. Так как оба потока должны заблокировать мьютекс, чтобы сделать его через итерацию, пока NVT::recv не возвращает другой поток не может прогрессировать.

Не зная подробностей этого класса NVT, Невозможно узнать, можно ли безопасно разблокировать мьютекс перед вызовом NVT::recv или этот класс не обеспечивает должной потокобезопасности, в которой вы нуждаетесь.

Если ваш код реализован правильно, recv блокирует только поток, который его вызывает.

Если это не так для вас, покажите минимальный пример кода, который демонстрирует проблему.