From: E. Scott Daniels Date: Tue, 25 Feb 2020 15:40:20 +0000 (-0500) Subject: Address multi-threading issues in SI95 X-Git-Tag: 3.2.5~2 X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=commitdiff_plain;h=5861625ff2eaf1bd3a69ce488bd7d14f7b402432;p=ric-plt%2Flib%2Frmr.git Address multi-threading issues in SI95 There are potential issues when a uer application is multi-threaded and disconnections are noticed. This change addresses these issues. Signed-off-by: E. Scott Daniels Change-Id: Ie586cfe6294429b299e0044b2f6bf315d78104ce --- diff --git a/src/rmr/si/src/si95/sibldpoll.c b/src/rmr/si/src/si95/sibldpoll.c index 6ad26ea..5b50fcc 100644 --- a/src/rmr/si/src/si95/sibldpoll.c +++ b/src/rmr/si/src/si95/sibldpoll.c @@ -52,7 +52,10 @@ extern void SIbldpoll( struct ginfo_blk* gptr ) { for( tpptr = gptr->tplist; tpptr != NULL; tpptr = nextb ) { nextb = tpptr->next; if( tpptr->flags & TPF_DELETE ) { - SIterm( gptr, tpptr ); + if( tpptr->fd >= 0 ) { // wasn't closed for some reason + SIterm( gptr, tpptr ); + } + SIrm_tpb( gptr, tpptr ); // safe to remove the block from the list in this thread } else { if( tpptr->fd >= 0 ) { // if valid file descriptor if( tpptr->fd >= gptr->fdcount ) { diff --git a/src/rmr/si/src/si95/siclose.c b/src/rmr/si/src/si95/siclose.c index cb5cf36..eed11ef 100644 --- a/src/rmr/si/src/si95/siclose.c +++ b/src/rmr/si/src/si95/siclose.c @@ -18,7 +18,7 @@ ================================================================================== */ -/* X +/* ****************************************************************************** * * Mnemonic: SIclose @@ -35,62 +35,51 @@ * Date: 3 February 1995 * Author: E. Scott Daniels * -* Modified: 19 Feb 1995 - To set TP blk to drain if output pending. -* 10 May 1995 - To change SOCK_RAW to SOCK_DGRAM -* 22 Feb 2002 - To accept TCP_LISTEN_PORT or UDP_PORT as fd +* Modified:i 19 Feb 1995 - To set TP blk to drain if output pending. +* 10 May 1995 - To change SOCK_RAW to SOCK_DGRAM +* 22 Feb 2002 - To accept TCP_LISTEN_PORT or UDP_PORT as fd ****************************************************************************** */ #include "sisetup.h" -extern int SIclose( struct ginfo_blk *gptr, int fd ) -{ - - struct tp_blk *tpptr; // pointer into tp list - int status = SI_ERROR; // status of processing - - gptr->sierr = SI_ERR_HANDLE; - if( gptr->magicnum == MAGICNUM ) // good cookie at the gptr address? - { - gptr->sierr = SI_ERR_SESSID; - - if( fd >= 0 ) // if caller knew the fd number - { - for( tpptr = gptr->tplist; tpptr != NULL && tpptr->fd != fd; - tpptr = tpptr->next ); // find the tppblock to close - } - else // user did not know the fd - find first Listener or UDP tp blk - { - if( fd == TCP_LISTEN_PORT ) // close first tcp listen port; else first udp - for( tpptr = gptr->tplist; tpptr != NULL && !(tpptr->flags&& TPF_LISTENFD); tpptr = tpptr->next ); - else - for( tpptr = gptr->tplist; tpptr != NULL && tpptr->type != SOCK_DGRAM; tpptr = tpptr->next ); - } +extern int SIclose( struct ginfo_blk *gptr, int fd ) { + struct tp_blk *tpptr; // pointer into tp list + int status = SI_ERROR; // status of processing - if( tpptr != NULL ) - { - gptr->sierr = SI_ERR_TP; + if( gptr != NULL ) { + if( fd >= 0 ) { // if caller knew the fd number + if( fd < MAX_FDS ) { // straight from map if possible + tpptr = gptr->tp_map[fd]; + } else { + // future: need to lock the list or switch to gmax hash + for( tpptr = gptr->tplist; tpptr != NULL && tpptr->fd != fd; tpptr = tpptr->next ); // find the tppblock to close + } + } else { // user did not know the fd - find first Listener or UDP tp blk + if( fd == TCP_LISTEN_PORT ) { // close first tcp listen port; else first udp + for( tpptr = gptr->tplist; tpptr != NULL && !(tpptr->flags&& TPF_LISTENFD); tpptr = tpptr->next ); + } else { + for( tpptr = gptr->tplist; tpptr != NULL && tpptr->type != SOCK_DGRAM; tpptr = tpptr->next ); + } + } - if( tpptr->squeue == NULL ) // if nothing is queued to send... - { - tpptr->flags |= TPF_UNBIND; // ensure port is unbound from tp - tpptr->flags |= TPF_DELETE; - { - int x = 1; - - setsockopt(tpptr->fd, SOL_SOCKET, SO_LINGER, (char *)&x, sizeof( x ) ) ; + if( tpptr != NULL ) { + if( tpptr->squeue == NULL ) { // if nothing is queued to send... + tpptr->flags |= TPF_UNBIND; // ensure port is unbound from tp + tpptr->flags |= TPF_DELETE; + { + int x = 1; + setsockopt(tpptr->fd, SOL_SOCKET, SO_LINGER, (char *)&x, sizeof( x ) ) ; + } + + SIterm( gptr, tpptr ); // close the fd and mark the block as deletable + } else { + tpptr->flags |= TPF_DRAIN; // stuff on queue, must drain before closing + } + + status = SI_OK; // give caller a good status + } // end if we found a tpptr } - close( tpptr->fd ); - tpptr->fd = -1; - tpptr->type = -1; - // siterm now called in build poll if tp is marked delete - // SIterm( gptr, gptr, tpptr );*/ /* cleanup and remove from the list - } - else // stuff queued to send - mark port to drain - tpptr->flags |= TPF_DRAIN; // and we will term the port when q empty - - status = SI_OK; // give caller a good status - } // end if we found a tpptr - } // end if the handle was good - return( status ); // send the status back to the caller + return status; // send the status back to the caller } // SIclose + diff --git a/src/rmr/si/src/si95/siconnect.c b/src/rmr/si/src/si95/siconnect.c index 842207f..114e873 100644 --- a/src/rmr/si/src/si95/siconnect.c +++ b/src/rmr/si/src/si95/siconnect.c @@ -62,24 +62,20 @@ extern int SIconnect( struct ginfo_blk *gptr, char *abuf ) { return SI_ERROR; } - gptr->sierr = SI_ERR_HANDLE; if( gptr->magicnum != MAGICNUM ) { // no cookie -- no connection return SI_ERROR; } } - gptr->sierr = SI_ERR_TPORT; tpptr = SIconn_prep( gptr, TCP_DEVICE, abuf, 0 ); // create tp struct, and socket. get peer address 0 == any family that suits the addr if( tpptr != NULL ) { taddr = tpptr->paddr; - gptr->sierr = SI_ERR_TP; errno = 0; if( connect( tpptr->fd, taddr, tpptr->palen ) != 0 ) { close( tpptr->fd ); // clean up fd and tp_block SItrash( TP_BLK, tpptr ); // free the trasnsport block fd = SI_ERROR; // send bad session id num back } else { // connect ok - gptr->sierr = 0; tpptr->flags |= TPF_SESSION; // indicate we have a session here tpptr->next = gptr->tplist; // add block to the list if( tpptr->next != NULL ) { diff --git a/src/rmr/si/src/si95/siestablish.c b/src/rmr/si/src/si95/siestablish.c index bdb3f72..846faa1 100644 --- a/src/rmr/si/src/si95/siestablish.c +++ b/src/rmr/si/src/si95/siestablish.c @@ -109,12 +109,12 @@ extern struct tp_blk *SIlisten_prep( struct ginfo_blk *gptr, int type, char* abu if( status == SI_OK ) { tptr->addr = addr; // save address } else { - //fprintf( stderr, ">>>>> siestablish: bind failed: fam=%d type=%d pro=%d %s\n", tptr->family, tptr->type, protocol, strerror( errno ) ); + fprintf( stderr, ">>>>> siestablish: bind failed: fam=%d type=%d pro=%d %s\n", tptr->family, tptr->type, protocol, strerror( errno ) ); close( tptr->fd ); } } else { status = ! SI_OK; // force bad return later - //fprintf( stderr, ">>>>> siestablish: socket not esablished: fam=%d type=%d pro=%d %s\n", tptr->family, tptr->type, protocol, strerror( errno ) ); + fprintf( stderr, ">>>>> siestablish: socket not esablished: fam=%d type=%d pro=%d %s\n", tptr->family, tptr->type, protocol, strerror( errno ) ); } if( status != SI_OK ) { // socket or bind call failed - clean up stuff diff --git a/src/rmr/si/src/si95/siinit.c b/src/rmr/si/src/si95/siinit.c index 9159f69..b297124 100644 --- a/src/rmr/si/src/si95/siinit.c +++ b/src/rmr/si/src/si95/siinit.c @@ -62,8 +62,6 @@ extern struct ginfo_blk* SIinitialise( int opts ) } memset( gptr->tp_map, 0, sizeof( struct tp_blk *) * MAX_FDS ); - gptr->sierr = SI_ERR_TPORT; - gptr->cbtab = (struct callback_blk *) malloc( (sizeof( struct callback_blk ) * MAX_CBS ) ); if( gptr->cbtab != NULL ) { @@ -76,8 +74,6 @@ extern struct ginfo_blk* SIinitialise( int opts ) free( gptr ); gptr = NULL; // dont allow them to continue } - - gptr->sierr = SI_OK; } // end if gen infor block allocated successfully diff --git a/src/rmr/si/src/si95/silisten.c b/src/rmr/si/src/si95/silisten.c index c7151d4..8cd484a 100644 --- a/src/rmr/si/src/si95/silisten.c +++ b/src/rmr/si/src/si95/silisten.c @@ -49,12 +49,10 @@ extern int SIlistener( struct ginfo_blk *gptr, int type, char *abuf ) { if( gptr == NULL ) { return status; } - gptr->sierr = SI_ERR_HANDLE; if( gptr->magicnum != MAGICNUM ) // good cookie at the gptr address? return status; } - gptr->sierr = SI_ERR_TP; tpptr = SIlisten_prep( gptr, type, abuf, 0 ); if( tpptr != NULL ) // established a fd bound to the port ok diff --git a/src/rmr/si/src/si95/sipoll.c b/src/rmr/si/src/si95/sipoll.c index df71eae..0ecca66 100644 --- a/src/rmr/si/src/si95/sipoll.c +++ b/src/rmr/si/src/si95/sipoll.c @@ -59,14 +59,10 @@ extern int SIpoll( struct ginfo_blk *gptr, int msdelay ) struct timeval delay; // delay to use on select call struct sockaddr *uaddr; // pointer to udp address - gptr->sierr = SI_ERR_SHUTD; - if( gptr->flags & GIF_SHUTDOWN ) // cannot do if we should shutdown return( SI_ERROR ); // so just get out - gptr->sierr = SI_ERR_HANDLE; - if( gptr->magicnum != MAGICNUM ) // if not a valid ginfo block return( SI_ERROR ); @@ -156,7 +152,7 @@ extern int SIpoll( struct ginfo_blk *gptr, int msdelay ) SIaddress( uaddr, (void **) &buf, AC_TODOT ); status = (*cbptr)( gptr->cbtab[SI_CB_RDATA].cbdata, gptr->rbuf, status, buf ); SIcbstat( gptr, status, SI_CB_RDATA ); // handle status - free( buf ); + free( buf ); } // end if call back was defined } // end if status was ok free( uaddr ); @@ -190,7 +186,6 @@ extern int SIpoll( struct ginfo_blk *gptr, int msdelay ) if( gptr->flags & GIF_SHUTDOWN ) // we need to stop for some reason { - gptr->sierr = SI_ERR_SHUTD; // indicate error exit status status = SI_ERROR; // status should indicate to user to die SIshutdown( gptr ); // clean things up } diff --git a/src/rmr/si/src/si95/siproto.h b/src/rmr/si/src/si95/siproto.h index bb94d2a..c59d626 100644 --- a/src/rmr/si/src/si95/siproto.h +++ b/src/rmr/si/src/si95/siproto.h @@ -48,6 +48,7 @@ extern void SImap_fd( struct ginfo_blk *gptr, int fd, struct tp_blk* tpptr ); extern int SInewsession( struct ginfo_blk *gptr, struct tp_blk *tpptr ); extern int SIpoll( struct ginfo_blk *gptr, int msdelay ); extern int SIrcv( struct ginfo_blk *gptr, int sid, char *buf, int buflen, char *abuf, int delay ); +extern void SIrm_tpb( struct ginfo_blk *gptr, struct tp_blk *tpptr ); extern void SIsend( struct ginfo_blk *gptr, struct tp_blk *tpptr ); extern int SIsendt( struct ginfo_blk *gptr, int fd, char *ubuf, int ulen ); extern void SIset_tflags( struct ginfo_blk* gp, int flags ); diff --git a/src/rmr/si/src/si95/sircv.c b/src/rmr/si/src/si95/sircv.c index 2202629..d69cb61 100644 --- a/src/rmr/si/src/si95/sircv.c +++ b/src/rmr/si/src/si95/sircv.c @@ -58,11 +58,9 @@ extern int SIrcv( struct ginfo_blk *gptr, int sid, char *buf, int buflen, char * char *acbuf; // pointer to converted address int addrlen; - gptr->sierr = SI_ERR_HANDLE; // set errno before we fail if( gptr->magicnum != MAGICNUM ) // if not a valid ginfo block return SI_ERROR; - gptr->sierr = SI_ERR_SESSID; // set errno before we fail for( tpptr = gptr->tplist; tpptr != NULL && tpptr->fd != sid; tpptr = tpptr->next ); // find transport block if( tpptr == NULL ) @@ -71,7 +69,6 @@ extern int SIrcv( struct ginfo_blk *gptr, int sid, char *buf, int buflen, char * uaddr = (struct sockaddr *) malloc( sizeof( struct sockaddr ) ); addrlen = sizeof( *uaddr ); - gptr->sierr = SI_ERR_SHUTD; // set errno before we fail if( ! (gptr->flags & GIF_SHUTDOWN) ) { // if not in shutdown and no signal flags FD_ZERO( &readfds ); // clear select info @@ -87,22 +84,18 @@ extern int SIrcv( struct ginfo_blk *gptr, int sid, char *buf, int buflen, char * tptr->tv_usec = delay; } - gptr->sierr = SI_ERR_TP; if( (select( tpptr->fd + 1, &readfds, NULL, &execpfds, tptr ) < 0 ) ) gptr->flags |= GIF_SHUTDOWN; // we must shut on error or signal else { // poll was successful - see if data ? - gptr->sierr = SI_ERR_TIMEOUT; if( FD_ISSET( tpptr->fd, &execpfds ) ) // session error? { SIterm( gptr, tpptr ); // clean up our end of things - gptr->sierr = SI_ERR_SESSID; // set errno before we fail } else { if( (FD_ISSET( tpptr->fd, &readfds )) ) { // process data if no signal - gptr->sierr = SI_ERR_TP; if( tpptr->type == SOCK_DGRAM ) // raw data received { status = RECVFROM( sid, buf, buflen, 0, uaddr, &addrlen ); diff --git a/src/rmr/si/src/si95/sisend.c b/src/rmr/si/src/si95/sisend.c index 5a8a94e..c0233ae 100644 --- a/src/rmr/si/src/si95/sisend.c +++ b/src/rmr/si/src/si95/sisend.c @@ -46,7 +46,6 @@ extern void SIsend( struct ginfo_blk *gptr, struct tp_blk *tpptr ) { struct t_unitdata *udata; // pointer at UDP unit data struct ioq_blk *qptr; // pointer at qio block for free int status; -//static int announced = 0; // TESTING if( tpptr->squeue == NULL ) // who knows why we were called return; // nothing queued - just leave @@ -64,14 +63,6 @@ extern void SIsend( struct ginfo_blk *gptr, struct tp_blk *tpptr ) { } */ - -/* -//TESTING -if( !announced && status < tpptr->squeue->dlen ) { -announced = 1; -fprintf( stderr, ">>>>>>> !!!!!! SIsend: short send: %d != %d\n", status, tpptr->squeue->dlen ); -} -*/ free( tpptr->squeue->data ); // trash buffer or the udp block qptr = tpptr->squeue; // hold pointer for free tpptr->squeue = tpptr->squeue->next; // next in queue becommes head @@ -82,6 +73,6 @@ fprintf( stderr, ">>>>>>> !!!!!! SIsend: short send: %d != %d\n", status, tpptr- if( (tpptr->flags & TPF_DRAIN) && tpptr->squeue == NULL ) // done w/ drain? { - SIterm( gptr, tpptr ); // trash the tp block + SIterm( gptr, tpptr ); // close the session and mark the block for delte } } // SIsend diff --git a/src/rmr/si/src/si95/sisendt.c b/src/rmr/si/src/si95/sisendt.c index 81a3be6..8a4d5f0 100644 --- a/src/rmr/si/src/si95/sisendt.c +++ b/src/rmr/si/src/si95/sisendt.c @@ -56,19 +56,25 @@ extern int SIsendt( struct ginfo_blk *gptr, int fd, char *ubuf, int ulen ) { int sidx = 0; // send index errno = EINVAL; - gptr->sierr = SI_ERR_SESSID; if( fd < 0 ) { + errno = EBADFD; return SI_ERROR; // bad form trying to use this fd } if( fd < MAX_FDS ) { // straight from map if possible tpptr = gptr->tp_map[fd]; } else { + // list should be locked before traversing for( tpptr = gptr->tplist; tpptr != NULL && tpptr->fd != fd; tpptr = tpptr->next ); // find the block if out of map's range } if( tpptr != NULL ) { + if( (fd = tpptr->fd) < 0 ) { // fd user given might not be real, and this might be closed already + errno = EBADFD; + return SI_ERROR; + } + tpptr->sent++; // investigate: this may over count FD_ZERO( &writefds ); // clear for select call @@ -80,10 +86,9 @@ extern int SIsendt( struct ginfo_blk *gptr, int fd, char *ubuf, int ulen ) { time.tv_usec = 1; // small pause on check to help drain things if( select( fd + 1, NULL, &writefds, &execpfds, &time ) > 0 ) { // would block if <= 0 - gptr->sierr = SI_ERR_TP; if( FD_ISSET( fd, &execpfds ) ) { // error? errno = EBADFD; - SIterm( gptr, tpptr ); // clean up our portion of the session + SIterm( gptr, tpptr ); // mark block for deletion when safe return SI_ERROR; // and bail from this sinking ship } else { errno = 0; @@ -112,91 +117,3 @@ extern int SIsendt( struct ginfo_blk *gptr, int fd, char *ubuf, int ulen ) { return status; } -/* - This routine will send a datagram to the TCP session partner - that is connected via the FD number that is passed in. - If the send would cause the process to block, the send is - queued on the tp_blk for the session and is sent later as - a function of the SIwait process. If the buffer must be - queued, a copy of the buffer is created such that the - user program may free, or reuse, the buffer upon return. - - Parms:i gptr - The pointer to the global info structure (context) - fd - File descriptor (session number) - ubuf - User buffer to send. - ulen - Lenght of the user buffer. - - Returns: SI_OK if sent, SI_QUEUED if queued for later, SI_ERROR if error. -*/ -#ifdef KEEP -extern int new_SIsendt( struct ginfo_blk *gptr, int fd, char *ubuf, int ulen ) { - int status = SI_OK; // status of processing - fd_set writefds; // local write fdset to check blockage - fd_set execpfds; // exception fdset to check errors - struct tp_blk *tpptr; // pointer at the tp_blk for the session - struct ioq_blk *qptr; // pointer at i/o queue block - struct timeval time; // delay time parameter for select call - - gptr->sierr = SI_ERR_HANDLE; - - //if( gptr->magicnum == MAGICNUM ) { // ensure cookie is good -- we need to be too performant for this - //{ // mmmm oatmeal, my favorite - gptr->sierr = SI_ERR_SESSID; - - if( fd < MAX_FDS ) { // straight from map if possible - tpptr = gptr->tp_map[fd]; - } else { - for( tpptr = gptr->tplist; tpptr != NULL && tpptr->fd != fd; tpptr = tpptr->next ); // find the block if out of map's range - } - - if( tpptr != NULL ) { - tpptr->sent++; - - FD_ZERO( &writefds ); // clear for select call - FD_SET( fd, &writefds ); // set to see if this one was writable - FD_ZERO( &execpfds ); // clear and set execptions fdset - FD_SET( fd, &execpfds ); - - time.tv_sec = 0; // set both to 0 if we just want a poll, else we block at max this amount - time.tv_usec = 1; // small pause on check to help drain things - - if( select( fd + 1, NULL, &writefds, &execpfds, &time ) > 0 ) { // see if it would block - gptr->sierr = SI_ERR_TP; - if( FD_ISSET( fd, &execpfds ) ) { // error? - SIterm( gptr, tpptr ); // clean up our portion of the session - return SI_ERROR; // and bail from this sinking ship - } else { - if( tpptr->squeue ) { - SIsend( gptr, tpptr ); // something queued; send off queue and queue this - } else { - return SEND( tpptr->fd, ubuf, (unsigned int) ulen, 0 ); // done after send - } - } - } - - gptr->sierr = SI_ERR_NOMEM; - - tpptr->qcount++; - if( (qptr = SInew( IOQ_BLK )) != NULL ) { // alloc a queue block - if( tpptr->sqtail == NULL ) { // if nothing on the queue - tpptr->squeue = qptr; // simple add to the tp blk q - tpptr->sqtail = qptr; - } else { // else - add at end of the q - tpptr->sqtail->next = qptr; - tpptr->sqtail = qptr; - qptr->next = NULL; // new block is the last one now - } // end add block at end of queue - - qptr->dlen = ulen; // copy info to queue block - qptr->data = (char *) malloc( ulen ); // get buffer - memcpy( qptr->data, (const char*) ubuf, ulen ); - - gptr->sierr = SI_QUEUED; // indicate queued to caller - status = SI_QUEUED; // for return - } - } // end if tpptr was not found - //} // ginfo pointer was corrupted - - return status; -} -#endif diff --git a/src/rmr/si/src/si95/sishutdown.c b/src/rmr/si/src/si95/sishutdown.c index 95b6f25..c76bc94 100644 --- a/src/rmr/si/src/si95/sishutdown.c +++ b/src/rmr/si/src/si95/sishutdown.c @@ -35,7 +35,6 @@ #include "sisetup.h" // get includes and defines extern void SIshutdown( struct ginfo_blk *gptr ) { - gptr->sierr = SI_ERR_HANDLE; if( gptr != NULL && gptr->magicnum == MAGICNUM ) { gptr->flags |= GIF_SHUTDOWN; // signal shutdown @@ -43,7 +42,6 @@ extern void SIshutdown( struct ginfo_blk *gptr ) { { gptr->tplist->flags |= TPF_UNBIND; // force unbind on session SIterm( gptr, gptr->tplist ); // and drop the session - } // end while - gptr->sierr = 0; + } } } diff --git a/src/rmr/si/src/si95/siterm.c b/src/rmr/si/src/si95/siterm.c index 0b74ba0..8b732f6 100644 --- a/src/rmr/si/src/si95/siterm.c +++ b/src/rmr/si/src/si95/siterm.c @@ -20,23 +20,26 @@ /* ************************************************************************** -* Mnemonic: SIterm -* Abstract: This routine will terminate a session based on the tp_blk -* that is passed into the routine. The transport session block -* is released and removed from the ginfo list. The session is -* terminated by issuing a t_unbind call (if the unbind flag is -* on in the tpptr block), and then issuing a t_close. -* Parms: gptr - Pointer to the global information block -* tpptr - Pointer to tp block that defines the open fd. -* Returns: Nothing. -* Date: 18 January 1995 -* Author: E. Scott Daniels +* Mnemonic: SIterm +* Abstract: Manage the transport provider block information relating to +* the need to terminate the session. The block is left in the +* list; it is unsafe to clean the lsit up outside of the SIwait +* thread. When safe, the SIrm_tpb() function can be called to +* do the rest of the work that was originally done by SIterm. +* +* Date: 18 January 1995 +* Author: E. Scott Daniels * ************************************************************************** */ #include "sisetup.h" // get the setup stuff #include "sitransport.h" +/* + Close the FD and mark the transport block as unusable/closed. + Removal of the block from the list is safe only from the siwait + thread. +*/ extern void SIterm( struct ginfo_blk* gptr, struct tp_blk *tpptr ) { if( tpptr != NULL ) { @@ -47,14 +50,28 @@ extern void SIterm( struct ginfo_blk* gptr, struct tp_blk *tpptr ) { } } - if( tpptr->prev != NULL ) { // remove from the list - tpptr->prev->next = tpptr->next; // point previous at the next - } else { - gptr->tplist = tpptr->next; // this was head, make next new head - } + tpptr->fd = -1; // prevent future sends etc. + tpptr->flags |= TPF_DELETE; // signal block deletion needed when safe + } +} - if( tpptr->next != NULL ) { - tpptr->next->prev = tpptr->prev; // point next one back behind this one +/* + It is safe to remove the block from the list; if it was in the list + in the first place. +*/ +extern void SIrm_tpb( struct ginfo_blk *gptr, struct tp_blk *tpptr ) { + + if( tpptr != NULL ) { + if( tpptr->prev != NULL || tpptr->next != NULL ) { // in the list + if( tpptr->prev != NULL ) { // remove from the list + tpptr->prev->next = tpptr->next; // point previous at the next + } else { + gptr->tplist = tpptr->next; // this was head, make next new head + } + + if( tpptr->next != NULL ) { + tpptr->next->prev = tpptr->prev; // point next one back behind this one + } } free( tpptr->addr ); // release the address bufers diff --git a/src/rmr/si/src/si95/siwait.c b/src/rmr/si/src/si95/siwait.c index cf06838..0d1e3e5 100644 --- a/src/rmr/si/src/si95/siwait.c +++ b/src/rmr/si/src/si95/siwait.c @@ -71,14 +71,10 @@ extern int SIwait( struct ginfo_blk *gptr ) { ibuf = (char *) malloc( 2048 ); - gptr->sierr = SI_ERR_SHUTD; - if( gptr->flags & GIF_SHUTDOWN ) { // cannot do if we should shutdown return SI_ERROR; // so just get out } - gptr->sierr = SI_ERR_HANDLE; - if( gptr->magicnum != MAGICNUM ) { // if not a valid ginfo block rmr_vlog( RMR_VL_CRIT, "SI95: wait: bad global info struct magic number is wrong\n" ); return SI_ERROR; @@ -127,7 +123,7 @@ extern int SIwait( struct ginfo_blk *gptr ) { status = (*cbptr)( gptr->cbtab[SI_CB_DISC].cbdata, tpptr->fd ); SIcbstat( gptr, status, SI_CB_DISC ); // handle status } - SIterm( gptr, tpptr ); + SIterm( gptr, tpptr ); // close FD and mark block for deletion } } } @@ -139,10 +135,8 @@ extern int SIwait( struct ginfo_blk *gptr ) { free( ibuf ); if( gptr->tplist == NULL ) // indicate all fds closed - gptr->sierr = SI_ERR_NOFDS; if( gptr->flags & GIF_SHUTDOWN ) { // we need to stop for some reason - gptr->sierr = SI_ERR_SHUTD; // indicate error exit status status = SI_ERROR; // status should indicate to user to die SIshutdown( gptr ); // clean things up } else {