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-settingsTools > Options > Debugger > GDB
handle SIGPIPE nostop noprint pass