commit f0780f01e405364779720f38b2aec12c6b63caf2
| author | 斟酌 鵬兄 <tgckpg@gmail.com> |
| date | 2026-06-05T18:20:25Z |
| subject | unify close behavior |
commit f0780f01e405364779720f38b2aec12c6b63caf2
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date: 2026-06-05T18:20:25Z
unify close behavior
---
devtools/ab_test.sh | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++
src/stream_builtin.c | 21 +++++++++++++---
src/stream_conn.c | 10 +++-----
3 files changed, 92 insertions(+), 9 deletions(-)
diff --git a/devtools/ab_test.sh b/devtools/ab_test.sh
new file mode 100755
index 0000000..9e98c1f
--- /dev/null
+++ b/devtools/ab_test.sh
@@ -0,0 +1,70 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+# Run from repo root:
+# sudo ./test_tinyproxy.sh
+#
+# Routes:
+# :12700 -> builtin http_ok
+# :12800 -> TCP proxy to 127.0.0.1:12700
+
+NOFILE="${NOFILE:-1048576}"
+WORKERS="${WORKERS:-0}"
+TINYPROXY="${TINYPROXY:-/usr/local/bin/tinyproxy}"
+
+LISTEN_BACKLOG="${LISTEN_BACKLOG:-65535}"
+SYN_BACKLOG="${SYN_BACKLOG:-65535}"
+EPHEMERAL_RANGE="${EPHEMERAL_RANGE:-10000 65535}"
+
+if [ "$(id -u)" -ne 0 ]; then
+ echo "error: run as root: sudo $0" >&2
+ exit 1
+fi
+
+if [ ! -x "$TINYPROXY" ]; then
+ echo "error: tinyproxy binary not found/executable: $TINYPROXY" >&2
+ exit 1
+fi
+
+echo "== tinyproxy stress-test launcher =="
+echo "tinyproxy: $TINYPROXY"
+echo "workers: $WORKERS"
+echo "nofile: $NOFILE"
+echo "somaxconn: $LISTEN_BACKLOG"
+echo "tcp_max_syn_backlog: $SYN_BACKLOG"
+echo "ephemeral ports: $EPHEMERAL_RANGE"
+echo
+
+echo "== raising process fd limit =="
+ulimit -n "$NOFILE"
+echo "soft nofile: $(ulimit -Sn)"
+echo "hard nofile: $(ulimit -Hn)"
+echo
+
+echo "== applying temporary sysctl tuning =="
+sysctl -w "net.core.somaxconn=$LISTEN_BACKLOG"
+sysctl -w "net.ipv4.tcp_max_syn_backlog=$SYN_BACKLOG"
+sysctl -w "net.ipv4.ip_local_port_range=$EPHEMERAL_RANGE"
+echo
+
+echo "== current relevant sysctls =="
+sysctl net.core.somaxconn
+sysctl net.ipv4.tcp_max_syn_backlog
+sysctl net.ipv4.ip_local_port_range
+echo
+
+echo "== starting tinyproxy =="
+echo "test direct builtin:"
+echo " ab -c 10000 -n 100000 http://127.0.0.1:12700/"
+echo
+echo "test chained tcp->tcp->builtin:"
+echo " ab -c 10000 -n 100000 http://127.0.0.1:12800/"
+echo
+echo "watch sockets:"
+echo " ./watch_tinyproxy_sockets.sh"
+echo
+
+exec "$TINYPROXY" \
+ -w"$WORKERS" \
+ -L "tcp :12700 builtin http_ok" \
+ -L "tcp :12800 tcp 127.0.0.1:12700"
diff --git a/src/stream_builtin.c b/src/stream_builtin.c
index 60a1617..f0f406c 100644
--- a/src/stream_builtin.c
+++ b/src/stream_builtin.c
@@ -108,11 +108,26 @@ int start_stream_builtin(conn_t *conn)
switch (res.action) {
case X_BUILTIN_ACTION_CLOSE:
if (res.data_len > 0) {
+ bufferevent_setcb(
+ conn->client,
+ builtin_client_read_cb,
+ builtin_close_after_write_cb,
+ stream_client_event_cb,
+ conn
+ );
bufferevent_write(conn->client, res.data, res.data_len);
- bufferevent_setcb(conn->client, NULL, builtin_close_after_write_cb, stream_client_event_cb, conn);
- bufferevent_enable(conn->client, EV_WRITE);
+ bufferevent_enable(conn->client, EV_READ | EV_WRITE);
} else {
- free_conn(conn);
+ finish_client_write(conn);
+ conn->close_after_client_eof = true;
+ bufferevent_setcb(
+ conn->client,
+ builtin_client_read_cb,
+ NULL,
+ stream_client_event_cb,
+ conn
+ );
+ bufferevent_enable(conn->client, EV_READ);
}
return 0;
diff --git a/src/stream_conn.c b/src/stream_conn.c
index 86466ae..43bdd20 100644
--- a/src/stream_conn.c
+++ b/src/stream_conn.c
@@ -94,7 +94,9 @@ static void drain_client_then_close(conn_t *conn)
}
if (!client_has_pending_output(conn)) {
- free_conn(conn);
+ finish_client_write(conn);
+ conn->close_client_after_drain = false;
+ conn->close_after_client_eof = true;
}
}
@@ -237,11 +239,7 @@ void stream_upstream_event_cb(struct bufferevent *bev, short events, void *arg)
}
if (events & BEV_EVENT_EOF) {
- if (client_has_pending_output(conn)) {
- goto out_drain_client;
- }
-
- goto out_free;
+ goto out_drain_client;
}
LOG_DEBUG("unhandled upstream event",