2017-02-18 71 views
0

我有多线程应用程序,它定期轮询几百个设备。 每个线程服务于一个设备,其套接字和其他描述符封装在单个对象上,因此没有共享描述符。 closesocket(fSock)偶尔应用程序崩溃,当我尝试设置描述符fSock为0.服务器在closesocket后崩溃

我假设,如果closesocket(fSock)返回SOCKET_ERROR,我不应该设置fSock = 0。 还是有其他原因吗?

我的代码:

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

零不是一个套接字无效的值。如果你想表明fSock不再是一个有效的套接字,你应该将它设置为INVALID_SOCKET而不是0,因为INVALID_SOCKET根据定义是一个永远不会被有效套接字使用的值。 –

回答

0

我多线程应用程序,... [它]偶尔崩溃

多线程应用程序,偶尔崩溃是一个种族的条件的典型症状。我认为,为了防止出现崩溃,需要弄清楚代码中的竞争条件,并解决该问题。

我假定,我不应该设置fSock = 0,如果关闭套接字(fSock)返回 SOCKET_ERROR。还是有其他原因吗?

我怀疑问题实际上是与closesocket()或将fSock设置为0.请记住,套接字实际上只是整数,并将整数设置为0不会导致其崩溃拥有。什么可能导致崩溃是写入无效内存 - 并且fSock = 0确实写入成员变量fSock位于(或位于)的内存位置。

因此,更可能的假设是_EthDev对象被线程B删除,而线程A仍然在调用Connect()的中间。在connect()调用执行时,这很可能会发生,因为阻塞connect()调用可能需要相当长的时间才能返回。因此,如果在connect()调用期间有另一个线程粗暴地删除了_EthDev对象,则只要connect()返回,下一行代码就会写入到(现在删除的)_EthDev对象所使用的位置将是“fSock = 0;”行,这可能会导致崩溃。

我建议您检查一下删除_EthDev对象的代码,如果它不小心先使用这些对象关闭任何线程(并且还要等待线程退出!),然后再删除_EthDev对象,你应该重写它,以便它可靠地做到这一点。在另一个线程可能仍在使用的时候删除一个对象会造成麻烦。

+0

谢谢杰里米!实际上,我创建对象并在应用程序启动时启动线程,并在退出之前停止线程并删除对象。 但现在我认为问题更多的是多线程而不是套接字。 – swampmanster