2017-02-18 4 views
0

У меня многопоточное приложение, оно периодически опросает несколько сотен устройств. Каждый поток обслуживает одно устройство, его сокет и другие дескрипторы инкапсулируются на отдельный объект, поэтому нет общих дескрипторов. Иногда аварийные ситуации приложения после closesocket (fSock), когда я пытаюсь установить дескриптор fSock на 0.Сбой сервера после closesocket

Я предполагаю, что я не должен устанавливать fSock = 0, если closesocket (fSock) возвращает SOCKET_ERROR. Или есть ли другая причина?

Мой код:

bool _EthDev::Connect() 
{ 
    int sockErr, ret, i, j; 
    int szOut = sizeof(sockaddr_in); 

    // create socket 
    if ((fSock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) 
    { 
     sockErr = GetLastError(); 
     Log("Invalid socket err %d", sockErr); 
     fSock = 0; 
     return false; 
    } 

    // set fast closing socket (by RST) 
    linger sLinger; 
    sLinger.l_onoff = 1; 
    sLinger.l_linger = 0; 
    if (sockErr = setsockopt(fSock, SOL_SOCKET, SO_LINGER, (const char FAR*)&sLinger, sizeof(linger))) 
    { 
     sockErr = WSAGetLastError(); 
     Log("Setsockopt err %d", sockErr); 
     closesocket(fSock); 
     fSock = 0;   // here crashes 
     return false; 
    } 

    // connect to device 
    fSockaddr.sin_port = htons((u_short)(baseport)); 
    if (connect(fSock, (struct sockaddr*)&fSockaddr, szOut)) 
    { 
     closesocket(fSock); 
     fSock = 0; 
     return false; 
    } 

    ... 

    return true; 
} 
+0

Zero не является недопустимым значением для сокета. Если вы хотите указать, что fSock больше не является допустимым сокетом, вы должны установить его вместо INVALID_SOCKET, а не 0, потому что INVALID_SOCKET по определению является значением, которое никогда не будет использоваться действительным сокетом. –

ответ

0

У меня есть многопоточность приложения, ... [он] иногда падает

А приложение многопоточность, что иногда происходит сбой является классическим симптомом состояния гонки. Я думаю, что для предотвращения сбоев вам нужно выяснить, что такое состояние гонки в вашем коде, и исправить это.

Я предполагаю, что я не должен установить fSock = 0, если closesocket (fSock) возвращает SOCKET_ERROR. Или есть другая причина?

Я сомневаюсь, что проблема на самом деле связано с closesocket() или установка fSock 0. Имейте в виду, что разъемы на самом деле являются целыми числами, и установив целое число 0, вероятно, причиной аварии на не его своя. Что может вызвать сбой - это запись в недопустимую память - и fSock = 0 записывает в ячейку памяти, где переменная-член fSock находится (или была) расположена по адресу.

Поэтому более вероятной гипотезой является то, что объект _EthDev был удален потоком B, в то время как поток A все еще находился в середине вызова Connect() на нем. Это, скорее всего, произойдет во время вызова connect(), потому что вызов блокировки connect() может занять относительно долгое время. Так что если был еще один поток, который грубо удалил объект _EthDev во время вызова connect(), то, как только connect() вернётся, следующая строка кода, которая будет записывать в место, где используется (теперь удаленный) объект _EthDev было бы «fSock = 0;» и это может привести к сбою.

Я предлагаю вам просмотреть свой код, который удаляет объекты _EthDev, и если он не будет тщательно закрывать любые потоки (нити), используя эти объекты (а также дождаться окончания потоков!) Перед удалением _EthDev объектов, вы должны переписать его так, чтобы он делал это надежно. Удаляя объект, пока другой поток все еще может использовать его, возникает проблема.

+0

Спасибо, Джереми! Фактически я создаю объекты и запускаю потоки при запуске приложения и останавливаю потоки и удаляю объекты перед выходом. Но теперь я думаю, что проблема в многопоточности, а не в сокетах. – swampmanster

Смежные вопросы