penguin/tinyproxy

An L4 proxy designed to act as a tiny transparent shim

commit 6b1d371b95b67c1490abf30c3bffe34a3f591e97

author斟酌 鵬兄 <tgckpg@gmail.com>
date2026-05-26T12:10:09Z
subjectBasic signal handling
commit 6b1d371b95b67c1490abf30c3bffe34a3f591e97
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date:   2026-05-26T12:10:09Z

    Basic signal handling
---
 Dockerfile  |  9 ++++----
 Makefile    | 52 +++++++++++++++++++++++--------------------
 signal.c    | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 signal.h    | 14 ++++++++++++
 tinyproxy.c | 11 ++++++++++
 5 files changed, 130 insertions(+), 29 deletions(-)

diff --git a/Dockerfile b/Dockerfile
index b846dd6..9d7b853 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -8,10 +8,10 @@ WORKDIR /src
 
 COPY [ "*.c", "*.h", "*.conf", "Makefile", "/src" ]
 
-RUN make all
+RUN make all STATIC=1
 
 COPY tests ./tests
-RUN STATIC=1 make test
+RUN make test STATIC=1
 
 RUN cp /src/tinyproxy.conf /etc/ && cp /src/bin/tinyproxy /usr/bin/
 
@@ -20,6 +20,5 @@ FROM scratch
 COPY --from=build /src/bin/tinyproxy /usr/bin/tinyproxy
 COPY --from=build /src/tinyproxy.conf /etc/tinyproxy.conf
 
-RUN /usr/bin/tinyproxy
-
-CMD [ "tinyproxy", "-c", "/etc/tinyproxy.conf" ]
+ENTRYPOINT ["/usr/bin/tinyproxy"]
+CMD ["-c", "/etc/tinyproxy.conf"]
diff --git a/Makefile b/Makefile
index 69433c7..ed1d3b5 100644
--- a/Makefile
+++ b/Makefile
@@ -1,18 +1,18 @@
 export
 
 CC ?= cc
-AR := /usr/bin/ar
-RANLIB := /usr/bin/ranlib
+AR ?= ar
+RANLIB ?= ranlib
 STRIP ?= strip
-STATIC ?= 1
 
 PROJECT_ROOT := $(CURDIR)
 BIN_DIR := $(CURDIR)/bin
 
 SRC := klog.c \
-	   proxy_proto_v2.c \
-	   route.c \
-	   tcp_route.c \
+       proxy_proto_v2.c \
+       signal.c \
+       route.c \
+       tcp_route.c \
        file_conf.c \
        tinyproxy.c
 
@@ -20,29 +20,37 @@ BIN := $(BIN_DIR)/tinyproxy
 
 BUILD_DIR := $(PROJECT_ROOT)/build
 
-# Optional. Set this only when you want to build vendored libevent.
-# Example:
-#   make LIBEVENT_SRC=$(PROJECT_ROOT)/libevent2
 LIBEVENT_SRC ?=
-
 LIBEVENT_PREFIX := $(BUILD_DIR)/libevent-install
 LIBEVENT_CORE_A := $(LIBEVENT_PREFIX)/lib/libevent_core.a
 
 CFLAGS ?= -Os -Wall -Wextra -ffunction-sections -fdata-sections
 
+UNAME_S := $(shell uname)
+
+ifeq ($(UNAME_S),Darwin)
+STATIC ?= 0
+LDFLAGS += -Wl,-dead_strip
+TEST_FLAGS := CONCURRENCY=1000 TOTAL=1000 FD_LIMIT=2560
+else
+STATIC ?= 1
+LDFLAGS += -Wl,--gc-sections
+TEST_FLAGS :=
+endif
+
 ifeq ($(STATIC),1)
 LDFLAGS += -static
 PKG_CONFIG_STATIC := --static
+else
+PKG_CONFIG_STATIC :=
 endif
 
 ifeq ($(strip $(LIBEVENT_SRC)),)
-# System libevent, statically linked
 LIBEVENT_CPPFLAGS := $(shell pkg-config --cflags libevent_core)
 LIBEVENT_LDFLAGS  :=
-LIBEVENT_LDLIBS   := $(shell pkg-config --static --libs libevent_core)
+LIBEVENT_LDLIBS   := $(shell pkg-config $(PKG_CONFIG_STATIC) --libs libevent_core)
 LIBEVENT_DEPS     :=
 else
-# Vendored libevent
 LIBEVENT_CPPFLAGS := -I$(LIBEVENT_PREFIX)/include
 LIBEVENT_LDFLAGS  := -L$(LIBEVENT_PREFIX)/lib
 LIBEVENT_LDLIBS   := -levent_core
@@ -50,9 +58,11 @@ LIBEVENT_DEPS     := $(LIBEVENT_CORE_A)
 endif
 
 CPPFLAGS += $(LIBEVENT_CPPFLAGS)
-LDFLAGS  += -static $(LIBEVENT_LDFLAGS)
+LDFLAGS  += $(LIBEVENT_LDFLAGS)
 LDLIBS   += $(LIBEVENT_LDLIBS)
 
