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 <daniels@research.att.com>
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 @@
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 )
-{
+extern int SIclose( struct ginfo_blk *gptr, int fd ) {
+ struct tp_blk *tpptr; // pointer into tp list
+ int status = SI_ERROR; // status of processing
- struct tp_blk *tpptr; // pointer into tp list
- int status = SI_ERROR; // status of processing
+ 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 );
+ }
+ }
- 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 );
- }
-
- if( tpptr != NULL )
- {
- gptr->sierr = SI_ERR_TP;
-
- 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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 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 @@
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 @@
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 @@
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 @@
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 @@
}
*/
-
-/*
-//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 @@
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 @@
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 @@
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 @@
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 @@
{
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 @@
}
}
- 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 @@
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 @@
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 @@
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 {