modules/sk/sk_socket.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. SK_atoport
  2. SK_close
  3. SK_getsock
  4. SK_accept_connection
  5. SK_read
  6. SK_write
  7. SK_gets
  8. SK_puts
  9. SK_putc
  10. SK_getc
  11. SK_getpeername
  12. SK_getpeerip
  13. SK_cd_puts
  14. SK_cd_gets
  15. SK_cd_close
  16. SK_cd_printf
  17. SK_init
  18. func_sigusr
  19. sk_watchdog
  20. SK_watchstart
  21. SK_watchstop
  22. SK_watchkill
  23. SK_watchexec
  24. SK_watchclear

   1 /***************************************
   2   $Revision: 1.6 $
   3 
   4   Example code: A socket module.
   5 
   6   Status: NOT REVUED, NOT TESTED
   7 
   8   +html+ <DL COMPACT>
   9   +html+ <DT>Online References:
  10   +html+ <DD><UL>
  11   +html+   <LI>Adapted from <A HREF="http://www.ibrado.com/sock-faq/sfaq.html#faq65">sample source code</A>.
  12   +html+ </UL>
  13   +html+ </DL>
  14   +html+ <PRE>
  15   +html+ </PRE>
  16  
  17   ******************/ /******************
  18   Modification History:
  19         ottrey (08/03/1999) Created from sockhelp.c.
  20         ottrey (08/03/1998) Heavily butchered.
  21         joao   (22/06/1999) Modified socket creation and accepts.
  22   ******************/ /******************
  23  REMINDER: PUT THE PROPER COPYRIGHT NOTICE HERE
  24   ***************************************/
  25 #include <arpa/inet.h>
  26 #include "socket.h"
  27 #include "constants.h"
  28 #include "stubs.h"
  29 
  30 #include "iproutines.h"
  31 #include "memwrap.h"
  32 
  33 #include <pthread.h>
  34 
  35 extern int h_errno;
  36 
  37 
  38 /*+ String sizes +*/
  39 #define STR_S   63
  40 #define STR_M   255
  41 #define STR_L   1023
  42 #define STR_XL  4095
  43 #define STR_XXL 16383
  44 
  45 /* SK_atoport() */
  46 /*++++++++++++++++++++++++++++++++++++++
  47    Take a service name, and a service type, and return a port number.  If the
  48    service name is not found, it tries it as a decimal number.  The number
  49    returned is byte ordered for the network.
  50 
  51   char *service   Service name (or port number).
  52 
  53   char *proto     Protocol (eg "tcp").
  54 
  55   More:
  56   +html+ <PRE>
  57   Authors:
  58         ottrey
  59 
  60   +html+ </PRE><DL COMPACT>
  61   +html+ <DT>Online References:
  62   +html+ <DD><UL>
  63   +html+ </UL></DL>
  64 
  65   ++++++++++++++++++++++++++++++++++++++*/
  66 int SK_atoport(const char *service, const char *proto) {
     /* [<][>][^][v][top][bottom][index][help] */
  67   int port;
  68   long int lport;
  69   struct servent *serv;
  70   char *errpos;
  71   struct servent result;
  72   char buffer[STR_XXL];
  73 
  74   /* First try to read it from /etc/services */
  75 
  76   /*  serv = getservbyname(service, proto); */
  77   serv = getservbyname_r(service, proto, &result, buffer, sizeof(buffer));
  78   if (serv != NULL)
  79     port = serv->s_port;
  80   else { /* Not in services, maybe a number? */
  81     lport = strtol(service,&errpos,0);
  82     if ( (errpos[0] != 0) || (lport < 1) || (lport > 65535) )
  83       return -1; /* Invalid port address */
  84     port = htons(lport);
  85   }
  86   return port;
  87 } /* SK_atoport() */
  88 
  89 
  90 /* SK_close() */
  91 /*++++++++++++++++++++++++++++++++++++++
  92   
  93   More:
  94   +html+ <PRE>
  95   Authors:
  96         ottrey
  97 
  98   +html+ </PRE><DL COMPACT>
  99   +html+ <DT>Online References:
 100   +html+ <DD><UL>
 101   +html+ </UL></DL>
 102 
 103   ++++++++++++++++++++++++++++++++++++++*/
 104 int SK_close(int socket) {
     /* [<][>][^][v][top][bottom][index][help] */
 105   ER_dbg_va(FAC_SK, ASP_SK_GEN, "Closing socket... %d", socket);
 106 
 107   return close(socket);
 108 }
 109 
 110 /* SK_getsock() */
 111 /*++++++++++++++++++++++++++++++++++++++
 112 
 113    This function creates a socket and binds to it
 114 
 115    int      SK_getsock       The new socket
 116 
 117    int      socket_type      SOCK_STREAM or SOCK_DGRAM (TCP or UDP sockets)
 118 
 119    u_short  port             The port to listen on.  Remember that ports < 1024 are
 120                              reserved for the root user.  Must be passed in network byte
 121                              order (see "man htons").
 122 
 123    uint32_t bind_address     Address to bind to, in network order.
 124   More:
 125   +html+ <PRE>
 126   Authors:
 127         ottrey
 128         joao
 129 
 130   +html+ </PRE><DL COMPACT>
 131   +html+ <DT>Online References:
 132   +html+ <DD><UL>
 133   +html+ </UL></DL>
 134 
 135   ++++++++++++++++++++++++++++++++++++++*/
 136 int SK_getsock(int socket_type, u_short port, uint32_t bind_address) {
     /* [<][>][^][v][top][bottom][index][help] */
 137   struct sockaddr_in address;
 138   int listening_socket;
 139   int reuse_addr = 1;
 140 
 141   /* Setup internet address information.  
 142      This is used with the bind() call */
 143   memset((char *) &address, 0, sizeof(address));
 144   address.sin_family = AF_INET;
 145   address.sin_port = port;
 146   address.sin_addr.s_addr = bind_address;
 147 
 148   /* Map all of the signals and exit routine */
 149 
 150   listening_socket = socket(AF_INET, socket_type, 0);
 151   if (listening_socket < 0) {
 152     perror("socket");
 153     exit(EXIT_FAILURE);
 154   }
 155 
 156   setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse_addr, sizeof(reuse_addr));
 157 
 158   if (bind(listening_socket, (struct sockaddr *) &address, sizeof(address)) < 0) {
 159     perror("bind");
 160     close(listening_socket);
 161     exit(EXIT_FAILURE);
 162   }
 163 
 164 
 165   if (socket_type == SOCK_STREAM) {
 166     listen(listening_socket, 5); /* Queue up to five connections before
 167                                   having them automatically rejected. */
 168   }
 169 
 170   return listening_socket;
 171 } /* SK_getsock() */
 172 
 173 /*++++++++++++++++++++++++++++++++++++++
 174 
 175    Wait for an incoming connection on the specified socket
 176 
 177    int  SK_accept_connection The socket for communicating to the client
 178 
 179    int  listening_socket     The socket that the server is bound to
 180 
 181   More:
 182   +html+ <PRE>
 183   Authors:
 184         joao
 185   +html+ </PRE>
 186   ++++++++++++++++++++++++++++++++++++++*/
 187 int SK_accept_connection(int listening_socket) {
     /* [<][>][^][v][top][bottom][index][help] */
 188   int connected_socket = -1;
 189 
 190   while(connected_socket < 0) {
 191     
 192     ER_dbg_va(FAC_SK, ASP_SK_GEN, 
 193               "Going to accept connections on socket : %d",listening_socket);
 194 
 195 /* XXX joao - ? - why is this here?
 196 fflush(NULL);
 197 */
 198 
 199     connected_socket = accept(listening_socket, NULL, NULL);
 200     if (connected_socket < 0) {
 201       /* Either a real error occured, or blocking was interrupted for
 202          some reason.  Only abort execution if a real error occured. */
 203       if (errno != EINTR) {
 204         perror("accept");
 205         close(listening_socket);
 206         return(-1);
 207      /* no exit, just return with error */
 208       } else {
 209         continue;    /* don't return - do the accept again */
 210       }
 211     }
 212   }
 213 
 214   ER_dbg_va(FAC_SK, ASP_SK_GEN, "client connected on socket %d", 
 215             connected_socket
 216             );
 217 
 218   return connected_socket;
 219 }
 220 
 221 /* SK_read() */
 222 /*++++++++++++++++++++++++++++++++++++++
 223 
 224    This is just like the read() system call, except that it will make
 225    sure that all your data goes through the socket.
 226 
 227    int    SK_read  The number of bytes read.
 228 
 229    int    sockfd    The socket file descriptor.
 230 
 231    char   *buf      The buffer to be read from the socket.
 232 
 233    size_t count     The number of bytes in the buffer.
 234 
 235   More:
 236   +html+ <PRE>
 237   Authors:
 238         ottrey
 239   +html+ </PRE>
 240   ++++++++++++++++++++++++++++++++++++++*/
 241 int SK_read(int sockfd, char *buf, size_t count) {
     /* [<][>][^][v][top][bottom][index][help] */
 242   size_t bytes_read = 0;
 243   int this_read;
 244 
 245   while (bytes_read < count) {
 246     do
 247       this_read = read(sockfd, buf, count - bytes_read);
 248     while ( (this_read < 0) && (errno == EINTR) );
 249     if (this_read < 0)
 250       return this_read;
 251     else if (this_read == 0)
 252       return bytes_read;
 253     bytes_read += this_read;
 254     buf += this_read;
 255   }
 256 
 257   return count;
 258 
 259 } /* SK_read() */
 260 
 261 
 262 /* SK_write() */
 263 /*++++++++++++++++++++++++++++++++++++++
 264 
 265    This is just like the write() system call, accept that it will
 266    make sure that all data is transmitted.
 267 
 268    int    sockfd  The socket file descriptor.
 269 
 270    char   *buf    The buffer to be written to the socket.
 271 
 272    size_t count   The number of bytes in the buffer.
 273 
 274   More:
 275   +html+ <PRE>
 276   Authors:
 277         ottrey
 278 
 279   +html+ </PRE><DL COMPACT>
 280   +html+ <DT>Online References:
 281   +html+ <DD><UL>
 282   +html+ </UL></DL>
 283 
 284   ++++++++++++++++++++++++++++++++++++++*/
 285 int SK_write(int sockfd, const char *buf, size_t count) {
     /* [<][>][^][v][top][bottom][index][help] */
 286   size_t  bytes_sent = 0;
 287   int     this_write;
 288 
 289   
 290   ER_dbg_va(FAC_SK, ASP_SK_WRIT,
 291             "SK_write = { sockfd=[%d], buf=[%s], count=[%d]", 
 292             sockfd, buf, count);
 293 
 294   while (bytes_sent < count) {
 295     do
 296       this_write = write(sockfd, buf, count - bytes_sent);
 297     while ( (this_write < 0) && (errno == EINTR) );
 298     if (this_write <= 0)
 299       return this_write;
 300     bytes_sent += this_write;
 301     buf += this_write;
 302   }
 303   return count;
 304 } /* SK_write() */
 305 
 306 
 307 /* SK_gets() */
 308 /*++++++++++++++++++++++++++++++++++++++
 309 
 310    This function reads from a socket, until it recieves a linefeed
 311    character.  It fills the buffer "str" up to the maximum size "count".
 312 
 313    int SK_gets  The total_count of bytes read.
 314 
 315    int    sockfd    The socket file descriptor.
 316 
 317    char   *str      The buffer to be written from the socket.
 318 
 319    size_t count     The number of bytes in the buffer.
 320 
 321   More:
 322   +html+ <PRE>
 323   Authors:
 324         ottrey
 325 
 326   Side Effects:
 327         This function will return -1 if the socket is closed during the read operation.
 328 
 329         Note that if a single line exceeds the length of count, the extra data
 330         will be read and discarded!  You have been warned.
 331 
 332   To Do:
 333         Capture the control-c properly!
 334 
 335   +html+ </PRE>
 336 
 337   ++++++++++++++++++++++++++++++++++++++*/
 338 int SK_gets(int sockfd, char *str, size_t count) {
     /* [<][>][^][v][top][bottom][index][help] */
 339   int bytes_read;
 340   int total_count = 0;
 341   char *current_position;
 342   char last_read = 0;
 343 
 344   int control_c = 0;
 345 
 346   current_position = str;
 347   while (last_read != 10) {
 348 
 349     
 350 
 351     bytes_read = read(sockfd, &last_read, 1);
 352     if (bytes_read <= 0) {
 353       /* The other side may have closed unexpectedly */
 354       return SK_DISCONNECT; 
 355       /* Is this effective on other platforms than linux? */
 356     }
 357     if ( (total_count < count) && (last_read != 10) && (last_read !=13) ) {
 358       *current_position = last_read;
 359       current_position++;
 360       total_count++;
 361     }
 362 
 363     if (last_read == -1) {
 364       bytes_read = read(sockfd, &last_read, 1);
 365       if (last_read == -12) {
 366         ER_dbg_va(FAC_SK, ASP_SK_GEN,"Client pressed Control-c");
 367         control_c = 1;
 368         ER_dbg_va(FAC_SK, ASP_SK_GEN,"returning SK_INTERRUPT");
 369         return SK_INTERRUPT;
 370       }
 371     }
 372   }
 373   if (count > 0) {
 374     *current_position = 0;
 375   }
 376 
 377   return total_count;
 378 
 379 } /* SK_gets() */
 380 
 381 
 382 /* SK_puts() */
 383 /*++++++++++++++++++++++++++++++++++++++
 384 
 385    This function writes a character string out to a socket.
 386 
 387    int SK_puts  The total_count of bytes written, 
 388                 or errors (represented as negative numbers)
 389 
 390    int    sockfd    The socket file descriptor.
 391 
 392    char   *str      The buffer to be written from the socket.
 393 
 394   More:
 395   +html+ <PRE>
 396   Authors:
 397         ottrey
 398 
 399   Side Effects:
 400         This function will return -1 if the socket is closed during the write operation.
 401 
 402         Note that if a single line exceeds the length of count, the extra data
 403         will be read and discarded!  You have been warned.
 404 
 405   +html+ </PRE>
 406 
 407   ++++++++++++++++++++++++++++++++++++++*/
 408 int SK_puts(int sockfd, const char *str) {
     /* [<][>][^][v][top][bottom][index][help] */
 409 
 410   return SK_write(sockfd, str, strlen(str));
 411 
 412 } /* SK_puts() */
 413 
 414 /* SK_putc() */
 415 /*++++++++++++++++++++++++++++++++++++++
 416 
 417    int SK_putc This function writes a single character out to a socket.
 418 
 419    int sockfd        socket
 420    char ch           character
 421 
 422    return number of chars written 
 423 
 424   ++++++++++++++++++++++++++++++++++++++*/
 425 int SK_putc(int sockfd, char ch) {
     /* [<][>][^][v][top][bottom][index][help] */
 426   return SK_write(sockfd, &ch, 1);
 427 }/* SK_putc() */
 428 
 429 /*++++++++++++++++++++++++++++++++++++++
 430 
 431    This function reads a single character from a socket.
 432 
 433    returns EOF when no character can be read. 
 434 
 435   ++++++++++++++++++++++++++++++++++++++*/
 436 int SK_getc(int sockfd) {
     /* [<][>][^][v][top][bottom][index][help] */
 437   char ch;
 438 
 439   if( read(sockfd, &ch, 1) <= 0 ) {
 440     return EOF;
 441   }
 442   else {
 443     return ch;
 444   }
 445 }/* SK_getc() */
 446 
 447 /* SK_getpeername() */
 448 /*++++++++++++++++++++++++++++++++++++++
 449 
 450    This function will tell you who is at the other end of a connected stream socket.
 451    XXX It's not working.
 452    XXX ? MB it is...
 453 
 454    int    sockfd    The socket file descriptor.
 455 
 456   More:
 457   +html+ <PRE>
 458   Authors:
 459         ottrey
 460   +html+ </PRE>
 461 
 462   ++++++++++++++++++++++++++++++++++++++*/
 463 char *SK_getpeername(int sockfd) 
     /* [<][>][^][v][top][bottom][index][help] */
 464 {
 465   char *hostaddress=NULL;
 466   struct sockaddr_in addr_in;
 467   int namelen=sizeof(addr_in);
 468  
 469   if (getpeername(sockfd, (struct sockaddr *)&addr_in, &namelen) != -1) {
 470 
 471     dieif( wr_malloc((void **)&hostaddress, 16) != UT_OK); 
 472     
 473     strcpy(hostaddress, inet_ntoa(addr_in.sin_addr));  /* XXX MT-UNSAFE */
 474   }
 475 
 476   return hostaddress;
 477   
 478 } /* SK_getpeername() */
 479 
 480 /* SK_getpeerip */
 481 int SK_getpeerip(int sockfd, ip_addr_t *ip) {
     /* [<][>][^][v][top][bottom][index][help] */
 482   struct sockaddr_in addr_in;
 483   int namelen=sizeof(addr_in);
 484   int ret=-1;
 485 
 486   memset(& addr_in, 0, sizeof(struct sockaddr_in));
 487 
 488   if (getpeername(sockfd, (struct sockaddr *)(& addr_in), &namelen) != -1) {
 489     ret=0;
 490     IP_addr_s2b(ip, &addr_in, namelen);
 491   }
 492   
 493   return ret;
 494 }
 495 
 496 /*-------------------------------------------------------------------
 497  *   CD varieties of the functions: broken connections get registered
 498  *   in the connection structure within the query environment 
 499  *   as side effects.
 500  * -----------------------------------------------------------------*/
 501 
 502 /* SK_cd_puts() */
 503 /*++++++++++++++++++++++++++++++++++++++
 504 
 505    This function writes a character string out to a socket.
 506 
 507    int SK_qe_puts  The total_count of bytes written, 
 508                 or errors (represented as negative numbers)
 509 
 510    sk_conn_st *condat connection data
 511 
 512    char   *str       The buffer to be written from the socket.
 513 
 514   More:
 515        if the connection structure has bad status for this connection
 516        from previous calls, no write will be attempted.
 517 
 518   +html+ <PRE>
 519   Authors:
 520         marek
 521 
 522   Side Effects:
 523        broken connections get registered
 524        in the connection structure within the query environment 
 525         
 526   +html+ </PRE>
 527 
 528   ++++++++++++++++++++++++++++++++++++++*/
 529 int SK_cd_puts(sk_conn_st *condat, const char *str) {
     /* [<][>][^][v][top][bottom][index][help] */
 530   int res=SK_puts(condat->sock, str);
 531 
 532   if( res < 0 ){
 533     /* set the corresponding rtc flag */
 534     condat->rtc |= (-res);
 535 
 536     switch( - res ) {
 537       /* dont know what to do and how to log */
 538     case SK_DISCONNECT:
 539     case SK_INTERRUPT:
 540       /*("Thread received a control-c\n");*/
 541     case SK_TIMEOUT:
 542       /*("Reading timed out\n");*/
 543       break;
 544     default:
 545       /* unexpected error code. bail out */
 546       die;
 547     }
 548   }
 549   return res;
 550 } /* SK_cd_puts() */
 551 
 552 /* SK_cd_gets() */
 553 /*++++++++++++++++++++++++++++++++++++++
 554 
 555    Wrapper around SK_gets.
 556 
 557    int SK_cd_gets  The total_count of bytes read, 
 558                    or errors (represented as negative numbers)
 559 
 560    sk_conn_st *condat connection data
 561 
 562    char   *str       The buffer to be written from the socket.
 563 
 564   More:
 565        if the connection structure has bad status for this connection
 566        from previous calls, no write will be attempted.
 567 
 568   +html+ <PRE>
 569   Authors:
 570         marek
 571         
 572   Side Effects:
 573        broken connections get registered
 574        in the connection structure within the query environment 
 575        
 576   +html+ </PRE>
 577 
 578   ++++++++++++++++++++++++++++++++++++++*/
 579 int SK_cd_gets(sk_conn_st *condat, char *str, size_t count) {
     /* [<][>][^][v][top][bottom][index][help] */
 580   fd_set rset;
 581   struct timeval *ptm = & condat->rd_timeout;
 582   int readcount = 0;
 583   
 584   memset( str, 0, count);
 585   FD_ZERO( &rset );
 586   FD_SET( condat->sock, &rset );
 587 
 588   if( ptm->tv_sec == 0 && ptm->tv_usec == 0) { /* if timeout undefined, 
 589                                                   do blocking I/O */
 590     ptm = NULL;
 591   }
 592 
 593   do {
 594     char buf[2];
 595     int sel = select( (condat->sock)+1, &rset, NULL, NULL, ptm);    
 596 
 597     dieif(sel < 0); /* we don't expect problems */
 598       
 599     if( sel == 0 ) {      
 600       condat->rtc |= SK_TIMEOUT;
 601       break;
 602     }
 603 
 604     else { 
 605       read( condat->sock, buf, 1 );
 606       str[readcount] = buf[0];
 607       readcount++;
 608       if( buf[0] == '\n' ) {
 609         break;
 610       }
 611     } 
 612   } while( readcount < count );
 613          
 614   return readcount;
 615 
 616 } /* SK_cd_gets() */
 617 
 618 
 619 int SK_cd_close(sk_conn_st *condat) {
     /* [<][>][^][v][top][bottom][index][help] */
 620   return SK_close(condat->sock);
 621 } /* SK_cd_close() */
 622 
 623 
 624 /* print to condat like printf
 625 
 626    by marek
 627 */
 628 int SK_cd_printf(sk_conn_st *condat, char *txt, ...)
     /* [<][>][^][v][top][bottom][index][help] */
 629 {
 630 #define SKBUFLEN 2047
 631   va_list   ap;
 632   char      buffer[SKBUFLEN+1];
 633   int       len;
 634   char      *newbuf = NULL;
 635   char      *finalbuf = buffer; /* points to where the text REALLY is */
 636  
 637   /* vsnprintf returns the number of character it WOULD write if it could.
 638      So we assume the buffer to be of adequate size for most cases,
 639      and if it isn't, then we allocate to newbuf and call v*printf again 
 640   */
 641   va_start(ap, txt);
 642   len = vsnprintf(buffer, SKBUFLEN, txt, ap);
 643   va_end(ap);
 644   
 645   if( len > SKBUFLEN ) {
 646     dieif(!NOERR(wr_malloc( (void **)& newbuf, len+1)));
 647     
 648     va_start(ap, txt);
 649     vsnprintf(newbuf, len, txt, ap);
 650     va_end(ap);   
 651     
 652     finalbuf = newbuf;
 653   }  
 654   /* terminate */
 655   finalbuf[len] = 0;
 656 
 657   /* reuse len */
 658   len = SK_cd_puts(condat, finalbuf);
 659 
 660   if(newbuf != NULL) {
 661     wr_free(newbuf);
 662   }
 663 
 664   return len;
 665 }
 666 
 667 /* =========================== watchdog =========================== */
 668 
 669 #define ONCE_INIT 0xABCDEF
 670 static pthread_key_t sk_watch_tsd = ONCE_INIT;
 671 
 672 void SK_init(void)
     /* [<][>][^][v][top][bottom][index][help] */
 673 {
 674   /* can be called only once */
 675   dieif( sk_watch_tsd != ONCE_INIT );
 676   dieif( pthread_key_create( &sk_watch_tsd, NULL) != 0 );
 677 }
 678 
 679 /* sk_watchdog signal handler */
 680 static void func_sigusr(int n) {
     /* [<][>][^][v][top][bottom][index][help] */
 681   int *tsd_flag = (int *) pthread_getspecific(sk_watch_tsd);
 682 
 683   ER_dbg_va(FAC_SK, ASP_SK_GEN,"func_sigusr(%d) called", n);
 684 
 685   /* set a thread-specific flag that the handler was invoked */
 686   
 687   pthread_setspecific(sk_watch_tsd, (void *)1 );
 688 }
 689 
 690 /* sk_watchdog - started as a separate thread.
 691 
 692    selects on the given socket; discards all input.
 693    whenever it sees end of file (socket closed), it
 694    * sets a corresponding flag in the condat structure, 
 695    * kills a thread designated to be killed (by SK_watchkill)
 696 
 697    by marek;
 698 */
 699 static
 700 void *sk_watchdog(void *arg)
     /* [<][>][^][v][top][bottom][index][help] */
 701 {
 702   sk_conn_st *condat = (sk_conn_st *) arg;
 703   int nready;
 704   int n;
 705   fd_set rset;
 706   char buff[STR_S];
 707   int socket = condat->sock;
 708   sigset_t sset;
 709   struct sigaction act;
 710   
 711   struct timeval timeout = { 1, 0 }; /* it's a timeout of 1 second */
 712 
 713   FD_ZERO(&rset);
 714   FD_SET(socket, &rset);
 715 
 716   sigemptyset(&sset);
 717   sigaddset(&sset, SIGUSR1);
 718   
 719   act.sa_handler = func_sigusr;
 720   act.sa_flags = 0;
 721   dieif(sigaction(SIGUSR1, &act, NULL) != 0);
 722 
 723   /* XXX in fact, it's unblocked already. Should be blocked on startup */
 724   dieif(pthread_sigmask(SIG_UNBLOCK, &sset, NULL) != 0);
 725   
 726   /* clear the handler's flag */
 727   pthread_setspecific(sk_watch_tsd, NULL);
 728   
 729   /* now ready for signal */
 730   pthread_mutex_unlock( & condat->watchmutex ); 
 731 
 732   /* hey, viva threaded signal handling! There is no way for select
 733      to unblock a blocked signal, It must be done by "hand" (above).
 734 
 735      Consequently, every once in a while, the signal will be delivered
 736      before the select starts :-/. So, we have to introduce a timeout
 737      for select and check if the signal was delivered anyway....aARGH!!!
 738 
 739      This adds a <timeout interval> to unlucky queries, about 0.1% of all.
 740   */
 741 
 742   while ((nready=select(socket+1, &rset, NULL, NULL, &timeout))!=-1) {
 743     
 744     ER_dbg_va(FAC_SK, ASP_SK_GEN,"select returned %d", nready);
 745 
 746     /* don't even try to read if we have been killed */
 747     if( errno == EINTR || pthread_getspecific(sk_watch_tsd) != NULL ) {
 748       break;
 749     }
 750 
 751     /* retry if the timeout has triggered */
 752     if( nready == 0 ) {
 753       continue;
 754     }
 755 
 756    /* There was some input or client half of connection was closed */
 757    /* Check for the latter */
 758    if (( n=read(socket, buff, sizeof(buff))) == 0) {
 759    /* Connection was closed by client */
 760    /* Now send a cancellation request to the whois thread. */
 761    /* mysql thread will be terminated by thread cleanup routine */
 762    
 763      /* set the reason-to-close flag on this connection */
 764      condat->rtc |= SK_INTERRUPT;
 765 
 766      /* cancel the thread to be cancelled if defined */
 767      if( condat->killthis != 0 ) {
 768        pthread_cancel(condat->killthis);
 769        /* The only possible error is ESRCH, so we do not care about it*/
 770      }
 771 
 772      /* call the function to be called if defined */
 773      if( condat->execthis != NULL ) {
 774        condat->execthis(condat->execargs);
 775      }
 776 
 777      /* quit */
 778      break;
 779    }
 780    /* Otherwise dump input and continue */
 781 
 782   }
 783 
 784   /* Exit the watchdog thread, passing NULL as we don't expect a join */
 785   pthread_exit(NULL);
 786 
 787   /* oh yes. Shouldn't compilers _analyze_ library functions ? */
 788   return NULL;
 789 }
 790 /* SK_watchstart
 791 
 792    starts sk_watchdog thread unless already started,
 793    and registers its threadid in the condat structure
 794 
 795    dies if watchdog already running
 796 */
 797 er_ret_t
 798 SK_watchstart(sk_conn_st *condat)
     /* [<][>][^][v][top][bottom][index][help] */
 799 {
 800   dieif( condat->watchdog != 0 );
 801   
 802   /* init the mutex in locked state, watchdog will unlock it when 
 803      it's ready for signal */
 804   pthread_mutex_init( & condat->watchmutex, NULL );
 805   pthread_mutex_lock( & condat->watchmutex ); 
 806 
 807   pthread_create(&condat->watchdog, NULL, sk_watchdog, (void *) condat );
 808   
 809   return SK_OK;
 810 }
 811 
 812 
 813 /* SK_watchstop 
 814 
 815    stops sk_watchdog thread if it is registered in the connection struct
 816 */
 817 er_ret_t
 818 SK_watchstop(sk_conn_st *condat)
     /* [<][>][^][v][top][bottom][index][help] */
 819 {
 820   void *res;
 821 
 822   if(condat->watchdog > 0) {
 823     int ret;
 824 
 825     /* wait until the watchdog is ready for signal */
 826     pthread_mutex_lock( & condat->watchmutex ); 
 827 
 828     ret = pthread_kill(condat->watchdog, SIGUSR1);
 829     
 830     ret = pthread_join(condat->watchdog, &res);
 831     
 832     pthread_mutex_destroy( & condat->watchmutex ); 
 833     condat->watchdog = 0;
 834   }
 835   return SK_OK;
 836 }
 837 
 838 /* SK_watchkill
 839 
 840    sets the threadid of the thread to be killed by watchdog
 841    0 means dont kill anything
 842 */
 843 void
 844 SK_watchkill(sk_conn_st *condat, pthread_t killthis)
     /* [<][>][^][v][top][bottom][index][help] */
 845 {
 846   condat->killthis = killthis;
 847 }
 848 
 849 void
 850 SK_watchexec( sk_conn_st *condat, void *(*function)(void *) , void *args)
     /* [<][>][^][v][top][bottom][index][help] */
 851 {
 852   condat->execthis = function;
 853   condat->execargs = args;
 854 }
 855 
 856 void 
 857 SK_watchclear(sk_conn_st *condat) 
     /* [<][>][^][v][top][bottom][index][help] */
 858 {
 859   condat->execthis = NULL;
 860   condat->execargs = NULL;
 861   condat->killthis = 0;
 862 }

/* [<][>][^][v][top][bottom][index][help] */