+all: $(BIN)
+
 $(BIN): $(SRC) $(LIBEVENT_DEPS)
 	mkdir -p $(BIN_DIR)
 	$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(SRC) $(LDFLAGS) $(LDLIBS)
@@ -75,18 +85,12 @@ $(LIBEVENT_CORE_A):
 	AR=$(AR) RANLIB=$(RANLIB) $(MAKE) -C $(LIBEVENT_SRC) install
 endif
 
-ifeq ($(shell uname),Darwin)
-LDFLAGS += -Wl,-dead_strip
-TEST_FLAGS := CONCURRENCY=1000 TOTAL=1000 FD_LIMIT=2560
-else
-LDFLAGS += -Wl,--gc-sections
-TEST_FLAGS :=
-endif
-
-all: $(BIN)
-
 strip: $(BIN)
+ifeq ($(UNAME_S),Darwin)
+	$(error strip target is not supported on macOS; build without stripping, or strip inside the Linux/Alpine container)
+else
 	$(STRIP) $(BIN)
+endif
 
 test: $(BIN)
 	$(TEST_FLAGS) python3 tests/test_proxy.py $(BIN)
diff --git a/signal.c b/signal.c
new file mode 100644
index 0000000..2e23425
--- /dev/null
+++ b/signal.c
@@ -0,0 +1,73 @@
+#include "signal.h"
+
+#include <signal.h>
+#include <string.h>
+
+#include "klog.h"
+
+static void signal_cb(evutil_socket_t sig, short events, void *arg)
+{
+	(void)events;
+
+	struct event_base *base = arg;
+
+	switch (sig) {
+	case SIGINT:
+		LOG_INFO("received signal, shutting down", "signal", "SIGINT");
+		break;
+	case SIGTERM:
+		LOG_INFO("received signal, shutting down", "signal", "SIGTERM");
+		break;
+	default:
+		LOG_INFO("received signal, shutting down", "signal", "unknown");
+		break;
+	}
+
+	event_base_loopbreak(base);
+}
+
+int setup_signal_handlers(struct event_base *base, struct signal_events *signals)
+{
+	if (base == NULL || signals == NULL) {
+		return -1;
+	}
+
+	memset(signals, 0, sizeof(*signals));
+
+	signals->sigint_ev = evsignal_new(base, SIGINT, signal_cb, base);
+	if (signals->sigint_ev == NULL) {
+		free_signal_handlers(signals);
+		return -1;
+	}
+
+	signals->sigterm_ev = evsignal_new(base, SIGTERM, signal_cb, base);
+	if (signals->sigterm_ev == NULL) {
+		free_signal_handlers(signals);
+		return -1;
+	}
+
+	if (event_add(signals->sigint_ev, NULL) != 0) {
+		free_signal_handlers(signals);
+		return -1;
+	}
+
+	if (event_add(signals->sigterm_ev, NULL) != 0) {
+		free_signal_handlers(signals);
+		return -1;
+	}
+
+	return 0;
+}
+
+void free_signal_handlers(struct signal_events *signals)
+{
+	if (signals == NULL) {
+		return;
+	}
+
+	event_free(signals->sigint_ev);
+	event_free(signals->sigterm_ev);
+
+	signals->sigint_ev = NULL;
+	signals->sigterm_ev = NULL;
+}
diff --git a/signal.h b/signal.h
new file mode 100644
index 0000000..abfb370
--- /dev/null
+++ b/signal.h
@@ -0,0 +1,14 @@
+#ifndef SIGNAL_H
+#define SIGNAL_H
+
+#include <event2/event.h>
+
+struct signal_events {
+	struct event *sigint_ev;
+	struct event *sigterm_ev;
+};
+
+int setup_signal_handlers(struct event_base *base, struct signal_events *signals);
+void free_signal_handlers(struct signal_events *signals);
+
+#endif
diff --git a/tinyproxy.c b/tinyproxy.c
index 171e483..e831c5b 100644
--- a/tinyproxy.c
+++ b/tinyproxy.c
@@ -7,6 +7,7 @@
 #include <unistd.h>
 
 #include "klog.h"
+#include "signal.h"
 #include "file_conf.h"
 #include "tcp_route.h"
 
@@ -86,6 +87,15 @@ int main(int argc, char **argv)
 		return 1;
 	}
 
+	struct signal_events signals;
+
+	if (setup_signal_handlers(base, &signals) != 0) {
+		LOG_ERROR("failed to setup signal handlers");
+		event_base_free(base);
+		free_routes(routes);
+		return 1;
+	}
+
 	struct worker w = {
 		.base = base,
 		.id = 0,
@@ -137,6 +147,7 @@ int main(int argc, char **argv)
 		free_tcp_route(tcp_ctxs[i]);
 	}
 
+	free_signal_handlers(&signals);
 	free(tcp_ctxs);
 	event_base_free(base);
 	free_routes(routes);