You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
On a real device, the Statistics screen showed active/open tunnels growing after YouTube was closed. Device logcat confirmed the proxy hit `IO thread pool full (256 threads)` around 135 active connections, after which pipe tasks were rejected.
10
+
11
+
## Root Cause
12
+
13
+
`ProxyServer.tunnel()` scheduled both tunnel directions as independent IO executor tasks after the client handler had already consumed one executor thread. Under load this required roughly three worker tasks per tunnel. When the executor rejected one of the pipe tasks, the active tunnel slot could remain counted until timeout or cleanup.
14
+
15
+
## Solution
16
+
17
+
- Run the client-to-upstream pipe in the current client handler worker.
18
+
- Schedule only the upstream-to-client pipe as an extra worker task.
19
+
- Add an explicit active tunnel limit with reserve capacity for accept and handshake work.
20
+
- Reserve the tunnel slot before upstream connection and before returning `200 Connection Established`.
21
+
- Return `503 Service Unavailable` when the active tunnel limit is reached.
22
+
- Release tunnel slots via a guarded decrement so counters cannot go negative.
- Started the app on `SM-A165F - 15` through the UI via ADB.
29
+
- Sent 120 short CONNECT requests through an ADB-forwarded local port: all completed and active tunnels dropped back down.
30
+
- Sent 130 concurrent CONNECT requests: 96 were accepted, 34 were rejected by the explicit tunnel limit, and logcat did not show `IO thread pool full`.
31
+
- Confirmed the Statistics screen showed `Peak = 96` and active tunnels did not keep growing after the test sockets were closed.
32
+
- Re-installed the final APK, selected a saved HTTPS upstream proxy, and verified 5 CONNECT requests completed through the upstream path.
33
+
- Stopped the proxy and verified system proxy was restored to `:0` and `127.0.0.1:8080` no longer listened.
34
+
35
+
## Prevention
36
+
37
+
- Do not schedule both directions of a long-lived tunnel without reserving executor capacity.
38
+
- Apply backpressure before sending success responses to clients.
39
+
- Treat rejected executor tasks as a cleanup path, not just a log event.
0 commit comments