CDT
CDT

Reputation: 10661

QTcpSocket - An invalid handle was specified when exting QRunnable

This error occurred in this snippet:

void TCPConnectThread::run()
{
    m_socket = new QTcpSocket();
    m_socket->setSocketDescriptor(m_fd);

    m_socket->waitForReadyRead(10000);

    QString data = m_socket->readAll();

    m_socket->waitForDisconnected();
}

A little deep in:

if (::WSAIoctl(socketDescriptor, FIONREAD, &dummy, sizeof(dummy), &nbytes,  
sizeof(nbytes), &sizeWritten, 0,0) == SOCKET_ERROR) <-Exception here
{
    WS_ERROR_DEBUG(WSAGetLastError());
    return -1;
}

Deeper in:

if (::getsockopt(d->socketDescriptor, SOL_SOCKET, 
SO_ERROR, (char *) &value, &valueSize) == 0) <-Here

invalid handle exception occurred when exiting the run method.

Here's how I get m_socket:

m_socket = new QTcpSocket();
m_socket->setSocketDescriptor(m_fd);//m_fd is the socket descriptor of another socket
                                    //from another thread

Here's the the thread from which m_fd is collected:

void TCPListenerThread::onNewConnection()
{
    QTcpSocket *clientSocket = m_tcpServer->nextPendingConnection();
    int sockfd = clientSocket->socketDescriptor();
    m_connectThread = new TCPConnectThread(sockfd);
    m_threadPool->start(m_connectThread);
}

Exception:

Most possible exception at 0x76edf9ea in manager_host.exe:   
0xC0000008: An invalid handle was specified  

How and where may I find this invalid handle ?

Upvotes: 3

Views: 814

Answers (1)

alexisdm
alexisdm

Reputation: 29896

You can't use the socket descriptor of a QTcpSocket object if it is already used by another QTcpSocket object. There is also no method of de-assigning it once is assigned to a QTcpSocket

Even if you don't explicitly use the initial QTcpSocket, if there is an event loop in the thread it was created (which is probably the case here), Qt will monitor it in that thread.

As an alternative, you could:

  • derive the QTcpServer class to redefine its incomingConnection(int socketDescriptor) method to get that descriptor before it is assigned to a QTcpSocket instead of using nextPendingConnection OR
  • pass directly the QTcpSocket you receive from nextPendingConnection instead of the socket descriptor as a parameter to the thread constructor, and move it to the other thread (see that note):

    TCPConnectThread(QTcpSocket *socket)
        : m_socket(socket) 
    {
        m_socket−>setParent(0); // necessary to move the object to another thread
        m_socket->moveToThread(this);
        ...
    }
    

    As the moving has to be done from the initial thread, the first alternative might be easier to do with a QRunnable, because you might not have access easily to the future QThread the runnable will be using.

Upvotes: 1

Related Questions