From 889e03fa8378ef8aff402f9d7ddf1152c7be557e Mon Sep 17 00:00:00 2001 From: Jeff Hill Date: Tue, 13 Jun 2000 22:33:27 +0000 Subject: [PATCH] check for shutdown condition when socket sys call returns EINTR --- src/ca/iocinf.h | 3 +- src/ca/tcpiiu.cpp | 75 ++++++++++++++++++++++++----------------------- src/ca/udpiiu.cpp | 58 ++++++++++++++++++++---------------- 3 files changed, 73 insertions(+), 63 deletions(-) diff --git a/src/ca/iocinf.h b/src/ca/iocinf.h index 017afbc32..88c83306b 100644 --- a/src/ca/iocinf.h +++ b/src/ca/iocinf.h @@ -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 (); diff --git a/src/ca/tcpiiu.cpp b/src/ca/tcpiiu.cpp index 2e73046e1..9b80c0943 100644 --- a/src/ca/tcpiiu.cpp +++ b/src/ca/tcpiiu.cpp @@ -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 ( 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; diff --git a/src/ca/udpiiu.cpp b/src/ca/udpiiu.cpp index b7362824f..487a580c3 100644 --- a/src/ca/udpiiu.cpp +++ b/src/ca/udpiiu.cpp @@ -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); }