Most sockets programmers are familiar with the
idiom of checking for a -1 return code from sockets
calls, and the ACE class methods which wrap them, to
detect errors resulting from socket operations such as
send() and recv(). However, there is one situation where
a failed send() call will raise a SIGPIPE signal rather
than return -1. If the connection has been broken (for
example, by the peer abruptly closing, or resetting, the
connection) a send() call will raise a SIGPIPE (broken
pipe) signal. This sounds rather inconvenient, but the
biggest problem is that, by default, a SIGPIPE signal
will cause your process to abort - probably not what you
wanted in that situation.
There is a more
graceful way to alter the way that send() responds to a
broken socket. If you change the handling of SIGPIPE so
that the signal is ignored, the signal will not be
raised, and send() will return -1 when a broken socket
is detected, allowing you to handle the failure more
gracefully.
If you are using ACE (and why
wouldn't you?) it's very easy to implement this behavior
using the ACE_Sig_Action class. Simply add these three
lines of code to a method or application where you'll be
doing socket writes:
ACE_Sig_Action
no_sigpipe ((ACE_SignalHandler)
SIG_IGN);ACE_Sig_Action
original_action;no_sigpipe.register_action
(SIGPIPE, &original_action);These
three lines change the SIGPIPE to be ignored, as you
want, while preserving the original handling action for
SIGPIPE soit can be restored later. Of course, if you
are changing SIGPIPE handling for your entire
application, and not just a method, you need not save
and restore the signal action. To restore the action,
add one more line after the send() calls are
complete:
no_sigpipe.restore_action
(SIGPIPE, original_action);This technique
is illustrated and explained more on pages 173-174 in
C++NPv2.