commit 70f86ba

uint  ·  2026-01-31 01:35:37 +0000 UTC
parent 3e2f344
remove brittle forking, replace with parallelism
2 files changed,  +38, -21
+1, -1
1@@ -2,7 +2,7 @@ CC ?= cc
2 VER = 1.26
3 GIT_VER != git describe --always --tags 2>/dev/null || echo unknown
4 CPPFLAGS = -D_POSIX_C_SOURCE=200809L -DGIT_VER=\"$(GIT_VER)\" -DVERSION=\"$(VER)\"
5-CFLAGS = -std=c99 -Wall -Wextra -Iserver/include
6+CFLAGS = -std=c99 -Wall -Wextra -Iserver/include -pthread
7 OUT = parados
8 
9 all: release
+37, -20
  1@@ -10,10 +10,13 @@
  2 
  3 #include <errno.h>
  4 #include <fcntl.h>
  5+#include <pthread.h>
  6+#include <semaphore.h>
  7 #include <signal.h>
  8 #include <stdarg.h>
  9 #include <stdbool.h>
 10 #include <stddef.h>
 11+#include <stdint.h>
 12 #include <stdio.h>
 13 #include <stdlib.h>
 14 #include <string.h>
 15@@ -36,6 +39,7 @@
 16 #endif /* GIT_VER */
 17 
 18 static void apply_rlimits(void);
 19+static void* client_thread(void* arg);
 20 static void fd_set_cloexec(int fd);
 21 static void sock_set_timeouts(int fd);
 22 
 23@@ -43,7 +47,8 @@ void die(const char* s, int e);
 24 void run(void);
 25 void setup(void);
 26 
 27-int sock;
 28+static sem_t slots;
 29+static int sock;
 30 struct library lib;
 31 
 32 static void apply_rlimits(void)
 33@@ -59,6 +64,19 @@ static void apply_rlimits(void)
 34 	(void)setrlimit(RLIMIT_NOFILE, &rl);
 35 }
 36 
 37+static void* client_thread(void* arg)
 38+{
 39+	int c = (int)(intptr_t)arg;
 40+
 41+	sock_set_timeouts(c);
 42+	(void)http_handle(c);
 43+	shutdown(c, SHUT_WR);
 44+	close(c);
 45+
 46+	(void)sem_post(&slots);
 47+	return NULL;
 48+}
 49+
 50 static void fd_set_cloexec(int fd)
 51 {
 52 	int f = fcntl(fd, F_GETFD);
 53@@ -85,46 +103,45 @@ void die(const char* s, int e)
 54 void run(void)
 55 {
 56 	for (;;) {
 57-		int c = accept(sock, NULL, NULL);
 58+		int c;
 59+
 60+		/* client cap */
 61+		(void)sem_wait(&slots);
 62+
 63+		c = accept(sock, NULL, NULL);
 64 		if (c < 0) {
 65+			(void)sem_post(&slots);
 66 			if (errno == EINTR)
 67 				continue;
 68 			continue;
 69 		}
 70+
 71 		fd_set_cloexec(c);
 72 		LOG(verbose_log, "CORE", "Connection         Accepted");
 73 
 74-		pid_t pid = fork();
 75-		if (pid < 0) {
 76+		pthread_t t;
 77+		int err = pthread_create(&t, NULL, client_thread, (void*)(intptr_t)c);
 78+		if (err != 0) {
 79+			LOG(true, "CORE", "pthread_create FAILED %d", err);
 80 			close(c);
 81+			(void)sem_post(&slots);
 82 			continue;
 83 		}
 84 
 85-		if (pid == 0) {
 86-#ifdef __OpenBSD__
 87-			if (pledge("stdio inet rpath", NULL) < 0)
 88-				_exit(EXIT_FAILURE);
 89-#endif
 90-			sock_set_timeouts(c);
 91-			(void)http_handle(c);
 92-			shutdown(c, SHUT_WR);
 93-			close(c);
 94-			_exit(EXIT_SUCCESS);
 95-		}
 96-
 97-		close(c);
 98+		(void)pthread_detach(t);
 99 	}
100 }
101 
102 void setup(void)
103 {
104-	signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE */
105-	signal(SIGCHLD, SIG_IGN); /* reap children to prevent
106-								 them to turn into zombies */
107+	signal(SIGPIPE, SIG_IGN);
108 
109 	config_load();
110 	apply_rlimits();
111 
112+	if (sem_init(&slots, 0, max_clients) < 0)
113+		die("sem_init", EXIT_FAILURE);
114+
115 	int ret = 1;
116 	sock = socket(AF_INET, SOCK_STREAM, 0);
117 	if (sock < 0)