## modules/sv/server.c

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

## FUNCTIONS

This source file includes following functions.

1. log_print
2. radix_init
3. main_loop
4. SV_start
5. SV_shutdown
6. SV_sleep
7. SV_signal_thread
8. SV_concurrent_server
9. SV_do_whois
10. SV_do_mirror
11. SV_do_config
12. SV_watchdog
13. do_watchdog

       1 /***************************************
       2   $Revision: 1.28 $
       3
       4   Example code: A server for a client to connect to.
       5
       6   Status: NOT REVUED, NOT TESTED
       7
       8  Authors:       Chris Ottrey, Joao Damas
       9
      10   +html+ <DL COMPACT>
      11   +html+ <DT>Online References:
      12   +html+ <DD><UL>
      13   +html+   <LI>Based on <A HREF="http://iii.ripe.net/dbase/coding/new.code/progress/ottrey/code/java/src/DBServer.java">DBServer.java</A>
      14   +html+ </UL>
      15   +html+ </DL>
      16
      17   ******************/ /******************
      18   Modification History:
      19         ottrey (02/03/1999) Created.
      20         ottrey (08/03/1999) Modified.
      21         joao   (22/06/1999) Modified.
      22   ******************/ /******************
      23   Copyright (c) 1999                              RIPE NCC
      24
      25   All Rights Reserved
      26
      27   Permission to use, copy, modify, and distribute this software and its
      28   documentation for any purpose and without fee is hereby granted,
      29   provided that the above copyright notice appear in all copies and that
      30   both that copyright notice and this permission notice appear in
      31   supporting documentation, and that the name of the author not be
      32   used in advertising or publicity pertaining to distribution of the
      33   software without specific, written prior permission.
      34
      35   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
      36   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
      37   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
      38   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
      39   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      40   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      41  ***************************************/
      42 #include <sys/socket.h>
      43 #include <netinet/in.h>
      44
      45 #include <sys/wait.h>
      46 #include <ctype.h>
      47
      48 #include <sys/types.h>
      49 #include <sys/stat.h>
      50
      51 #include "thread.h"
      52 #include "rxroutines.h"
      53 #include "socket.h"
      54 /*
      55 #include "objects.h"
      56 */
      57 #include "constants.h"
      58 #include "mysql_driver.h"
      59 #include "access_control.h"
      60 #include "ud.h"
      61 #include "server.h"
      62
      63 #include "rp.h"
      64 #include "memwrap.h"
      65
      66 #define RIPE_REG 17
      67
      68 /*+ String sizes +*/
      69 #define STR_S   63
      70 #define STR_M   255
      71 #define STR_L   1023
      72 #define STR_XL  4095
      73 #define STR_XXL 16383
      74
      75
      76 /* Storage for descriptors of the read side of the pipe */
      77 int sv_lockfd[MAX_LOCKS];
      78
      79 /* Listening sockets */
      80 int SV_whois_sock;
      81 int SV_config_sock;
      82 int SV_mirror_sock;
      83 int SV_update_sock;
      84
      85 /*+ Mutex lock.  Used for synchronizing changes. +*/
      86 pthread_mutex_t   Whois_thread_count_lock;
      87 pthread_mutex_t   Config_thread_count_lock;
      88 pthread_mutex_t   Mirror_thread_count_lock;
      89
      90 /*+ The number of threads. +*/
      91 int       Whois_thread_count;
      92 int       Config_thread_count;
      93 int       Mirror_thread_count;
      94
      95
      96 /*+ Server starting time +*/
      97 time_t SV_starttime;
      98
      99 /* pthread_mutex_t radix_initializing_lock; */
     100 /* XXX this is a workaround of a problem with mysql - it prevents the
     101 update/nrtm threads from starting before the radix tree is loaded.
     102
     103 Apparently, even LOCK TABLES doesn't prevent the program from locking up
     104 */
     105
     106 static void do_watchdog(void *arg);
     107
     108 /* Logging results */
     109 static void log_print(const char *arg) {
         /* [<][>][^][v][top][bottom][index][help] */
     110   FILE *logf;
     111
     112   if (CO_get_thread_logging() == 1) {
     113     if (strcmp(CO_get_thread_logfile(), "stdout") == 0) {
     114       printf(arg);
     115     }
     116     else {
     117       logf = fopen(CO_get_thread_logfile(), "a");
     118       fprintf(logf, arg);
     119       fclose(logf);
     120     }
     121   }
     122
     123 } /* log_print() */
     124
     125
     126 void radix_init(void){
         /* [<][>][^][v][top][bottom][index][help] */
     127   wr_log_set(0);
     128
     129   dieif( RP_init_trees( RIPE_REG ) != RP_OK );
     130   dieif( RP_sql_load_reg(RIPE_REG) != RP_OK );
     131 #if 0
     132   {
     133       er_path_t erlogstr;
     134
     135       erlogstr.fdes = stderr;
     136       erlogstr.asp  = 0xffffffff;
     137       erlogstr.fac  = FAC_RP; /* FAC_QI; */
     138       erlogstr.sev  = ER_SEV_D;
     139       erlogstr.mode = ER_M_SEVCHAR | ER_M_FACSYMB | ER_M_TEXTLONG;
     140
     141       ER_setpath(& erlogstr);
     142   }
     143 #endif
     144   wr_log_set(0); /* switch on/off the memory leak detector */
     145 /*  pthread_mutex_unlock( &radix_initializing_lock );  */
     146
     147   pthread_exit((void *)0);
     148 }
     149
     150 /* main_loop() */
     151 /*++++++++++++++++++++++++++++++++++++++
     152
     153   Waits for an incoming connection on the and spawns a new thread to handle it.
     154
     155   void *arg Pointer to a struct containing the socket to talk to the client and
     156             the function to call depending on the incoming connection.
     157
     158   More:
     159   +html+ <PRE>
     160   Author:
     161         ottrey
     162         joao
     163         andrei (do_server)
     164   +html+ </PRE>
     165   ++++++++++++++++++++++++++++++++++++++*/
     166 static void  *main_loop(void *arg) {
         /* [<][>][^][v][top][bottom][index][help] */
     167   th_args *args = (th_args *)arg;
     168   int connected_socket;
     169   int do_server;
     170
     171   while(do_server=CO_get_do_server()) {
     172
     173     connected_socket = SK_accept_connection(args->sock);
     174     if(connected_socket==-1) break;
     175
     176
     177     ER_dbg_va(FAC_TH, ASP_TH_NEW, "Starting a new thread");
     178
     179     /* Start a new thread. */
     180
     181
     182     TH_create((void *(*)(void *))(args->function), (void *)connected_socket);
     183 //
     184 //    pthread_attr_init(&attr);    /* initialize attr with default attributes */
     185 //    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
     186 //    pthread_create(&tid, &attr, (void *(*)(void *))(args->function), (void *)connected_socket);
     187   }
     188
     189    ER_dbg_va(FAC_TH, ASP_TH_NEW, "Exiting from the main loop");
     190
     191 } /* main_loop() */
     192
     193
     194 /* SV_start() */
     195 /*++++++++++++++++++++++++++++++++++++++
     196
     197   Start the server.
     198
     199   More:
     200   +html+ <PRE>
     201   Authors:
     202         ottrey
     203         joao
     204   +html+ </PRE>
     205   +html+ Starts up the server.
     206   +html+ <OL>
     207   +html+   <LI> Create sockets on the necessary ports (whois, config and mirror)
     208   +html+   <LI> Start new threads for each service.
     209   +html+ </OL>
     210   +html+ <A HREF=".DBrc">.properties</A>
     211
     212   ++++++++++++++++++++++++++++++++++++++*/
     213 void SV_start() {
         /* [<][>][^][v][top][bottom][index][help] */
     214   /* Make listening sockets global variables  */
     215   /*  int whois_sock,config_sock,mirror_sock,update_sock; */
     216   /* uint32_t whois_addr,sock_addr,mirror_addr; */
     217   int whois_port = -1;
     218   int config_port = -1;
     219   int mirror_port = -1;
     220   int update_port = -1;
     221   int update_mode;
     222   sigset_t sset;
     223   int fdes[2];
     224   struct timeval tval;
     225
     226   /* Store the starting time */
     227   gettimeofday(&tval, NULL);
     228   SV_starttime = tval.tv_sec;/* seconds since Jan. 1, 1970 */
     229
     230   /* Create interrupt pipe */
     231   /* Writing to this pipe will cause sleeping threads */
     232   /* to wake up */
     233   fprintf(stderr, "Creating an interrupt pipe\n");
     234   if(pipe(fdes)==-1) {
     235    printf("Cannot open interrupt pipe\n");
     236    exit(-1);
     237   }
     238   /* Save the pipe descriptors in sv_lock array */
     239   sv_lockfd[WLOCK_SHTDOWN]=fdes[0];
     240   sv_lockfd[LOCK_SHTDOWN]=fdes[1];
     241
     242
     243   /* Initialise the access control list. */
     244   AC_build();
     245   AC_acc_load();
     246   /* explicitly start the decay thread */
     247   TH_create((void *(*)(void *))AC_decay, NULL);
     248
     249   /* Initialise the radix tree (separate thread[s])
     250      already can allow socket connections, because the trees will
     251      be created locked, and will be unlocked when loaded */
     252
     253 /*   pthread_mutex_lock( &radix_initializing_lock );  */
     254   TH_create((void *(*)(void *))radix_init, NULL);
     255 /*  pthread_mutex_lock( &radix_initializing_lock );  */
     256
     257
     258   /* XXX I have no idea how this is working!! It's wrong! - ottrey 30/7/99 */
     259   /* Get port information for each service */
     260   whois_port = SK_atoport(CO_get_whois_port(), "tcp");
     261   printf("XXX htons(whois_port)=%d\n", htons(whois_port));
     262   if(whois_port == -1) {
     263     printf("Invalid service/port: %d\n", htons(whois_port));
     264     exit(-1);
     265   }
     266
     267   /* XXX I have no idea how this is working!! It's wrong! - ottrey 30/7/99 */
     268   config_port = SK_atoport(CO_get_config_port(), "tcp");
     269   printf("XXX htons(config_port)=%d\n", htons(config_port));
     270   if(config_port == -1) {
     271     printf("Invalid service/port: %d\n", htons(config_port));
     272     exit(-1);
     273   }
     274   mirror_port = SK_atoport(CO_get_mirror_port(), "tcp");
     275   printf("XXX htons(mirror_port)=%d\n", htons(mirror_port));
     276   if(mirror_port == -1) {
     277     printf("Invalid service/port: %d\n", mirror_port);
     278     exit(-1);
     279   }
     280
     281   /* XXX I have no idea how this is working!! It's wrong! - ottrey 30/7/99 */
     282   update_port = SK_atoport(CO_get_update_port(), "tcp");
     283   printf("XXX htons(update_port)=%d\n", htons(update_port));
     284   if(update_port == -1) {
     285     printf("Invalid service/port: %d\n", htons(update_port));
     286     exit(-1);
     287   }
     288
     289
     290
     291   /* 6. Create a socket on the necessary ports/addresses and bind to them. */
     292   /* whois socket */
     293   SV_whois_sock = SK_getsock(SOCK_STREAM, whois_port, INADDR_ANY);
     294 /* Currently binds to INADDR_ANY. Will need to get specific address */
     295 /*  SV_whois_sock = SK_getsock(SOCK_STREAM,whois_port,whois_addr); */
     296   /* config interface socket */
     297   SV_config_sock = SK_getsock(SOCK_STREAM, config_port, INADDR_ANY);
     298   /* nrt socket */
     299   SV_mirror_sock = SK_getsock(SOCK_STREAM,mirror_port,INADDR_ANY);
     300   /* update interface socket */
     301   SV_update_sock = SK_getsock(SOCK_STREAM, update_port, INADDR_ANY);
     302
     303
     304   /* Now.... accept() calls block until they get a connection
     305      so to listen on more than one port we need more
     306      than one thread */
     307
     308   /* Create master thread for whois threads */
     309    SV_concurrent_server(SV_whois_sock, SV_do_whois);
     310
     311   /* Create master thread for config threads */
     312    SV_concurrent_server(SV_config_sock, SV_do_config);
     313   /* Create master thread for mirror threads */
     314    SV_concurrent_server(SV_mirror_sock, SV_do_mirror);
     315
     316 /* Get the mode of operation of the update layer */
     317     update_mode=CO_get_update_mode();
     318     if(IS_UPDATE(update_mode)) {
     319     /* we will play with dbupdate */
     320     fprintf(stderr,"UPDATE mode\n");
     321      TH_create((void *(*)(void *))UD_do_updates, (void *)SV_update_sock);
     322     }
     323     else {
     324    /* start NRTM client */
     325     fprintf(stderr,"NRTM mode\n");
     326     TH_create((void *(*)(void *))UD_do_nrtm, NULL);
     327     }
     328
     329   /* XXX Is this needed? */
     330   pthread_exit(NULL);
     331
     332 } /* SV_start() */
     333
     334 /* SV_shutdown() */
     335 /*++++++++++++++++++++++++++++++++++++++
     336
     337   Shutdown the server.
     338
     339   More:
     340   +html+ <PRE>
     341   Authors:
     342         andrei
     343   +html+ </PRE>
     344   +html+ Stops the server.
     345   +html+ <OL>
     346   +html+   <LI> Close listening sockets (whois, config, mirror and updates)
     347   +html+   <LI> Stop all threads by triggering do_server variable.
     348   +html+ </OL>
     349   +html+ <A HREF=".DBrc">.properties</A>
     350
     351   ++++++++++++++++++++++++++++++++++++++*/
     352 void SV_shutdown() {
         /* [<][>][^][v][top][bottom][index][help] */
     353 char print_buf[STR_M];
     354
     355  sprintf(print_buf, "%d", 0);
     356  /* Stop updates */
     357  CO_set_const("UD.do_update", print_buf);
     358  /* Stop all servers */
     359  CO_set_const("SV.do_server", print_buf);
     360  sprintf(print_buf, "Stopping all servers\n");
     361  fprintf(stderr, print_buf);
     362  /*log_print(print_buf); */
     363  strcpy(print_buf, "");
     364
     365  /* Wake up all sleeping threads */
     366  fprintf(stderr, "Going to wake sleeping threads up\n");
     367  write(sv_lockfd[WLOCK_SHTDOWN], " ", 1);
     368
     369  /* CLose all listening sockets, so accept call exits */
     370  close(SV_whois_sock);
     371  close(SV_config_sock);
     372  close(SV_mirror_sock);
     373  close(SV_update_sock);
     374
     375
     376 } /* SV_shutdown() */
     377
     378
     379 /* SV_sleep() */
     380 /*++++++++++++++++++++++++++++++++++++++
     381
     382   Sleep and wake up on special events.
     383
     384   More:
     385   +html+ <PRE>
     386   Authors:
     387         andrei
     388   +html+ </PRE>
     389   +html+ Sleeps timeout but wakes up when an envent occures.
     390
     391   ++++++++++++++++++++++++++++++++++++++*/
     392 int SV_sleep(int lock, int sleeptime) {
         /* [<][>][^][v][top][bottom][index][help] */
     393 struct timeval timeout;
     394 struct stat st;
     395 fd_set set;
     396
     397  if (fstat(sv_lockfd[lock], &st) ==-1) {
     398   fprintf(stderr, "Error stat-ing the lock file\n");
     399   return(-1);
     400  }
     401
     402  timeout.tv_sec=sleeptime;
     403  timeout.tv_usec=0;
     404
     405  FD_ZERO(&set);
     406  FD_SET(sv_lockfd[lock], &set);
     407
     408  fprintf(stderr, "Going to sleep\n");
     409  select(sv_lockfd[lock]+1, &set, NULL, NULL, &timeout);
     410
     411  fprintf(stderr, "Select returned\n");
     412
     413  return(0);
     414 }
     415
     416 /*++++++++++++++++++++++++++++++++++++++
     417
     418   Handle signals.
     419
     420   Changes the flags:
     421         do_nrtm
     422         do_update
     423         do_whoisd
     424
     425   More:
     426   +html+ <PRE>
     427   Author:
     428         andrei
     429   +html+ </PRE>
     430   ++++++++++++++++++++++++++++++++++++++*/
     431 void *SV_signal_thread() {
         /* [<][>][^][v][top][bottom][index][help] */
     432 char print_buf[STR_M];
     433 sigset_t sset;
     434 int sigReceived;
     435 int do_update;
     436
     437         sigemptyset(&sset);
     438         sigaddset(&sset, SIGTERM);
     439         sigaddset(&sset, SIGINT);
     440         /* This is a bit confusing, but is needed */
     441         /* For more information on signal handling in */
     442         /* threads see for example "Multithreading Programming */
     443         /* Techniques" by Shashi Prasad, ISBN 0-07-912250-7, pp. 94-101 */
     444         pthread_sigmask(SIG_BLOCK, &sset, NULL);
     445         /*      fprintf(stderr, "Signal handler installed\n");*/
     446
     447         for(;;)
     448         {
     449          sigwait(&sset, &sigReceived);
     450          sprintf(print_buf, "Signal received [%d]\n", sigReceived);
     451          log_print(print_buf); strcpy(print_buf, "");
     452          /*      fprintf(stderr, "Signal received [%d]\n", sigReceived); */
     453          switch (sigReceived)
     454          {
     455            case SIGINT:
     456            /* SIGINT stops all servers */
     457                 SV_shutdown();
     458                 pthread_exit((void *)0);
     459                 break;
     460
     461            case SIGTERM:
     462            /* SIGTERM will switch the updates on and off */
     463                 do_update=CO_get_do_update();
     464                 if(do_update)do_update=0; else do_update=1;
     465                 sprintf(print_buf, "%d", do_update);
     466                 CO_set_const("UD.do_update", print_buf);
     467                 if(do_update)
     468                   sprintf(print_buf, "Starting updates\n");
     469                 else
     470                   sprintf(print_buf, "Stopping updates\n");
     471                 log_print(print_buf); strcpy(print_buf, "");
     472                 /*              fprintf(stderr, "Stopping updates (SIGTERM received)\n"); */
     473                 break;
     474          }
     475         }
     476 } /* SV_signal_thread() */
     477
     478 /* SV_concurrent_server() */
     479 /*++++++++++++++++++++++++++++++++++++++
     480
     481   This is the routine that creates the main threads.
     482
     483   int     sock        The socket to connect to.
     484   void *  do_function The function to call for each type of service
     485
     486   More:
     487   +html+ <PRE>
     488   Author:
     489         ottrey
     490         joao
     491   +html+ </PRE>
     492   ++++++++++++++++++++++++++++++++++++++*/
     493 void SV_concurrent_server(int sock, void *do_function(void *)) {
         /* [<][>][^][v][top][bottom][index][help] */
     494   th_args *args;
     495   pthread_t tid;
     496   pthread_attr_t attr;
     497
     498   dieif( wr_calloc((void **)&args,1,sizeof(th_args)) != UT_OK);
     499
     500   args->function=(void *)do_function;
     501   args->sock=sock;
     502
     503 /*  pthread_mutex_init(&Whois_thread_count_lock,NULL); */
     504
     505   /* Start a new thread. */
     506
     507   TH_create(main_loop, (void *)args);
     508
     509
     510     /* Start a new thread. */
     511 //  pthread_attr_init(&attr);     /* initialize attr with default attributes */
     512 //  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
     513 //  pthread_create(&tid, &attr, main_thread, (void *)args);
     514
     515 } /* TH_run() */
     516
     517 /* SV_do_whois() */
     518 /*++++++++++++++++++++++++++++++++++++++
     519
     520   Handle whois connections.
     521
     522   void *arg The socket to connect to. (It has to be passed in this way for this thread routine.)
     523
     524   More:
     525   +html+ <PRE>
     526   Author:
     527         joao
     528   +html+ </PRE>
     529   ++++++++++++++++++++++++++++++++++++++*/
     530 void *SV_do_whois(void *arg) {
         /* [<][>][^][v][top][bottom][index][help] */
     531   int sock = (int)arg;
     532
     533   ER_dbg_va(FAC_TH, ASP_TH_NEW,
     534             "Whois: Child thread [%d]: Socket number = %d",
     535             pthread_self(), sock);
     536
     537   /* Use a mutex to update the global whois thread counter. */
     538   pthread_mutex_lock(&Whois_thread_count_lock);
     539   Whois_thread_count++;
     540   ER_dbg_va(FAC_TH, ASP_TH_NEW,
     541             "Whois_thread_count++=%d", Whois_thread_count);
     542
     543   pthread_mutex_unlock(&Whois_thread_count_lock);
     544
     545   PW_interact(sock);
     546
     547   /* Use a mutex to update the global whois thread counter. */
     548   pthread_mutex_lock(&Whois_thread_count_lock);
     549   Whois_thread_count--;
     550   ER_dbg_va(FAC_TH, ASP_TH_NEW,
     551             "Whois_thread_count--=%d", Whois_thread_count);
     552   pthread_mutex_unlock(&Whois_thread_count_lock);
     553
     554   pthread_exit((void *)0);
     555
     556 } /* SV_do_whois() */
     557
     558 /* SV_do_mirror() */
     559 /*++++++++++++++++++++++++++++++++++++++
     560
     561   Handle NRTM connections.
     562
     563   void *arg The socket to connect to. (It has to be passed in this way for this thread routine.)
     564
     565   More:
     566   +html+ <PRE>
     567   Author:
     568         joao
     569   +html+ </PRE>
     570   ++++++++++++++++++++++++++++++++++++++*/
     571 void *SV_do_mirror(void *arg) {
         /* [<][>][^][v][top][bottom][index][help] */
     572   int sock = (int)arg;
     573   char print_buf[STR_M];
     574
     575   sprintf(print_buf, "NRTM: Child thread [%d]: Socket number = %d\n", pthread_self(), sock); log_print(print_buf); strcpy(print_buf, "");
     576
     577   /* Use a mutex to update the global mirror thread counter. */
     578   pthread_mutex_lock(&Mirror_thread_count_lock);
     579   Mirror_thread_count++;
     580   sprintf(print_buf, "Mirror_thread_count++=%d\n", Mirror_thread_count); log_print(print_buf); strcpy(print_buf, "");
     581   pthread_mutex_unlock(&Mirror_thread_count_lock);
     582
     583   PM_interact(sock);
     584
     585   /* Use a mutex to update the global mirror thread counter. */
     586   pthread_mutex_lock(&Mirror_thread_count_lock);
     587   Mirror_thread_count--;
     588   sprintf(print_buf, "Mirror_thread_count--=%d\n", Mirror_thread_count); log_print(print_buf); strcpy(print_buf, "");
     589   pthread_mutex_unlock(&Mirror_thread_count_lock);
     590
     591   pthread_exit((void *)0);
     592
     593 } /* SV_do_mirror() */
     594
     595 /* SV_do_config() */
     596 /*++++++++++++++++++++++++++++++++++++++
     597
     598   Handle config connections.
     599
     600   void *arg The socket to connect to. (It has to be passed in this way for this
     601 thread routine.)
     602
     603   More:
     604   +html+ <PRE>
     605   Author:
     606         joao
     607   +html+ </PRE>
     608   ++++++++++++++++++++++++++++++++++++++*/
     609 void *SV_do_config(void *arg) {
         /* [<][>][^][v][top][bottom][index][help] */
     610   int sock = (int)arg;
     611   char print_buf[STR_M];
     612
     613   sprintf(print_buf, "Config: Child thread [%d]: Socket number = %d\n", pthread_self(), sock); log_print(print_buf); strcpy(print_buf, "");
     614
     615 /*
     616   printf("Hi there, there is nothing to configure yet\nBye..... :-)\n");
     617   fflush(NULL);
     618
     619   SK_close(sock);
     620 */
     621   PC_interact(sock);
     622
     623   pthread_exit((void *)0);
     624
     625 } /* SV_do_config() */
     626
     627
     628 /*++++++++++++++++++++++++++++++++++++++
     629
     630   This is the routine that creates a watchdog thread.
     631
     632   The watchdog will cancel (pthread_cancel()) the calling thread in case the
     633   socket is closed by the client (its read-half is closed). The calling
     634   thread should make necessaruy preparations when calling the watchdog:
     635
     636   - the socket should be connected
     637   - cancellation points and cleanup routines should be defined
     638
     639   In case the connection is closed by the calling thread itself, the
     640   watchdog just exits and no action against the calling thread is performed.
     641
     642   wd_args - a pointer to wd_args_t structure containing
     643             data about socket and thread ID
     644
     645   More:
     646   +html+ <PRE>
     647   Author:
     648         ottrey
     649         joao
     650         andrei
     651   +html+ </PRE>
     652   ++++++++++++++++++++++++++++++++++++++*/
     653
     654 void SV_watchdog(wd_args_t *wd_args) {
         /* [<][>][^][v][top][bottom][index][help] */
     655  pthread_t tid;
     656  pthread_attr_t attr;
     657
     658  /* Start a new thread. */
     659  TH_create((void *(*)(void *))do_watchdog, (void *)wd_args);
     660
     661 // pthread_attr_init(&attr);     /* initialize attr with default attributes */
     662 // pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
     663 // pthread_create(&tid, &attr, (void *(*)(void *))do_watchdog, (void *)wd_args);
     664
     665 }
     666
     667
     668 /*++++++++++++++++++++++++++++++++++++++
     669
     670 The watchdog thread itself
     671
     672 The watchdog thread makes select() on the connected socket waiting until it
     673 becomes readable. If this happens as a result of some input, it'll simply
     674 dump it. Otherwise, this indicates that the client has closed the
     675 connection. In this case watchdog will cancel (pthread_cancel()) the whois
     676 thread (which in its turn will kill (mysql_kill()) mysql thread as part of
     677 its cleanup routine).
     678
     679 More:
     680 +html+ <PRE>
     681 Author:
     682       andrei
     683 +html+ </PRE>
     684 ++++++++++++++++++++++++++++++++++++++*/
     685 static void do_watchdog(void *arg) {
         /* [<][>][^][v][top][bottom][index][help] */
     686   wd_args_t *wd_args = (wd_args_t *)arg;
     687   int socket;
     688   pthread_t tid;
     689   int nready;
     690   int n;
     691   fd_set rset;
     692   char buff[STR_S];
     693
     694   socket = wd_args->connected_socket;
     695   tid = wd_args->tid;
     696
     697
     698   FD_ZERO(&rset);
     699   FD_SET(socket, &rset);
     700
     701   while ((nready=select(socket+1, &rset, NULL, NULL, NULL))!=-1) {
     702
     703    /* There was some input or client half of connection was closed */
     704    /* Check for the latter */
     705    if (( n=read(socket, buff, sizeof(buff))) == 0) {
     706    /* Connection was closed by client */
     707    /* Now send a cancellation request to the whois thread. */
     708    /* mysql thread will be terminated by thread cleanup routine */
     709
     710    /* The only possible error is ESRCH, so we do not care about */
     711    pthread_cancel(tid);
     712
     713    /* Exit the watchdog thread, passing NULL as we don't expect pthread_join() */
     714    pthread_exit(NULL);
     715    }
     716
     717    /* Otherwise dump input and continue */
     718   }
     719
     720   /* the only reason that we are here is that the socket has been */
     721   /* closed by the whois thread and not valid. Just exit the watchdog, */
     722   /* passing NULL as we don't expect pthread_join() */
     723    pthread_exit(NULL);
     724
     725 }

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