Address multi-threading issues in SI95 01/2601/1
authorE. Scott Daniels <daniels@research.att.com>
Tue, 25 Feb 2020 15:40:20 +0000 (10:40 -0500)
committerE. Scott Daniels <daniels@research.att.com>
Tue, 25 Feb 2020 15:40:20 +0000 (10:40 -0500)
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

14 files changed:
src/rmr/si/src/si95/sibldpoll.c
src/rmr/si/src/si95/siclose.c
src/rmr/si/src/si95/siconnect.c
src/rmr/si/src/si95/siestablish.c
src/rmr/si/src/si95/siinit.c
src/rmr/si/src/si95/silisten.c
src/rmr/si/src/si95/sipoll.c
src/rmr/si/src/si95/siproto.h
src/rmr/si/src/si95/sircv.c
src/rmr/si/src/si95/sisend.c
src/rmr/si/src/si95/sisendt.c
src/rmr/si/src/si95/sishutdown.c
src/rmr/si/src/si95/siterm.c
src/rmr/si/src/si95/siwait.c

index 6ad26ea..5b50fcc 100644 (file)
@@ -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 ) {      
index cb5cf36..eed11ef 100644 (file)
@@ -18,7 +18,7 @@
 ==================================================================================
 */
 
-/* X
+/*
 ******************************************************************************
 *
 *  Mnemonic: SIclose
 *  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: 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 
+
index 842207f..114e873 100644 (file)
@@ -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 ) {
index bdb3f72..846faa1 100644 (file)
@@ -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 
index 9159f69..b297124 100644 (file)
@@ -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 
 
        
index c7151d4..8cd484a 100644 (file)
@@ -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
index df71eae..0ecca66 100644 (file)
@@ -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
   }
index bb94d2a..c59d626 100644 (file)
@@ -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 );
index 2202629..d69cb61 100644 (file)
@@ -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 );
index 5a8a94e..c0233ae 100644 (file)
@@ -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 
index 81a3be6..8a4d5f0 100644 (file)
@@ -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
index 95b6f25..c76bc94 100644 (file)
@@ -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;
+               }
        }
 }            
index 0b74ba0..8b732f6 100644 (file)
 
 /*
 **************************************************************************
-*  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 
index cf06838..0d1e3e5 100644 (file)
@@ -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 {