[comp.lang.c] Interrupt driven socket -read and write

kannan@b.cs.wvu.wvnet.edu (Raman Kannan) (04/18/89)

The problem I am trying to solve is to be interrupted when 
there is something to read from a socket.

I am using signal (SIGIO, handler_function).

Within that handler I do the following:

	reset my interrupt

	
	accept --- check for errors and get the file descriptor

	read on the fd. -- check for errors

	return ; hoping to get back to place where the main was interrupted.
The trouble I am having:

It does not return to the main after the call to accept.

OBSERVED:

	Multiple interrupts trigger the handler function. I put some
print stmts to check it.

	If I return before the accept call, the main loop comes back to
	life.

Can soemone point out the problem. Thank you very much in advance.

---==== The following is the source

/* sock header has socket and fcntl include 
   and a couple of int definitions */

#include "sock_header.h"
#include <signal.h>

/* 
   this code listens on a socket
   and writes out on stdio.
   Quits when the message recd is ENDING ALL CONNECTIONS

*/


  int rval, sock , msgsock , length ;
  struct sockaddr_in name ;
  int buf_count ;
/*****************

THIS IS COMMON BLOCK 


*****************/

  /* the kb_buffer holds the recd message until it is processed */
  char kb_buffer [10] [1024] ;

  /* the r_id indicates the next buffer to be used for reading
     the w_id indicates the next buffer to ne used for writing
     the kbstatus indicates the current status of the next
     buffer 
     0 => has been read and can be written over
     1 => has been written and must be read before writing
  */

  int r_id , w_id  , kbstatus [10] ;

/*****************

END OF COMMON BLOCK 

*****************/

  char buf [1024],  rd_buf [1024] ;

/* set all buffers to be written 
   A buffer can be written only if the content has been read 
*/

initialize_buffers ()

{
  int i = 0 ;
  for (; i < 10 ; ) kbstatus [i++] = HAS_BEEN_READ ;
  r_id = w_id = 0 ;
}

int io_handler ()
{
   /* when a signal is raised
      it resets to default
      so set it back to our handler */
   signal ( SIGIO,  io_handler  ) ;


   if ( kbstatus[w_id] ) {
	 printf ("\n all buffers full ");
	 return ;}

   msgsock = accept ( sock , (struct sockaddr *)0 , (int *) 0) ;

   buf_count = 0 ;

   if ( msgsock == -1 ) { perror ("accept") ;
			  exit (1) ;

			}
/* a connection has been accepted
   clear the next write buffer */

   bzero ( kb_buffer[w_id] , LCM_BLOCK_SIZE ) ;


printf ("\n In INTERRUPT HANDLER\n");

     bzero ( rd_buf , LCM_BLOCK_SIZE ) ;     
     if  ( (rval = read ( msgsock , rd_buf, LCM_BLOCK_SIZE ))< 0 ) {
       perror ("READING STREAM SOCKET") ;
       exit (0) ;  }
     
     else if ( rval != 0 ) {

      /* place it in a buffer for processing by the main module */
       strcat ( kb_buffer[w_id] , rd_buf ) ;

       printf ("\n<%s>", rd_buf ) ;
       printf ("\n<kb_buffer =>%s>", kb_buffer[w_id]);

       buf_count += rval ; 


      /* printf ("\n--> %s \n",rd_buf ) ;*/
     }

       /* indicate that this buffer buffer is not yet read */

printf ("\nbuffer being written is <%d>",w_id);

       kbstatus [w_id] = 1 ;

       /* next buffer */
   if ( ++w_id == 10 ) w_id = 0 ;
   close (msgsock ) ;

printf ("\nreturning from interrupt");
return rval ;
 }/* returning from interrrupt */

main ()

{ 

  initialize_buffers () ;
  sock = socket ( AF_INET , SOCK_STREAM , 0 ) ;
  
  if ( sock < 0 ) {
    perror ( "opening SOCK_STREAM socket");
    exit (1) ;
  }

  name.sin_family = AF_INET ;
  
  name.sin_addr.s_addr = INADDR_ANY ;

  name.sin_port = READ_SOCK ;

  if ( bind ( sock ,(struct sockaddr *) &name , sizeof name ) < 0 )
    {
      perror ("binding STREAM SOCKET");
      exit (1) ;

    }


/* set up interrupt for reading on sock */
 signal ( SIGIO,  io_handler  ) ;

 /* set th eprocess receving the SIGIO/SIGURG signal to us */

 if ( fcntl ( sock , F_SETOWN , getpid () ) < 0 ) {
   perror ("COULDNT SET OWNER FOR THE SIGURG");
   exit (1) ;
 }

/* allow receipt of asynchrouns I/O signal */

 if ( fcntl ( sock , F_SETFL , FASYNC ) < 0 ) {
   perror ("COULDNT SET asynchrnous I/O");
   exit (1) ;
 }

listen ( sock , 5 ) ;

do {

  /* the r_id refers to next buffer in the ring 
     if it is the end of the ring reset it to the 
     beginning of the buffer */

  if ( r_id == 10 ) r_id = 0 ; 

  printf ("\n< MAIN LOOP WORKING>\n");   
printf ("\nbuffer being checked is <%d>",r_id);
  if ( kbstatus [ r_id ] )

    { /* something has been  written into this buffer
	 let us process it */

    printf ("\n< SOMETHING CAME IN THE SOCKET>\n\n");   

    printf ("The string recd <%s>",kb_buffer [r_id ]);

   if ( strcmp ( kb_buffer[r_id] , "END ALL CONNECTION"))
     printf ("Ending this connection \n") ;
   else {
     printf ("\n--> ENDING ALL CONNECTIONS" ) ;
     exit (1) ;
       }
    /* reset the buffer */
    kbstatus [r_id++] = 0 ;
  }
   sleep (5) ;
   } while ( 1 ) ;

}

----====END OF SOURCE


--kannan
  Concurrent Engineering Research Center,
  West Virginia University, Morgantown.