Process management
This commit is contained in:
@ -10,16 +10,73 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/select.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <wait.h>
|
||||
|
||||
#include "utils.c"
|
||||
#include "net/http.c"
|
||||
#include "client.c"
|
||||
|
||||
|
||||
int active = 1;
|
||||
|
||||
void destroy() {
|
||||
fprintf(stderr, "\n" ERR_STR "Terminating forcefully!" CLR_STR "\n");
|
||||
int status = 0;
|
||||
int ret;
|
||||
int kills = 0;
|
||||
for (int i = 0; i < MAX_CHILDREN; i++) {
|
||||
if (CHILDREN[i] != 0) {
|
||||
ret = waitpid(CHILDREN[i], &status, WNOHANG);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, ERR_STR "Unable to wait for child process (PID %i): %s" CLR_STR "\n", CHILDREN[i], strerror(errno));
|
||||
} else if (ret == CHILDREN[i]) {
|
||||
CHILDREN[i] = 0;
|
||||
} else {
|
||||
kill(CHILDREN[i], SIGKILL);
|
||||
kills++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (kills > 0) {
|
||||
fprintf(stderr, ERR_STR "Killed %i child process(es)" CLR_STR "\n", kills);
|
||||
}
|
||||
exit(2);
|
||||
}
|
||||
|
||||
void terminate() {
|
||||
fprintf(stderr, "\nTerminating gracefully...\n");
|
||||
active = 0;
|
||||
|
||||
signal(SIGTERM, destroy);
|
||||
signal(SIGINT, destroy);
|
||||
|
||||
for (int i = 0; i < NUM_SOCKETS; i++) {
|
||||
shutdown(SOCKETS[i], SHUT_RDWR);
|
||||
close(SOCKETS[i]);
|
||||
}
|
||||
|
||||
int status = 0;
|
||||
int ret;
|
||||
for (int i = 0; i < MAX_CHILDREN; i++) {
|
||||
if (CHILDREN[i] != 0) {
|
||||
ret = waitpid(CHILDREN[i], &status, 0);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, ERR_STR "Unable to wait for child process (PID %i): %s" CLR_STR "\n", CHILDREN[i], strerror(errno));
|
||||
} else if (ret == CHILDREN[i]) {
|
||||
CHILDREN[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "Goodbye\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
const int YES = 1;
|
||||
fd_set socket_fds, read_socket_fds;
|
||||
@ -27,6 +84,12 @@ int main(int argc, const char *argv[]) {
|
||||
int ready_sockets_num = 0;
|
||||
long client_num = 0;
|
||||
|
||||
int client;
|
||||
struct sockaddr_in6 client_addr;
|
||||
unsigned int client_addr_len = sizeof(client_addr);
|
||||
|
||||
struct timeval timeout;
|
||||
|
||||
parent_stdout = stdout;
|
||||
parent_stderr = stderr;
|
||||
|
||||
@ -60,6 +123,9 @@ int main(int argc, const char *argv[]) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
signal(SIGINT, terminate);
|
||||
signal(SIGTERM, terminate);
|
||||
|
||||
// TODO implement TLS server side handshake
|
||||
|
||||
for (int i = 0; i < NUM_SOCKETS; i++) {
|
||||
@ -77,9 +143,11 @@ int main(int argc, const char *argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
while (1) {
|
||||
while (active) {
|
||||
timeout.tv_sec = 1;
|
||||
timeout.tv_usec = 0;
|
||||
read_socket_fds = socket_fds;
|
||||
ready_sockets_num = select(max_socket_fd + 1, &read_socket_fds, NULL, NULL, NULL);
|
||||
ready_sockets_num = select(max_socket_fd + 1, &read_socket_fds, NULL, NULL, &timeout);
|
||||
if (ready_sockets_num == -1) {
|
||||
fprintf(stderr, ERR_STR "Unable to select sockets: %s" CLR_STR "\n", strerror(errno));
|
||||
return 1;
|
||||
@ -87,16 +155,26 @@ int main(int argc, const char *argv[]) {
|
||||
|
||||
for (int i = 0; i < NUM_SOCKETS; i++) {
|
||||
if (FD_ISSET(SOCKETS[i], &read_socket_fds)) {
|
||||
client = accept(SOCKETS[i], (struct sockaddr *) &client_addr, &client_addr_len);
|
||||
if (client == -1) {
|
||||
fprintf(parent_stderr, ERR_STR "Unable to accept connection: %s" CLR_STR "\n", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid == 0) {
|
||||
// child
|
||||
return client_handler(SOCKETS[i], client_num);
|
||||
signal(SIGINT, SIG_IGN);
|
||||
signal(SIGTERM, SIG_IGN);
|
||||
return client_handler(client, client_num, &client_addr);
|
||||
} else if (pid > 0) {
|
||||
// parent
|
||||
client_num++;
|
||||
close(client);
|
||||
for (int j = 0; j < MAX_CHILDREN; j++) {
|
||||
if (CHILDREN[j] == 0) {
|
||||
CHILDREN[j] = pid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -104,5 +182,20 @@ int main(int argc, const char *argv[]) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int status = 0;
|
||||
int ret;
|
||||
for (int i = 0; i < MAX_CHILDREN; i++) {
|
||||
if (CHILDREN[i] != 0) {
|
||||
ret = waitpid(CHILDREN[i], &status, WNOHANG);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, ERR_STR "Unable to wait for child process (PID %i): %s" CLR_STR "\n", CHILDREN[i], strerror(errno));
|
||||
} else if (ret == CHILDREN[i]) {
|
||||
CHILDREN[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user