check for shutdown condition when socket sys call returns EINTR
This commit is contained in:
@@ -442,7 +442,7 @@ public:
|
||||
unsigned short repeaterPort;
|
||||
bool contactRepeater;
|
||||
bool repeaterContacted;
|
||||
bool sendThreadExitCmd;
|
||||
bool shutdownCmd;
|
||||
|
||||
// exceptions
|
||||
class noSocket {};
|
||||
@@ -503,6 +503,7 @@ public:
|
||||
int post_msg (char *pInBuf, unsigned long blockSize);
|
||||
void addToChanList (nciu *chan);
|
||||
void removeFromChanList (nciu *chan);
|
||||
void connect ();
|
||||
void disconnect (nciu *chan);
|
||||
bool fullyConstructed () const;
|
||||
void recvMsg ();
|
||||
|
||||
@@ -84,9 +84,9 @@ tcpiiu * constructTCPIIU (cac *pcac, const struct sockaddr_in *pina,
|
||||
|
||||
|
||||
/*
|
||||
* cac_connect_tcp ()
|
||||
* tcpiiu::connect ()
|
||||
*/
|
||||
LOCAL void cac_connect_tcp (tcpiiu *piiu)
|
||||
void tcpiiu::connect ()
|
||||
{
|
||||
int status;
|
||||
|
||||
@@ -96,14 +96,14 @@ LOCAL void cac_connect_tcp (tcpiiu *piiu)
|
||||
while (1) {
|
||||
int errnoCpy;
|
||||
|
||||
status = connect ( piiu->sock, &piiu->dest.sa,
|
||||
sizeof (piiu->dest.sa) );
|
||||
if (status == 0) {
|
||||
status = ::connect ( this->sock, &this->dest.sa,
|
||||
sizeof ( this->dest.sa ) );
|
||||
if ( status == 0 ) {
|
||||
break;
|
||||
}
|
||||
|
||||
errnoCpy = SOCKERRNO;
|
||||
if (errnoCpy==SOCK_EISCONN) {
|
||||
if ( errnoCpy == SOCK_EISCONN ) {
|
||||
/*
|
||||
* called connect after we are already connected
|
||||
* (this appears to be how they provide
|
||||
@@ -111,16 +111,7 @@ LOCAL void cac_connect_tcp (tcpiiu *piiu)
|
||||
*/
|
||||
break;
|
||||
}
|
||||
else if ( errnoCpy==SOCK_EINPROGRESS ||
|
||||
errnoCpy==SOCK_EWOULDBLOCK /* for WINSOCK */ ) {
|
||||
/*
|
||||
* The socket is non-blocking and a
|
||||
* connection attempt has been initiated,
|
||||
* but not completed.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
else if (errnoCpy==SOCK_EALREADY) {
|
||||
else if ( errnoCpy == SOCK_EALREADY ) {
|
||||
return;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
@@ -133,15 +124,20 @@ LOCAL void cac_connect_tcp (tcpiiu *piiu)
|
||||
}
|
||||
#endif
|
||||
else if ( errnoCpy == SOCK_EINTR ) {
|
||||
/*
|
||||
* restart the system call if interrupted
|
||||
*/
|
||||
continue;
|
||||
if ( this->state == iiu_disconnected ) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if ( errnoCpy == SOCK_SHUTDOWN ) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
ca_printf ("Unable to connect because %d=\"%s\"\n",
|
||||
ca_printf ( "Unable to connect because %d=\"%s\"\n",
|
||||
errnoCpy, SOCKERRSTR (errnoCpy) );
|
||||
piiu->shutdown ();
|
||||
this->shutdown ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -149,9 +145,9 @@ LOCAL void cac_connect_tcp (tcpiiu *piiu)
|
||||
/*
|
||||
* put the iiu into the connected state
|
||||
*/
|
||||
piiu->state = iiu_connected;
|
||||
this->state = iiu_connected;
|
||||
|
||||
piiu->rescheduleRecvTimer (); // reset connection activity watchdog
|
||||
this->rescheduleRecvTimer (); // reset connection activity watchdog
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -202,7 +198,7 @@ extern "C" void cacSendThreadTCP (void *pParam)
|
||||
int status;
|
||||
|
||||
pOutBuf = static_cast <char *> ( cacRingBufferReadReserveNoBlock (&piiu->send, &sendCnt) );
|
||||
while (!pOutBuf) {
|
||||
while ( ! pOutBuf ) {
|
||||
piiu->tcpSendWatchdog::cancel ();
|
||||
pOutBuf = (char *) cacRingBufferReadReserve (&piiu->send, &sendCnt);
|
||||
if ( piiu->state != iiu_connected ) {
|
||||
@@ -229,25 +225,30 @@ extern "C" void cacSendThreadTCP (void *pParam)
|
||||
cacRingBufferReadCommit (&piiu->send, 0);
|
||||
|
||||
if ( status == 0 ) {
|
||||
semBinaryGive (piiu->sendThreadExitSignal);
|
||||
piiu->shutdown ();
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( localError == SOCK_SHUTDOWN ) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ( localError != SOCK_EWOULDBLOCK && localError != SOCK_EINTR ) {
|
||||
if ( localError != SOCK_EPIPE && localError != SOCK_ECONNRESET &&
|
||||
localError != SOCK_ETIMEDOUT) {
|
||||
ca_printf ("CAC: unexpected TCP send error: %s\n", SOCKERRSTR (localError) );
|
||||
if ( localError == SOCK_EINTR ) {
|
||||
if ( piiu->state == iiu_disconnected ) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
|
||||
semBinaryGive ( piiu->sendThreadExitSignal );
|
||||
piiu->shutdown ();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( localError != SOCK_EPIPE && localError != SOCK_ECONNRESET &&
|
||||
localError != SOCK_ETIMEDOUT) {
|
||||
ca_printf ("CAC: unexpected TCP send error: %s\n", SOCKERRSTR (localError) );
|
||||
}
|
||||
|
||||
piiu->shutdown ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,7 +287,7 @@ void tcpiiu::recvMsg ()
|
||||
return;
|
||||
}
|
||||
|
||||
if ( localErrno == SOCK_EWOULDBLOCK || localErrno == SOCK_EINTR ) {
|
||||
if ( localErrno == SOCK_EINTR ) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -314,7 +315,7 @@ extern "C" void cacRecvThreadTCP (void *pParam)
|
||||
{
|
||||
tcpiiu *piiu = (tcpiiu *) pParam;
|
||||
|
||||
cac_connect_tcp (piiu);
|
||||
piiu->connect ();
|
||||
if ( piiu->state == iiu_connected ) {
|
||||
unsigned priorityOfSelf = threadGetPrioritySelf ();
|
||||
unsigned priorityOfSend;
|
||||
|
||||
@@ -27,23 +27,28 @@ LOCAL int cac_udp_recv_msg (udpiiu *piiu)
|
||||
int src_size = sizeof (src);
|
||||
int status;
|
||||
|
||||
status = recvfrom (piiu->sock, piiu->recvBuf, sizeof (piiu->recvBuf), 0,
|
||||
&src.sa, &src_size);
|
||||
status = recvfrom ( piiu->sock, piiu->recvBuf, sizeof (piiu->recvBuf), 0,
|
||||
&src.sa, &src_size );
|
||||
if (status < 0) {
|
||||
int errnoCpy = SOCKERRNO;
|
||||
|
||||
if (errnoCpy == SOCK_SHUTDOWN) {
|
||||
if ( errnoCpy == SOCK_SHUTDOWN ) {
|
||||
return -1;
|
||||
}
|
||||
if (errnoCpy == SOCK_EWOULDBLOCK || errnoCpy == SOCK_EINTR) {
|
||||
return 0;
|
||||
if ( errnoCpy == SOCK_EINTR ) {
|
||||
if ( piiu->shutdownCmd ) {
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
# ifdef linux
|
||||
/*
|
||||
* Avoid spurious ECONNREFUSED bug
|
||||
* in linux
|
||||
*/
|
||||
if (errnoCpy==SOCK_ECONNREFUSED) {
|
||||
if ( errnoCpy == SOCK_ECONNREFUSED ) {
|
||||
return 0;
|
||||
}
|
||||
# endif
|
||||
@@ -181,18 +186,16 @@ void notify_ca_repeater (udpiiu *piiu)
|
||||
len = 0;
|
||||
# endif
|
||||
|
||||
status = sendto (piiu->sock, (char *)&msg, len,
|
||||
0, (struct sockaddr *)&saddr, sizeof(saddr));
|
||||
if (status < 0) {
|
||||
status = sendto ( piiu->sock, (char *) &msg, len,
|
||||
0, (struct sockaddr *)&saddr, sizeof (saddr) );
|
||||
if ( status < 0 ) {
|
||||
int errnoCpy = SOCKERRNO;
|
||||
if( errnoCpy != SOCK_EINTR &&
|
||||
errnoCpy != SOCK_EWOULDBLOCK &&
|
||||
if ( errnoCpy != SOCK_EINTR &&
|
||||
/*
|
||||
* This is returned from Linux when
|
||||
* the repeater isnt running
|
||||
*/
|
||||
errnoCpy != SOCK_ECONNREFUSED
|
||||
) {
|
||||
errnoCpy != SOCK_ECONNREFUSED ) {
|
||||
ca_printf (
|
||||
"CAC: error sending to repeater was \"%s\"\n",
|
||||
SOCKERRSTR(errnoCpy));
|
||||
@@ -209,7 +212,7 @@ extern "C" void cacSendThreadUDP (void *pParam)
|
||||
{
|
||||
udpiiu *piiu = (udpiiu *) pParam;
|
||||
|
||||
while ( ! piiu->sendThreadExitCmd ) {
|
||||
while ( ! piiu->shutdownCmd ) {
|
||||
int status;
|
||||
|
||||
if (piiu->contactRepeater) {
|
||||
@@ -222,13 +225,13 @@ extern "C" void cacSendThreadUDP (void *pParam)
|
||||
osiSockAddrNode *pNode;
|
||||
|
||||
pNode = (osiSockAddrNode *) ellFirst (&piiu->dest);
|
||||
while (pNode) {
|
||||
while ( pNode ) {
|
||||
|
||||
assert ( piiu->nBytesInXmitBuf <= INT_MAX );
|
||||
status = sendto (piiu->sock, piiu->xmitBuf,
|
||||
status = sendto ( piiu->sock, piiu->xmitBuf,
|
||||
(int) piiu->nBytesInXmitBuf, 0,
|
||||
&pNode->addr.sa, sizeof(pNode->addr.sa));
|
||||
if (status <= 0) {
|
||||
&pNode->addr.sa, sizeof (pNode->addr.sa) );
|
||||
if ( status <= 0 ) {
|
||||
int localErrno = SOCKERRNO;
|
||||
|
||||
if (status==0) {
|
||||
@@ -239,7 +242,12 @@ extern "C" void cacSendThreadUDP (void *pParam)
|
||||
break;
|
||||
}
|
||||
else if ( localErrno == SOCK_EINTR ) {
|
||||
status = 1;
|
||||
if ( piiu->shutdownCmd ) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
char buf[64];
|
||||
@@ -258,17 +266,17 @@ extern "C" void cacSendThreadUDP (void *pParam)
|
||||
|
||||
piiu->nBytesInXmitBuf = 0u;
|
||||
|
||||
if (status<=0) {
|
||||
if ( status <= 0 ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
semMutexGive (piiu->xmitBufLock);
|
||||
semMutexGive ( piiu->xmitBufLock );
|
||||
|
||||
semBinaryMustTake (piiu->xmitSignal);
|
||||
semBinaryMustTake ( piiu->xmitSignal );
|
||||
}
|
||||
|
||||
semBinaryGive (piiu->sendThreadExitSignal);
|
||||
semBinaryGive ( piiu->sendThreadExitSignal) ;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -342,7 +350,7 @@ udpiiu::udpiiu (cac *pcac) :
|
||||
netiiu (pcac),
|
||||
searchTmr (*this, pcac->timerQueue),
|
||||
repeaterSubscribeTmr (*this, pcac->timerQueue),
|
||||
sendThreadExitCmd (false)
|
||||
shutdownCmd (false)
|
||||
{
|
||||
static const unsigned short PORT_ANY = 0u;
|
||||
osiSockAddr addr;
|
||||
@@ -580,7 +588,7 @@ udpiiu::~udpiiu ()
|
||||
void udpiiu::shutdown ()
|
||||
{
|
||||
::shutdown (this->sock, SD_BOTH);
|
||||
this->sendThreadExitCmd = true;
|
||||
this->shutdownCmd = true;
|
||||
semBinaryGive (this->xmitSignal);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user