Process management
This commit is contained in:
2
Makefile
2
Makefile
@ -8,7 +8,7 @@ packages:
|
|||||||
compile:
|
compile:
|
||||||
@echo "Compiling..."
|
@echo "Compiling..."
|
||||||
@mkdir -p bin
|
@mkdir -p bin
|
||||||
gcc src/necronda-server.c -o bin/necronda-server -std=c11
|
gcc src/necronda-server.c -o bin/necronda-server -std=c11 -D_POSIX_C_SOURCE
|
||||||
@echo "Finished compiling!"
|
@echo "Finished compiling!"
|
||||||
|
|
||||||
install: | packages update compile
|
install: | packages update compile
|
||||||
|
26
src/client.c
26
src/client.c
@ -37,32 +37,30 @@ int client_request_handler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int client_connection_handler(int client) {
|
int client_connection_handler(int client) {
|
||||||
char buf[256];
|
char buf1[256];
|
||||||
|
char buf2[256];
|
||||||
print("Connection accepted from %s (%s) [%s]", client_addr_str, client_addr_str, "N/A");
|
print("Connection accepted from %s (%s) [%s]", client_addr_str, client_addr_str, "N/A");
|
||||||
|
|
||||||
sprintf(buf, "Hello World!\nYour address is: %s\n", client_addr_str);
|
sprintf(buf1, "Hello World!\nYour address is: %s\n", client_addr_str);
|
||||||
send(client, buf, strlen(buf), 0);
|
send(client, buf1, strlen(buf1), 0);
|
||||||
|
int len = recv(client, &buf1, sizeof(buf1), 0);
|
||||||
|
sprintf(buf2, "Thank you, %.*s!\nGood bye!\n", len, buf1);
|
||||||
|
send(client, buf2, strlen(buf2), 0);
|
||||||
|
|
||||||
close(client);
|
close(client);
|
||||||
|
|
||||||
print("Connection closed");
|
print("Connection closed");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int client_handler(int socket, long client_num) {
|
int client_handler(int client, long client_num, struct sockaddr_in6 *client_addr) {
|
||||||
struct sockaddr_in6 client_addr, *server_addr;
|
struct sockaddr_in6 *server_addr;
|
||||||
struct sockaddr_storage server_addr_storage;
|
struct sockaddr_storage server_addr_storage;
|
||||||
unsigned int client_addr_len = sizeof(client_addr);
|
|
||||||
|
|
||||||
char *color_table[] = {"\x1B[31m", "\x1B[32m", "\x1B[33m", "\x1B[34m", "\x1B[35m", "\x1B[36m"};
|
char *color_table[] = {"\x1B[31m", "\x1B[32m", "\x1B[33m", "\x1B[34m", "\x1B[35m", "\x1B[36m"};
|
||||||
|
|
||||||
int client = accept(socket, (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));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
client_addr_str_ptr = malloc(INET6_ADDRSTRLEN);
|
client_addr_str_ptr = malloc(INET6_ADDRSTRLEN);
|
||||||
inet_ntop(client_addr.sin6_family, (void *) &client_addr.sin6_addr, client_addr_str_ptr, INET6_ADDRSTRLEN);
|
inet_ntop(client_addr->sin6_family, (void *) &client_addr->sin6_addr, client_addr_str_ptr, INET6_ADDRSTRLEN);
|
||||||
if (strncmp(client_addr_str_ptr, "::ffff:", 7) == 0) {
|
if (strncmp(client_addr_str_ptr, "::ffff:", 7) == 0) {
|
||||||
client_addr_str = client_addr_str_ptr + 7;
|
client_addr_str = client_addr_str_ptr + 7;
|
||||||
} else {
|
} else {
|
||||||
@ -83,7 +81,7 @@ int client_handler(int socket, long client_num) {
|
|||||||
log_base_prefix = malloc(256);
|
log_base_prefix = malloc(256);
|
||||||
sprintf(log_base_prefix, "[%24s][%s%4i%s]%s[%*s][%5i]%s ",
|
sprintf(log_base_prefix, "[%24s][%s%4i%s]%s[%*s][%5i]%s ",
|
||||||
server_addr_str, R_STR, ntohs(server_addr->sin6_port), CLR_STR,
|
server_addr_str, R_STR, ntohs(server_addr->sin6_port), CLR_STR,
|
||||||
color_table[client_num % 6], INET_ADDRSTRLEN, client_addr_str, ntohs(client_addr.sin6_port), CLR_STR);
|
color_table[client_num % 6], INET_ADDRSTRLEN, client_addr_str, ntohs(client_addr->sin6_port), CLR_STR);
|
||||||
|
|
||||||
int ret = client_connection_handler(client);
|
int ret = client_connection_handler(client);
|
||||||
free(client_addr_str_ptr);
|
free(client_addr_str_ptr);
|
||||||
|
@ -10,16 +10,73 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <wait.h>
|
||||||
|
|
||||||
#include "utils.c"
|
#include "utils.c"
|
||||||
#include "net/http.c"
|
#include "net/http.c"
|
||||||
#include "client.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[]) {
|
int main(int argc, const char *argv[]) {
|
||||||
const int YES = 1;
|
const int YES = 1;
|
||||||
fd_set socket_fds, read_socket_fds;
|
fd_set socket_fds, read_socket_fds;
|
||||||
@ -27,6 +84,12 @@ int main(int argc, const char *argv[]) {
|
|||||||
int ready_sockets_num = 0;
|
int ready_sockets_num = 0;
|
||||||
long client_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_stdout = stdout;
|
||||||
parent_stderr = stderr;
|
parent_stderr = stderr;
|
||||||
|
|
||||||
@ -60,6 +123,9 @@ int main(int argc, const char *argv[]) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signal(SIGINT, terminate);
|
||||||
|
signal(SIGTERM, terminate);
|
||||||
|
|
||||||
// TODO implement TLS server side handshake
|
// TODO implement TLS server side handshake
|
||||||
|
|
||||||
for (int i = 0; i < NUM_SOCKETS; i++) {
|
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;
|
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) {
|
if (ready_sockets_num == -1) {
|
||||||
fprintf(stderr, ERR_STR "Unable to select sockets: %s" CLR_STR "\n", strerror(errno));
|
fprintf(stderr, ERR_STR "Unable to select sockets: %s" CLR_STR "\n", strerror(errno));
|
||||||
return 1;
|
return 1;
|
||||||
@ -87,16 +155,26 @@ int main(int argc, const char *argv[]) {
|
|||||||
|
|
||||||
for (int i = 0; i < NUM_SOCKETS; i++) {
|
for (int i = 0; i < NUM_SOCKETS; i++) {
|
||||||
if (FD_ISSET(SOCKETS[i], &read_socket_fds)) {
|
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();
|
pid_t pid = fork();
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
// child
|
// 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) {
|
} else if (pid > 0) {
|
||||||
// parent
|
// parent
|
||||||
client_num++;
|
client_num++;
|
||||||
|
close(client);
|
||||||
for (int j = 0; j < MAX_CHILDREN; j++) {
|
for (int j = 0; j < MAX_CHILDREN; j++) {
|
||||||
if (CHILDREN[j] == 0) {
|
if (CHILDREN[j] == 0) {
|
||||||
CHILDREN[j] = pid;
|
CHILDREN[j] = pid;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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