runservice.c (3940B)
1 /************************************************************************* 2 * This file is part of Crosroads 1.23, a load balancer and fail over 3 * utility for TCP. Copyright (c) Karel Kubat, distributed under GPL. 4 * Visit http://crossroads.e-tunity.com for information. 5 *************************************************************************/ 6 #include "crossroads.h" 7 8 void runservice () { 9 int pid; 10 int first_serving = 1; 11 12 msg ("Service %s (on port %d): STARTING", 13 activeservice->name, activeservice->port); 14 15 /* Allocate the shared mem segment. */ 16 alloc_reporter(activeservice, 1); 17 18 /* Load any allow- or deny filter files if appropriate. */ 19 if (ipf_loadfile (activeservice->allowfile, &(activeservice->allowchain), 20 &(activeservice->nallowchain))) 21 error ("Error in allow file"); 22 if (ipf_loadfile (activeservice->denyfile, &(activeservice->denychain), 23 &(activeservice->ndenychain))) 24 error ("Error in deny file"); 25 26 /* Go into the background. */ 27 if ( (pid = fork()) < 0 ) { 28 /* Fork failed */ 29 error ("Service %s: fork failure: %s", 30 activeservice->name, strerror(errno)); 31 } else if (pid) { 32 /* Parent branch */ 33 msg ("Service %s: detached as PID %d", 34 activeservice->name, pid); 35 return; 36 } 37 38 /* Child branch */ 39 set_program_title ("Service %s: listening", activeservice->name); 40 close (0); 41 close (1); 42 close (2); 43 daemonized++; 44 if ( (open ("/dev/null", O_RDONLY) < 0) || 45 (open ("/dev/null", O_WRONLY) < 0) || 46 (open ("/dev/null", O_WRONLY) < 0) ) 47 error ("Service %s: " 48 "failed to reopen stdin/out/err on /dev/null", 49 activeservice->name); 50 if (setsid() < 0) 51 error ("Service %s: failed to become seesion leader", 52 activeservice->name); 53 54 /* Promote verbosity. */ 55 flag_verbose = activeservice->verbosity; 56 57 /* We've forked for the first time */ 58 program_stage = stage_waiting; 59 60 /* In 'forever' mode, we create a server-side socket and ask tcpserve() 61 * to service it. tcpserve() will return to us if there are no back 62 * ends to service the request. In that case, we close the listening 63 * socket (so that new clients get denied), take a nap, and redo. 64 * Of course we only start listening if we have back ends at all... 65 */ 66 while (1) { 67 if (backend_count()) { 68 /* Create the socket, bind to port. */ 69 if ( (listen_sock = make_socket (activeservice->port, 70 activeservice->bind)) < 0 ) { 71 if (!sloppyportbind) 72 error ("Service %s: failed to listen to port %d: %s", 73 activeservice->name, activeservice->port, 74 strerror(errno)); 75 warning ("Service %s: " 76 "listening socket creation failed.. will retry", 77 activeservice->name); 78 79 /* We wait here for some time, to let the system regain 80 * equilibrium. Something's really afoot, so let's not retry 81 * right away. */ 82 sleep (SLEEP_TIME); 83 84 continue; 85 } 86 msg ("Service %s: server-side network socket: %d", 87 activeservice->name, listen_sock); 88 89 /* Zero out the stats for first usage. */ 90 if (first_serving) { 91 first_serving = 0; 92 memset (servicereport, 0, sizeof(Servicereport)); 93 /* Store our pid, so that 'crossroads stop' may kill us. */ 94 lock_reporter(); 95 servicereport->pid = getpid(); 96 unlock_reporter(); 97 } 98 99 /* Start serving the port! */ 100 tcpserve (listen_sock); 101 102 /* tcpserve() returned -- must be because this service is out 103 * of back ends */ 104 if (shutdown (listen_sock, SHUT_RDWR)) 105 error ("Service %s: " 106 "failed to shut down server-side socket %d: %s", 107 activeservice->name, listen_sock, strerror(errno)); 108 if (close (listen_sock)) 109 error ("Service %s: failed to close server-side socket %d: %s", 110 activeservice->name, listen_sock, strerror(errno)); 111 112 } 113 114 msg ("Service %s: taking a nap...", activeservice->name); 115 sleep (SLEEP_TIME); 116 } 117 }