Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

SIGPIPE error when flushing a recently closed QTcpSocket



  • I'm trying to write fault-tolerant socket code that will gracefully handle a TCP connection that was closed during a conversation.

    @ for (short i=0;i<10;i++)
    if (swSocket->state() == QAbstractSocket::ConnectedState) {
    qDebug() << "Sending a message...";
    swSocket->write("Hello from Socket Writer.\r\n");
    if (swSocket->state() == QAbstractSocket::ConnectedState) {
    swSocket->flush(); // <----- Line in question
    swSocket->waitForBytesWritten(50);
    } else {
    qDebug() << "Not connected.";
    }
    sleep(1);
    } else {
    qDebug() << "Not connected.";
    }
    @

    In the above code, if I have the flush call and the receiving computer closes the connection, I get a SIGPIPE signal which crashes the program. I have tried adding signal(SIGPIPE, SIG_IGN); in my main() but that doesn't fix it. Removing the flush line fixed the problem but what I'm trying to avoid is the TCP stack queuing up my outgoing messages.

    Would I be able to accomplish this by using TCP_NODELAY? And is there a way to get flush to gracefully return?



  • afaik,

    there are 2 buffers

    application level buffer, currently maintained by your TCP socket object

    network socket buffer, maintained and handled by the OS

    the QAbstractSocket::flush() method just forces the transfer of data from 1] to 2]. There is no way to have an unbuffered QTcpSocket (QIODevice::Unbuffered option).
    However, you can accomplish TCP_NODELAY by using the QAbstractSocket::LowDelayOption option.

    Also, the way the program is structured, there is no guarantee that e.g. the state of the socket will be the same from the time line 5 was executed to when line 6 gets to be executed. Usually such programs rely heavily on the available signals of the Socket classes.

    would you mind connecting the error() and/or disconnected() signals to a simple debugging routine that will print the relevant info?

    lastly, i'm not sure why your signal handler didn't work, but if event if it did, it would mean that you should get an error on your next socket I/O operation.



  • @compor , the code in question is absolutely legal and fault-tolerant. It doesn't contain any race conditions, i.e. it's normal situation when underlying(!) system socket changes its state between line 5 and 6. There are no way to catch it even if you handle error()/disconnected() signals. Also the problem isn't TCP-specific. I personally encountered same issue with QLocalSocket. Qt implementation should handle it properly but it doesn't. Seems like it's a Qt bug (or platform-specific feature?).



  • @artem_pisarenko
    Would have been nice if you had posted the solution here :)
    https://stackoverflow.com/a/55757737
    The Debugger.
    https://ahlamnote.blogspot.com/2006/12/gdb-ignore-sigpipe.html
    https://doc.qt.io/qtcreator/creator-debugger-engines.html#specifying-debugger-settings

    Tools > Options > Debugger > GDB
    handle SIGPIPE nostop noprint pass


Log in to reply