2 * A simple preforking daemon, inspired by the logic in Apache 1.3
3 * Martin Mares, September 2007
11 #include <sys/socket.h>
12 #include <netinet/in.h>
14 #define NUM_CHILDREN 10
16 static int listening_sk;
18 /*** Logging functions ***/
21 vmsg(char *msg, va_list args)
24 * This is a little bit tricky, because we need to be sure that logging
25 * is atomic with respect to other processes. Fortunately, it is sufficient
26 * to prepare everything in a buffer and flush it with a single write().
29 int cnt = vsnprintf(buf, sizeof(buf)-1, msg, args);
53 /*** Child process ***/
61 struct sockaddr_in sa;
62 socklen_t len = sizeof(sa);
63 int sk = accept(listening_sk, (struct sockaddr *) &sa, &len);
65 die("Accept failed: %m");
67 /* Handle the connection somehow */
68 write(sk, "Hello, world!\n", 14);
71 /* After processing a certain number of requests, exit. This makes small memory leaks harmless. */
77 /*** Master process ***/
82 /* Set up the listening socket */
84 listening_sk = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
86 die("Cannot create listening socket: %m");
87 if (setsockopt(listening_sk, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0)
88 die("Cannot set SO_REUSEADDR: %m");
89 struct sockaddr_in sa = { .sin_family = AF_INET, .sin_port = htons(9999) };
90 if (bind(listening_sk, (struct sockaddr *) &sa, sizeof(sa)) < 0)
91 die("Cannot bind: %m");
92 if (listen(listening_sk, 256) < 0)
93 die("Cannot listen: %m");
101 if (children < NUM_CHILDREN)
106 /* Temporary resource shortage, better sleep for a while */
107 msg("Fork failed: %m");
118 die("Wait failed: %m");
119 if (!(WIFEXITED(status) && !WEXITSTATUS(status)))
120 msg("Child %d exited with status %x", (int)pid, status);