From 4e1fd091ea2ebf5b25e87c7f2050f24b754598db Mon Sep 17 00:00:00 2001 From: Jeff Hill Date: Thu, 5 Feb 2004 21:12:09 +0000 Subject: [PATCH] fixed enobuf causes stuck send thread --- src/rsrv/camsgtask.c | 11 +++- src/rsrv/caserverio.c | 134 ++++++++++++++++++++++++++++-------------- 2 files changed, 99 insertions(+), 46 deletions(-) diff --git a/src/rsrv/camsgtask.c b/src/rsrv/camsgtask.c index 0c571546c..f537915ec 100644 --- a/src/rsrv/camsgtask.c +++ b/src/rsrv/camsgtask.c @@ -245,7 +245,7 @@ FAST int sock; UNLOCK_CLIENTQ; client->recv.cnt = 0ul; - while (TRUE) { + while ( ! client->disconnect ) { client->recv.stk = 0; nchars = recv( @@ -269,6 +269,15 @@ FAST int sock; long anerrno; anerrno = errnoGet(); + + if ( anerrno == SOCK_ENOBUFS ) { + logMsg ( + "rsrv: system low on network buffers " + "- receive retry in 15 seconds\n", + 0,0,0,0,0,0 ); + taskDelay ( 15 * sysClkRateGet() ); + continue; + } /* * normal conn lost conditions diff --git a/src/rsrv/caserverio.c b/src/rsrv/caserverio.c index 275ce07e3..3a5eef279 100644 --- a/src/rsrv/caserverio.c +++ b/src/rsrv/caserverio.c @@ -61,6 +61,7 @@ int lock_needed; } if(pclient->disconnect){ + pclient->send.stk = 0; if(CASDEBUG>2){ logMsg( "CAS: msg Discard for sock %d addr %x\n", pclient->sock, @@ -77,46 +78,49 @@ int lock_needed; SEND_LOCK(pclient); } - if(pclient->send.stk){ #ifdef CONVERSION_REQUIRED - /* Convert all caHdr into net format. - * The remaining bytes must already be in - * net format, because here we have no clue - * how to convert them. - */ - char *buf; - unsigned long msg_size, num_bytes; - caHdr *mp; + { + /* Convert all caHdr into net format. + * The remaining bytes must already be in + * net format, because here we have no clue + * how to convert them. + */ + char * buf; + unsigned long msg_size, num_bytes; + caHdr * mp; - - buf = (char *) pclient->send.buf; - num_bytes = pclient->send.stk; + + buf = (char *) pclient->send.buf; + num_bytes = pclient->send.stk; - /* convert only if we have at least a complete caHdr */ - while (num_bytes >= sizeof(caHdr)) - { - mp = (caHdr *) buf; + /* convert only if we have at least a complete caHdr */ + while (num_bytes >= sizeof(caHdr)) + { + mp = (caHdr *) buf; - msg_size = sizeof (caHdr) + mp->m_postsize; + msg_size = sizeof (caHdr) + mp->m_postsize; - DLOG(3,"CAS: sending cmmd %d, postsize %d\n", - mp->m_cmmd, (int)mp->m_postsize, - 0, 0, 0, 0); + DLOG(3,"CAS: sending cmmd %d, postsize %d\n", + mp->m_cmmd, (int)mp->m_postsize, + 0, 0, 0, 0); - /* convert the complete header into host format */ - mp->m_cmmd = htons (mp->m_cmmd); - mp->m_postsize = htons (mp->m_postsize); - mp->m_dataType = htons (mp->m_dataType); - mp->m_count = htons (mp->m_count); - mp->m_cid = htonl (mp->m_cid); - mp->m_available = htonl (mp->m_available); + /* convert the complete header into host format */ + mp->m_cmmd = htons (mp->m_cmmd); + mp->m_postsize = htons (mp->m_postsize); + mp->m_dataType = htons (mp->m_dataType); + mp->m_count = htons (mp->m_count); + mp->m_cid = htonl (mp->m_cid); + mp->m_available = htonl (mp->m_available); - /* get next message: */ - buf += msg_size; - num_bytes -= msg_size; - } + /* get next message: */ + buf += msg_size; + num_bytes -= msg_size; + } + } #endif + while(pclient->send.stk&&!pclient->disconnect){ + status = sendto( pclient->sock, pclient->send.buf, @@ -124,16 +128,34 @@ int lock_needed; NULL, (struct sockaddr *)&pclient->addr, sizeof(pclient->addr)); - if( pclient->send.stk != (unsigned)status){ + if( pclient->send.stk == (unsigned)status){ + pclient->send.stk = 0; + pclient->ticks_at_last_send = tickGet(); + } + else { if(status < 0){ int anerrno; char buf[64]; anerrno = errnoGet(); + if ( pclient->disconnect ) { + pclient->send.stk = 0; + break; + } + ipAddrToA (&pclient->addr, buf, sizeof(buf)); if(pclient->proto == IPPROTO_TCP) { + if ( anerrno == ENOBUFS ) { + logMsg ( + "rsrv: system low on network buffers - " + "tcp send retry in 15 sec\n", + 0,0,0,0,0,0); + taskDelay ( 15 * sysClkRateGet() ); + continue; + } + if( (anerrno!=ECONNABORTED&& anerrno!=ECONNRESET&& anerrno!=EPIPE&& @@ -149,7 +171,19 @@ int lock_needed; NULL, NULL); } + pclient->send.stk = 0; pclient->disconnect = TRUE; + { + static const int shutdownReadAndWrite = 2; + int status = shutdown ( pclient->sock, shutdownReadAndWrite ); + if ( status ) { + logMsg ( + "rsrv: socket shutdown error was %s\n", + (int) strerror ( anerrno ), NULL, NULL, + NULL, NULL, NULL ); + } + } + break; } else if (pclient->proto == IPPROTO_UDP) { if (anerrno==ENOBUFS) { @@ -165,29 +199,39 @@ int lock_needed; NULL, NULL); } + break; } else { assert (0); } } else{ - logMsg( - "CAS: blk sock partial send: req %d sent %d \n", - pclient->send.stk, - status, - NULL, - NULL, - NULL, - NULL); + pclient->ticks_at_last_send = tickGet(); + if(pclient->proto == IPPROTO_TCP) { + unsigned transferSize = (unsigned) status; + if ( pclient->send.stk > transferSize ) { + unsigned bytesLeft = pclient->send.stk - transferSize; + memmove ( pclient->send.buf, &pclient->send.buf[transferSize], + bytesLeft ); + pclient->send.stk = bytesLeft; + } + else { + pclient->send.stk = 0; + } + } + else if (pclient->proto == IPPROTO_UDP) { + pclient->send.stk = 0; + logMsg ( "partial UDP message sent?\n", + 0,0,0,0,0,0); + break; + } + else { + assert ( 0 ); + } } } - - pclient->send.stk = 0; - - pclient->ticks_at_last_send = tickGet(); } - if(lock_needed){ SEND_UNLOCK(pclient); }