2
0

server.c 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025
  1. /*
  2. * Portions created by SGI are Copyright (C) 2000 Silicon Graphics, Inc.
  3. * All Rights Reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of Silicon Graphics, Inc. nor the names of its
  15. * contributors may be used to endorse or promote products derived from
  16. * this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. * HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
  24. * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  25. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  26. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  27. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  28. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <unistd.h>
  34. #include <time.h>
  35. #include <sys/types.h>
  36. #include <sys/stat.h>
  37. #include <sys/socket.h>
  38. #include <sys/wait.h>
  39. #include <netinet/in.h>
  40. #include <arpa/inet.h>
  41. #include <netdb.h>
  42. #include <fcntl.h>
  43. #include <signal.h>
  44. #include <pwd.h>
  45. #include "st.h"
  46. /******************************************************************
  47. * Server configuration parameters
  48. */
  49. /* Log files */
  50. #define PID_FILE "pid"
  51. #define ERRORS_FILE "errors"
  52. #define ACCESS_FILE "access"
  53. /* Default server port */
  54. #define SERV_PORT_DEFAULT 8000
  55. /* Socket listen queue size */
  56. #define LISTENQ_SIZE_DEFAULT 256
  57. /* Max number of listening sockets ("hardware virtual servers") */
  58. #define MAX_BIND_ADDRS 16
  59. /* Max number of "spare" threads per process per socket */
  60. #define MAX_WAIT_THREADS_DEFAULT 8
  61. /* Number of file descriptors needed to handle one client session */
  62. #define FD_PER_THREAD 2
  63. /* Access log buffer flushing interval (in seconds) */
  64. #define ACCLOG_FLUSH_INTERVAL 30
  65. /* Request read timeout (in seconds) */
  66. #define REQUEST_TIMEOUT 30
  67. /******************************************************************
  68. * Global data
  69. */
  70. struct socket_info {
  71. st_netfd_t nfd; /* Listening socket */
  72. char *addr; /* Bind address */
  73. unsigned int port; /* Port */
  74. int wait_threads; /* Number of threads waiting to accept */
  75. int busy_threads; /* Number of threads processing request */
  76. int rqst_count; /* Total number of processed requests */
  77. } srv_socket[MAX_BIND_ADDRS]; /* Array of listening sockets */
  78. static int sk_count = 0; /* Number of listening sockets */
  79. static int vp_count = 0; /* Number of server processes (VPs) */
  80. static pid_t *vp_pids; /* Array of VP pids */
  81. static int my_index = -1; /* Current process index */
  82. static pid_t my_pid = -1; /* Current process pid */
  83. static st_netfd_t sig_pipe[2]; /* Signal pipe */
  84. /*
  85. * Configuration flags/parameters
  86. */
  87. static int interactive_mode = 0;
  88. static int serialize_accept = 0;
  89. static int log_access = 0;
  90. static char *logdir = NULL;
  91. static char *username = NULL;
  92. static int listenq_size = LISTENQ_SIZE_DEFAULT;
  93. static int errfd = STDERR_FILENO;
  94. /*
  95. * Thread throttling parameters (all numbers are per listening socket).
  96. * Zero values mean use default.
  97. */
  98. static int max_threads = 0; /* Max number of threads */
  99. static int max_wait_threads = 0; /* Max number of "spare" threads */
  100. static int min_wait_threads = 2; /* Min number of "spare" threads */
  101. /******************************************************************
  102. * Useful macros
  103. */
  104. #ifndef INADDR_NONE
  105. #define INADDR_NONE 0xffffffff
  106. #endif
  107. #define SEC2USEC(s) ((s)*1000000LL)
  108. #define WAIT_THREADS(i) (srv_socket[i].wait_threads)
  109. #define BUSY_THREADS(i) (srv_socket[i].busy_threads)
  110. #define TOTAL_THREADS(i) (WAIT_THREADS(i) + BUSY_THREADS(i))
  111. #define RQST_COUNT(i) (srv_socket[i].rqst_count)
  112. /******************************************************************
  113. * Forward declarations
  114. */
  115. static void usage(const char *progname);
  116. static void parse_arguments(int argc, char *argv[]);
  117. static void start_daemon(void);
  118. static void set_thread_throttling(void);
  119. static void create_listeners(void);
  120. static void change_user(void);
  121. static void open_log_files(void);
  122. static void start_processes(void);
  123. static void wdog_sighandler(int signo);
  124. static void child_sighandler(int signo);
  125. static void install_sighandlers(void);
  126. static void start_threads(void);
  127. static void *process_signals(void *arg);
  128. static void *flush_acclog_buffer(void *arg);
  129. static void *handle_connections(void *arg);
  130. static void dump_server_info(void);
  131. static void Signal(int sig, void (*handler)(int));
  132. static int cpu_count(void);
  133. extern void handle_session(long srv_socket_index, st_netfd_t cli_nfd);
  134. extern void load_configs(void);
  135. extern void logbuf_open(void);
  136. extern void logbuf_flush(void);
  137. extern void logbuf_close(void);
  138. /* Error reporting functions defined in the error.c file */
  139. extern void err_sys_report(int fd, const char *fmt, ...);
  140. extern void err_sys_quit(int fd, const char *fmt, ...);
  141. extern void err_sys_dump(int fd, const char *fmt, ...);
  142. extern void err_report(int fd, const char *fmt, ...);
  143. extern void err_quit(int fd, const char *fmt, ...);
  144. /*
  145. * General server example: accept a client connection and do something.
  146. * This program just outputs a short HTML page, but can be easily adapted
  147. * to do other things.
  148. *
  149. * This server creates a constant number of processes ("virtual processors"
  150. * or VPs) and replaces them when they die. Each virtual processor manages
  151. * its own independent set of state threads (STs), the number of which varies
  152. * with load against the server. Each state thread listens to exactly one
  153. * listening socket. The initial process becomes the watchdog, waiting for
  154. * children (VPs) to die or for a signal requesting termination or restart.
  155. * Upon receiving a restart signal (SIGHUP), all VPs close and then reopen
  156. * log files and reload configuration. All currently active connections remain
  157. * active. It is assumed that new configuration affects only request
  158. * processing and not the general server parameters such as number of VPs,
  159. * thread limits, bind addresses, etc. Those are specified as command line
  160. * arguments, so the server has to be stopped and then started again in order
  161. * to change them.
  162. *
  163. * Each state thread loops processing connections from a single listening
  164. * socket. Only one ST runs on a VP at a time, and VPs do not share memory,
  165. * so no mutual exclusion locking is necessary on any data, and the entire
  166. * server is free to use all the static variables and non-reentrant library
  167. * functions it wants, greatly simplifying programming and debugging and
  168. * increasing performance (for example, it is safe to ++ and -- all global
  169. * counters or call inet_ntoa(3) without any mutexes). The current thread on
  170. * each VP maintains equilibrium on that VP, starting a new thread or
  171. * terminating itself if the number of spare threads exceeds the lower or
  172. * upper limit.
  173. *
  174. * All I/O operations on sockets must use the State Thread library's I/O
  175. * functions because only those functions prevent blocking of the entire VP
  176. * process and perform state thread scheduling.
  177. */
  178. int main(int argc, char *argv[])
  179. {
  180. /* Parse command-line options */
  181. parse_arguments(argc, argv);
  182. /* Allocate array of server pids */
  183. if ((vp_pids = calloc(vp_count, sizeof(pid_t))) == NULL)
  184. err_sys_quit(errfd, "ERROR: calloc failed");
  185. /* Start the daemon */
  186. if (!interactive_mode)
  187. start_daemon();
  188. /* Initialize the ST library */
  189. if (st_init() < 0)
  190. err_sys_quit(errfd, "ERROR: initialization failed: st_init");
  191. /* Set thread throttling parameters */
  192. set_thread_throttling();
  193. /* Create listening sockets */
  194. create_listeners();
  195. /* Change the user */
  196. if (username)
  197. change_user();
  198. /* Open log files */
  199. open_log_files();
  200. /* Start server processes (VPs) */
  201. start_processes();
  202. /* Turn time caching on */
  203. st_timecache_set(1);
  204. /* Install signal handlers */
  205. install_sighandlers();
  206. /* Load configuration from config files */
  207. load_configs();
  208. /* Start all threads */
  209. start_threads();
  210. /* Become a signal processing thread */
  211. process_signals(NULL);
  212. /* NOTREACHED */
  213. return 1;
  214. }
  215. /******************************************************************/
  216. static void usage(const char *progname)
  217. {
  218. fprintf(stderr, "Usage: %s -l <log_directory> [<options>]\n\n"
  219. "Possible options:\n\n"
  220. "\t-b <host>:<port> Bind to specified address. Multiple"
  221. " addresses\n"
  222. "\t are permitted.\n"
  223. "\t-p <num_processes> Create specified number of processes.\n"
  224. "\t-t <min_thr>:<max_thr> Specify thread limits per listening"
  225. " socket\n"
  226. "\t across all processes.\n"
  227. "\t-u <user> Change server's user id to specified"
  228. " value.\n"
  229. "\t-q <backlog> Set max length of pending connections"
  230. " queue.\n"
  231. "\t-a Enable access logging.\n"
  232. "\t-i Run in interactive mode.\n"
  233. "\t-S Serialize all accept() calls.\n"
  234. "\t-h Print this message.\n",
  235. progname);
  236. exit(1);
  237. }
  238. /******************************************************************/
  239. static void parse_arguments(int argc, char *argv[])
  240. {
  241. extern char *optarg;
  242. int opt;
  243. char *c;
  244. while ((opt = getopt(argc, argv, "b:p:l:t:u:q:aiSh")) != EOF) {
  245. switch (opt) {
  246. case 'b':
  247. if (sk_count >= MAX_BIND_ADDRS)
  248. err_quit(errfd, "ERROR: max number of bind addresses (%d) exceeded",
  249. MAX_BIND_ADDRS);
  250. if ((c = strdup(optarg)) == NULL)
  251. err_sys_quit(errfd, "ERROR: strdup");
  252. srv_socket[sk_count++].addr = c;
  253. break;
  254. case 'p':
  255. vp_count = atoi(optarg);
  256. if (vp_count < 1)
  257. err_quit(errfd, "ERROR: invalid number of processes: %s", optarg);
  258. break;
  259. case 'l':
  260. logdir = optarg;
  261. break;
  262. case 't':
  263. max_wait_threads = (int) strtol(optarg, &c, 10);
  264. if (*c++ == ':')
  265. max_threads = atoi(c);
  266. if (max_wait_threads < 0 || max_threads < 0)
  267. err_quit(errfd, "ERROR: invalid number of threads: %s", optarg);
  268. break;
  269. case 'u':
  270. username = optarg;
  271. break;
  272. case 'q':
  273. listenq_size = atoi(optarg);
  274. if (listenq_size < 1)
  275. err_quit(errfd, "ERROR: invalid listen queue size: %s", optarg);
  276. break;
  277. case 'a':
  278. log_access = 1;
  279. break;
  280. case 'i':
  281. interactive_mode = 1;
  282. break;
  283. case 'S':
  284. /*
  285. * Serialization decision is tricky on some platforms. For example,
  286. * Solaris 2.6 and above has kernel sockets implementation, so supposedly
  287. * there is no need for serialization. The ST library may be compiled
  288. * on one OS version, but used on another, so the need for serialization
  289. * should be determined at run time by the application. Since it's just
  290. * an example, the serialization decision is left up to user.
  291. * Only on platforms where the serialization is never needed on any OS
  292. * version st_netfd_serialize_accept() is a no-op.
  293. */
  294. serialize_accept = 1;
  295. break;
  296. case 'h':
  297. case '?':
  298. usage(argv[0]);
  299. }
  300. }
  301. if (logdir == NULL && !interactive_mode) {
  302. err_report(errfd, "ERROR: logging directory is required\n");
  303. usage(argv[0]);
  304. }
  305. if (getuid() == 0 && username == NULL)
  306. err_report(errfd, "WARNING: running as super-user!");
  307. if (vp_count == 0 && (vp_count = cpu_count()) < 1)
  308. vp_count = 1;
  309. if (sk_count == 0) {
  310. sk_count = 1;
  311. srv_socket[0].addr = "0.0.0.0";
  312. }
  313. }
  314. /******************************************************************/
  315. static void start_daemon(void)
  316. {
  317. pid_t pid;
  318. /* Start forking */
  319. if ((pid = fork()) < 0)
  320. err_sys_quit(errfd, "ERROR: fork");
  321. if (pid > 0)
  322. exit(0); /* parent */
  323. /* First child process */
  324. setsid(); /* become session leader */
  325. if ((pid = fork()) < 0)
  326. err_sys_quit(errfd, "ERROR: fork");
  327. if (pid > 0) /* first child */
  328. exit(0);
  329. umask(022);
  330. if (chdir(logdir) < 0)
  331. err_sys_quit(errfd, "ERROR: can't change directory to %s: chdir", logdir);
  332. }
  333. /******************************************************************
  334. * For simplicity, the minimal size of thread pool is considered
  335. * as a maximum number of spare threads (max_wait_threads) that
  336. * will be created upon server startup. The pool size can grow up
  337. * to the max_threads value. Note that this is a per listening
  338. * socket limit. It is also possible to limit the total number of
  339. * threads for all sockets rather than impose a per socket limit.
  340. */
  341. static void set_thread_throttling(void)
  342. {
  343. /*
  344. * Calculate total values across all processes.
  345. * All numbers are per listening socket.
  346. */
  347. if (max_wait_threads == 0)
  348. max_wait_threads = MAX_WAIT_THREADS_DEFAULT * vp_count;
  349. /* Assuming that each client session needs FD_PER_THREAD file descriptors */
  350. if (max_threads == 0)
  351. max_threads = (st_getfdlimit() * vp_count) / FD_PER_THREAD / sk_count;
  352. if (max_wait_threads > max_threads)
  353. max_wait_threads = max_threads;
  354. /*
  355. * Now calculate per-process values.
  356. */
  357. if (max_wait_threads % vp_count)
  358. max_wait_threads = max_wait_threads / vp_count + 1;
  359. else
  360. max_wait_threads = max_wait_threads / vp_count;
  361. if (max_threads % vp_count)
  362. max_threads = max_threads / vp_count + 1;
  363. else
  364. max_threads = max_threads / vp_count;
  365. if (min_wait_threads > max_wait_threads)
  366. min_wait_threads = max_wait_threads;
  367. }
  368. /******************************************************************/
  369. static void create_listeners(void)
  370. {
  371. int i, n, sock;
  372. char *c;
  373. struct sockaddr_in serv_addr;
  374. struct hostent *hp;
  375. unsigned short port;
  376. for (i = 0; i < sk_count; i++) {
  377. port = 0;
  378. if ((c = strchr(srv_socket[i].addr, ':')) != NULL) {
  379. *c++ = '\0';
  380. port = (unsigned short) atoi(c);
  381. }
  382. if (srv_socket[i].addr[0] == '\0')
  383. srv_socket[i].addr = "0.0.0.0";
  384. if (port == 0)
  385. port = SERV_PORT_DEFAULT;
  386. /* Create server socket */
  387. if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0)
  388. err_sys_quit(errfd, "ERROR: can't create socket: socket");
  389. n = 1;
  390. if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&n, sizeof(n)) < 0)
  391. err_sys_quit(errfd, "ERROR: can't set SO_REUSEADDR: setsockopt");
  392. memset(&serv_addr, 0, sizeof(serv_addr));
  393. serv_addr.sin_family = AF_INET;
  394. serv_addr.sin_port = htons(port);
  395. serv_addr.sin_addr.s_addr = inet_addr(srv_socket[i].addr);
  396. if (serv_addr.sin_addr.s_addr == INADDR_NONE) {
  397. /* not dotted-decimal */
  398. if ((hp = gethostbyname(srv_socket[i].addr)) == NULL)
  399. err_quit(errfd, "ERROR: can't resolve address: %s",
  400. srv_socket[i].addr);
  401. memcpy(&serv_addr.sin_addr, hp->h_addr, hp->h_length);
  402. }
  403. srv_socket[i].port = port;
  404. /* Do bind and listen */
  405. if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
  406. err_sys_quit(errfd, "ERROR: can't bind to address %s, port %hu",
  407. srv_socket[i].addr, port);
  408. if (listen(sock, listenq_size) < 0)
  409. err_sys_quit(errfd, "ERROR: listen");
  410. /* Create file descriptor object from OS socket */
  411. if ((srv_socket[i].nfd = st_netfd_open_socket(sock)) == NULL)
  412. err_sys_quit(errfd, "ERROR: st_netfd_open_socket");
  413. /*
  414. * On some platforms (e.g. IRIX, Linux) accept() serialization is never
  415. * needed for any OS version. In that case st_netfd_serialize_accept()
  416. * is just a no-op. Also see the comment above.
  417. */
  418. if (serialize_accept && st_netfd_serialize_accept(srv_socket[i].nfd) < 0)
  419. err_sys_quit(errfd, "ERROR: st_netfd_serialize_accept");
  420. }
  421. }
  422. /******************************************************************/
  423. static void change_user(void)
  424. {
  425. struct passwd *pw;
  426. if ((pw = getpwnam(username)) == NULL)
  427. err_quit(errfd, "ERROR: can't find user '%s': getpwnam failed", username);
  428. if (setgid(pw->pw_gid) < 0)
  429. err_sys_quit(errfd, "ERROR: can't change group id: setgid");
  430. if (setuid(pw->pw_uid) < 0)
  431. err_sys_quit(errfd, "ERROR: can't change user id: setuid");
  432. err_report(errfd, "INFO: changed process user id to '%s'", username);
  433. }
  434. /******************************************************************/
  435. static void open_log_files(void)
  436. {
  437. int fd;
  438. char str[32];
  439. if (interactive_mode)
  440. return;
  441. /* Open access log */
  442. if (log_access)
  443. logbuf_open();
  444. /* Open and write pid to pid file */
  445. if ((fd = open(PID_FILE, O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0)
  446. err_sys_quit(errfd, "ERROR: can't open pid file: open");
  447. sprintf(str, "%d\n", (int)getpid());
  448. if (write(fd, str, strlen(str)) != strlen(str))
  449. err_sys_quit(errfd, "ERROR: can't write to pid file: write");
  450. close(fd);
  451. /* Open error log file */
  452. if ((fd = open(ERRORS_FILE, O_CREAT | O_WRONLY | O_APPEND, 0644)) < 0)
  453. err_sys_quit(errfd, "ERROR: can't open error log file: open");
  454. errfd = fd;
  455. err_report(errfd, "INFO: starting the server...");
  456. }
  457. /******************************************************************/
  458. static void start_processes(void)
  459. {
  460. int i, status;
  461. pid_t pid;
  462. sigset_t mask, omask;
  463. if (interactive_mode) {
  464. my_index = 0;
  465. my_pid = getpid();
  466. return;
  467. }
  468. for (i = 0; i < vp_count; i++) {
  469. if ((pid = fork()) < 0) {
  470. err_sys_report(errfd, "ERROR: can't create process: fork");
  471. if (i == 0)
  472. exit(1);
  473. err_report(errfd, "WARN: started only %d processes out of %d", i,
  474. vp_count);
  475. vp_count = i;
  476. break;
  477. }
  478. if (pid == 0) {
  479. my_index = i;
  480. my_pid = getpid();
  481. /* Child returns to continue in main() */
  482. return;
  483. }
  484. vp_pids[i] = pid;
  485. }
  486. /*
  487. * Parent process becomes a "watchdog" and never returns to main().
  488. */
  489. /* Install signal handlers */
  490. Signal(SIGTERM, wdog_sighandler); /* terminate */
  491. Signal(SIGHUP, wdog_sighandler); /* restart */
  492. Signal(SIGUSR1, wdog_sighandler); /* dump info */
  493. /* Now go to sleep waiting for a child termination or a signal */
  494. for ( ; ; ) {
  495. if ((pid = wait(&status)) < 0) {
  496. if (errno == EINTR)
  497. continue;
  498. err_sys_quit(errfd, "ERROR: watchdog: wait");
  499. }
  500. /* Find index of the exited child */
  501. for (i = 0; i < vp_count; i++) {
  502. if (vp_pids[i] == pid)
  503. break;
  504. }
  505. /* Block signals while printing and forking */
  506. sigemptyset(&mask);
  507. sigaddset(&mask, SIGTERM);
  508. sigaddset(&mask, SIGHUP);
  509. sigaddset(&mask, SIGUSR1);
  510. sigprocmask(SIG_BLOCK, &mask, &omask);
  511. if (WIFEXITED(status))
  512. err_report(errfd, "WARN: watchdog: process %d (pid %d) exited"
  513. " with status %d", i, pid, WEXITSTATUS(status));
  514. else if (WIFSIGNALED(status))
  515. err_report(errfd, "WARN: watchdog: process %d (pid %d) terminated"
  516. " by signal %d", i, pid, WTERMSIG(status));
  517. else if (WIFSTOPPED(status))
  518. err_report(errfd, "WARN: watchdog: process %d (pid %d) stopped"
  519. " by signal %d", i, pid, WSTOPSIG(status));
  520. else
  521. err_report(errfd, "WARN: watchdog: process %d (pid %d) terminated:"
  522. " unknown termination reason", i, pid);
  523. /* Fork another VP */
  524. if ((pid = fork()) < 0) {
  525. err_sys_report(errfd, "ERROR: watchdog: can't create process: fork");
  526. } else if (pid == 0) {
  527. my_index = i;
  528. my_pid = getpid();
  529. /* Child returns to continue in main() */
  530. return;
  531. }
  532. vp_pids[i] = pid;
  533. /* Restore the signal mask */
  534. sigprocmask(SIG_SETMASK, &omask, NULL);
  535. }
  536. }
  537. /******************************************************************/
  538. static void wdog_sighandler(int signo)
  539. {
  540. int i, err;
  541. /* Save errno */
  542. err = errno;
  543. /* Forward the signal to all children */
  544. for (i = 0; i < vp_count; i++) {
  545. if (vp_pids[i] > 0)
  546. kill(vp_pids[i], signo);
  547. }
  548. /*
  549. * It is safe to do pretty much everything here because process is
  550. * sleeping in wait() which is async-safe.
  551. */
  552. switch (signo) {
  553. case SIGHUP:
  554. err_report(errfd, "INFO: watchdog: caught SIGHUP");
  555. /* Reopen log files - needed for log rotation */
  556. if (log_access) {
  557. logbuf_close();
  558. logbuf_open();
  559. }
  560. close(errfd);
  561. if ((errfd = open(ERRORS_FILE, O_CREAT | O_WRONLY | O_APPEND, 0644)) < 0)
  562. err_sys_quit(STDERR_FILENO, "ERROR: watchdog: open");
  563. break;
  564. case SIGTERM:
  565. /* Non-graceful termination */
  566. err_report(errfd, "INFO: watchdog: caught SIGTERM, terminating");
  567. unlink(PID_FILE);
  568. exit(0);
  569. case SIGUSR1:
  570. err_report(errfd, "INFO: watchdog: caught SIGUSR1");
  571. break;
  572. default:
  573. err_report(errfd, "INFO: watchdog: caught signal %d", signo);
  574. }
  575. /* Restore errno */
  576. errno = err;
  577. }
  578. /******************************************************************/
  579. static void install_sighandlers(void)
  580. {
  581. sigset_t mask;
  582. int p[2];
  583. /* Create signal pipe */
  584. if (pipe(p) < 0)
  585. err_sys_quit(errfd, "ERROR: process %d (pid %d): can't create"
  586. " signal pipe: pipe", my_index, my_pid);
  587. if ((sig_pipe[0] = st_netfd_open(p[0])) == NULL ||
  588. (sig_pipe[1] = st_netfd_open(p[1])) == NULL)
  589. err_sys_quit(errfd, "ERROR: process %d (pid %d): can't create"
  590. " signal pipe: st_netfd_open", my_index, my_pid);
  591. /* Install signal handlers */
  592. Signal(SIGTERM, child_sighandler); /* terminate */
  593. Signal(SIGHUP, child_sighandler); /* restart */
  594. Signal(SIGUSR1, child_sighandler); /* dump info */
  595. /* Unblock signals */
  596. sigemptyset(&mask);
  597. sigaddset(&mask, SIGTERM);
  598. sigaddset(&mask, SIGHUP);
  599. sigaddset(&mask, SIGUSR1);
  600. sigprocmask(SIG_UNBLOCK, &mask, NULL);
  601. }
  602. /******************************************************************/
  603. static void child_sighandler(int signo)
  604. {
  605. int err, fd;
  606. err = errno;
  607. fd = st_netfd_fileno(sig_pipe[1]);
  608. /* write() is async-safe */
  609. if (write(fd, &signo, sizeof(int)) != sizeof(int))
  610. err_sys_quit(errfd, "ERROR: process %d (pid %d): child's signal"
  611. " handler: write", my_index, my_pid);
  612. errno = err;
  613. }
  614. /******************************************************************
  615. * The "main" function of the signal processing thread.
  616. */
  617. /* ARGSUSED */
  618. static void *process_signals(void *arg)
  619. {
  620. int signo;
  621. for ( ; ; ) {
  622. /* Read the next signal from the signal pipe */
  623. if (st_read(sig_pipe[0], &signo, sizeof(int),
  624. ST_UTIME_NO_TIMEOUT) != sizeof(int))
  625. err_sys_quit(errfd, "ERROR: process %d (pid %d): signal processor:"
  626. " st_read", my_index, my_pid);
  627. switch (signo) {
  628. case SIGHUP:
  629. err_report(errfd, "INFO: process %d (pid %d): caught SIGHUP,"
  630. " reloading configuration", my_index, my_pid);
  631. if (interactive_mode) {
  632. load_configs();
  633. break;
  634. }
  635. /* Reopen log files - needed for log rotation */
  636. if (log_access) {
  637. logbuf_flush();
  638. logbuf_close();
  639. logbuf_open();
  640. }
  641. close(errfd);
  642. if ((errfd = open(ERRORS_FILE, O_CREAT | O_WRONLY | O_APPEND, 0644)) < 0)
  643. err_sys_quit(STDERR_FILENO, "ERROR: process %d (pid %d): signal"
  644. " processor: open", my_index, my_pid);
  645. /* Reload configuration */
  646. load_configs();
  647. break;
  648. case SIGTERM:
  649. /*
  650. * Terminate ungracefully since it is generally not known how long
  651. * it will take to gracefully complete all client sessions.
  652. */
  653. err_report(errfd, "INFO: process %d (pid %d): caught SIGTERM,"
  654. " terminating", my_index, my_pid);
  655. if (log_access)
  656. logbuf_flush();
  657. exit(0);
  658. case SIGUSR1:
  659. err_report(errfd, "INFO: process %d (pid %d): caught SIGUSR1",
  660. my_index, my_pid);
  661. /* Print server info to stderr */
  662. dump_server_info();
  663. break;
  664. default:
  665. err_report(errfd, "INFO: process %d (pid %d): caught signal %d",
  666. my_index, my_pid, signo);
  667. }
  668. }
  669. /* NOTREACHED */
  670. return NULL;
  671. }
  672. /******************************************************************
  673. * The "main" function of the access log flushing thread.
  674. */
  675. /* ARGSUSED */
  676. static void *flush_acclog_buffer(void *arg)
  677. {
  678. for ( ; ; ) {
  679. st_sleep(ACCLOG_FLUSH_INTERVAL);
  680. logbuf_flush();
  681. }
  682. /* NOTREACHED */
  683. return NULL;
  684. }
  685. /******************************************************************/
  686. static void start_threads(void)
  687. {
  688. long i, n;
  689. /* Create access log flushing thread */
  690. if (log_access && st_thread_create(flush_acclog_buffer, NULL, 0, 0) == NULL)
  691. err_sys_quit(errfd, "ERROR: process %d (pid %d): can't create"
  692. " log flushing thread", my_index, my_pid);
  693. /* Create connections handling threads */
  694. for (i = 0; i < sk_count; i++) {
  695. err_report(errfd, "INFO: process %d (pid %d): starting %d threads"
  696. " on %s:%u", my_index, my_pid, max_wait_threads,
  697. srv_socket[i].addr, srv_socket[i].port);
  698. WAIT_THREADS(i) = 0;
  699. BUSY_THREADS(i) = 0;
  700. RQST_COUNT(i) = 0;
  701. for (n = 0; n < max_wait_threads; n++) {
  702. if (st_thread_create(handle_connections, (void *)i, 0, 0) != NULL)
  703. WAIT_THREADS(i)++;
  704. else
  705. err_sys_report(errfd, "ERROR: process %d (pid %d): can't create"
  706. " thread", my_index, my_pid);
  707. }
  708. if (WAIT_THREADS(i) == 0)
  709. exit(1);
  710. }
  711. }
  712. /******************************************************************/
  713. static void *handle_connections(void *arg)
  714. {
  715. st_netfd_t srv_nfd, cli_nfd;
  716. struct sockaddr_in from;
  717. int fromlen;
  718. long i = (long) arg;
  719. srv_nfd = srv_socket[i].nfd;
  720. fromlen = sizeof(from);
  721. while (WAIT_THREADS(i) <= max_wait_threads) {
  722. cli_nfd = st_accept(srv_nfd, (struct sockaddr *)&from, &fromlen,
  723. ST_UTIME_NO_TIMEOUT);
  724. if (cli_nfd == NULL) {
  725. err_sys_report(errfd, "ERROR: can't accept connection: st_accept");
  726. continue;
  727. }
  728. /* Save peer address, so we can retrieve it later */
  729. st_netfd_setspecific(cli_nfd, &from.sin_addr, NULL);
  730. WAIT_THREADS(i)--;
  731. BUSY_THREADS(i)++;
  732. if (WAIT_THREADS(i) < min_wait_threads && TOTAL_THREADS(i) < max_threads) {
  733. /* Create another spare thread */
  734. if (st_thread_create(handle_connections, (void *)i, 0, 0) != NULL)
  735. WAIT_THREADS(i)++;
  736. else
  737. err_sys_report(errfd, "ERROR: process %d (pid %d): can't create"
  738. " thread", my_index, my_pid);
  739. }
  740. handle_session(i, cli_nfd);
  741. st_netfd_close(cli_nfd);
  742. WAIT_THREADS(i)++;
  743. BUSY_THREADS(i)--;
  744. }
  745. WAIT_THREADS(i)--;
  746. return NULL;
  747. }
  748. /******************************************************************/
  749. static void dump_server_info(void)
  750. {
  751. char *buf;
  752. int i, len;
  753. if ((buf = malloc(sk_count * 512)) == NULL) {
  754. err_sys_report(errfd, "ERROR: malloc failed");
  755. return;
  756. }
  757. len = sprintf(buf, "\n\nProcess #%d (pid %d):\n", my_index, (int)my_pid);
  758. for (i = 0; i < sk_count; i++) {
  759. len += sprintf(buf + len, "\nListening Socket #%d:\n"
  760. "-------------------------\n"
  761. "Address %s:%u\n"
  762. "Thread limits (min/max) %d/%d\n"
  763. "Waiting threads %d\n"
  764. "Busy threads %d\n"
  765. "Requests served %d\n",
  766. i, srv_socket[i].addr, srv_socket[i].port,
  767. max_wait_threads, max_threads,
  768. WAIT_THREADS(i), BUSY_THREADS(i), RQST_COUNT(i));
  769. }
  770. write(STDERR_FILENO, buf, len);
  771. free(buf);
  772. }
  773. /******************************************************************
  774. * Stubs
  775. */
  776. /*
  777. * Session handling function stub. Just dumps small HTML page.
  778. */
  779. void handle_session(long srv_socket_index, st_netfd_t cli_nfd)
  780. {
  781. static char resp[] = "HTTP/1.0 200 OK\r\nContent-type: text/html\r\n"
  782. "Connection: close\r\n\r\n<H2>It worked!</H2>\n";
  783. char buf[512];
  784. int n = sizeof(resp) - 1;
  785. struct in_addr *from = st_netfd_getspecific(cli_nfd);
  786. if (st_read(cli_nfd, buf, sizeof(buf), SEC2USEC(REQUEST_TIMEOUT)) < 0) {
  787. err_sys_report(errfd, "WARN: can't read request from %s: st_read",
  788. inet_ntoa(*from));
  789. return;
  790. }
  791. if (st_write(cli_nfd, resp, n, ST_UTIME_NO_TIMEOUT) != n) {
  792. err_sys_report(errfd, "WARN: can't write response to %s: st_write",
  793. inet_ntoa(*from));
  794. return;
  795. }
  796. RQST_COUNT(srv_socket_index)++;
  797. }
  798. /*
  799. * Configuration loading function stub.
  800. */
  801. void load_configs(void)
  802. {
  803. err_report(errfd, "INFO: process %d (pid %d): configuration loaded",
  804. my_index, my_pid);
  805. }
  806. /*
  807. * Buffered access logging methods.
  808. * Note that stdio functions (fopen(3), fprintf(3), fflush(3), etc.) cannot
  809. * be used if multiple VPs are created since these functions can flush buffer
  810. * at any point and thus write only partial log record to disk.
  811. * Also, it is completely safe for all threads of the same VP to write to
  812. * the same log buffer without any mutex protection (one buffer per VP, of
  813. * course).
  814. */
  815. void logbuf_open(void)
  816. {
  817. }
  818. void logbuf_flush(void)
  819. {
  820. }
  821. void logbuf_close(void)
  822. {
  823. }
  824. /******************************************************************
  825. * Small utility functions
  826. */
  827. static void Signal(int sig, void (*handler)(int))
  828. {
  829. struct sigaction sa;
  830. sa.sa_handler = handler;
  831. sigemptyset(&sa.sa_mask);
  832. sa.sa_flags = 0;
  833. sigaction(sig, &sa, NULL);
  834. }
  835. static int cpu_count(void)
  836. {
  837. int n;
  838. #if defined (_SC_NPROCESSORS_ONLN)
  839. n = (int) sysconf(_SC_NPROCESSORS_ONLN);
  840. #elif defined (_SC_NPROC_ONLN)
  841. n = (int) sysconf(_SC_NPROC_ONLN);
  842. #elif defined (HPUX)
  843. #include <sys/mpctl.h>
  844. n = mpctl(MPC_GETNUMSPUS, 0, 0);
  845. #else
  846. n = -1;
  847. errno = ENOSYS;
  848. #endif
  849. return n;
  850. }
  851. /******************************************************************/