Copilot commented on code in PR #13898:
URL: https://github.com/apache/trafficserver/pull/13898#discussion_r4392594762
##########
src/iocore/net/UnixNetAccept.cc:
##########
@@ -85,6 +87,81 @@ count_client_connection(UnixNetVConnection *vc, bool exempt)
}
}
+/** Whether this acceptor should leave the connections queued on its listen
socket for now.
+ *
+ * True while the peak awake span has reached
+ * @c proxy.config.exec_thread.watchdog.timeout_refuse_ms, where the queued
connections cost nothing at
+ * all and the threads may yet catch up and serve them. Independent of the
accept queue shrink, which
+ * has its own threshold (see @c watchdog_apply_backlog) and lets the *kernel*
shed while ATS keeps
+ * accepting - a bounded queue only drains as fast as we call @c accept4,
which is what keeps inflow
+ * near the rate we can actually serve. Both can be in force at once, in which
case the queue is
+ * bounded and nothing is draining it.
+ *
+ * A listener marked @c f_watchdog_exempt is never subject to backpressure.
Those are the loopback
+ * companion listeners opened alongside each proxy port, so local connections
keep getting a
+ * truthful answer about the proxy however far behind the event threads are.
The volume of local
+ * connections is small against the inbound load that caused the saturation.
+ *
+ * @param[in] na The acceptor.
+ *
+ * @return true if the caller should not drain its listen socket on this pass.
+ */
+bool
+watchdog_should_refuse(NetAccept *na)
+{
+ return !na->opt.f_watchdog_exempt && Watchdog::accept_refuse();
+}
+
+/** Resize @a na's kernel accept queue to the depth the watchdog is currently
asking for.
+ *
+ * Calling @c listen again on a listening socket updates its backlog.
Shrinking it does not evict
+ * connections already queued - they drain normally - but it does stop the
kernel admitting more until
+ * the depth falls back under the new limit, which is the backpressure we
want. The kernel then sheds on
+ * our behalf at no per-connection cost to ATS, and keeps doing so even when
no ATS thread is scheduled
+ * to run an accept loop. On Linux that means silently dropping new SYNs
rather than refusing them, so
+ * shed clients retransmit with backoff instead of seeing an error.
+ *
+ * Called at the top of each accept pass rather than from the monitor thread:
the monitor has no access
+ * to the listen descriptors without taking @c naVecMutex, and it is
deliberately kept clear of every
+ * event system lock. One syscall per acceptor per transition, none in the
steady state.
+ *
+ * @param[in,out] na The acceptor whose listen socket should be resized.
+ */
+void
+watchdog_apply_backlog(NetAccept *na)
+{
+ int want_permille = 1000;
+ if (!na->opt.f_watchdog_exempt) {
+ want_permille = Watchdog::backlog_scale_permille();
+ }
+
+ if (!na->server.sock.is_ok() || want_permille ==
na->applied_backlog_permille->load(std::memory_order_relaxed)) {
+ return;
+ }
+
+ int const configured = get_listen_backlog();
+ int const target = std::max(1, configured * want_permille / 1000);
+
+ if (safe_listen(na->server.sock.get_fd(), target) < 0) {
Review Comment:
Acceptors cloned onto the same socket have different mutexes, so the shared
atomic does not serialize the listen call with the subsequent applied-scale
store. Across a watchdog transition, one acceptor can restore the full backlog,
another can shrink it, and the first can then publish 1000; subsequent passes
skip restoration because the cached value already matches 1000, leaving the
socket permanently shrunk even after backpressure is disabled. Serialize the
entire resize/check/publication operation per shared socket, or give each
socket a single resize owner.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]