commit 70f86ba
uint
·
2026-01-31 01:35:37 +0000 UTC
parent 3e2f344
remove brittle forking, replace with parallelism
2 files changed,
+38,
-21
M
Makefile
+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)