XX-net/XX-Net · warning

remove conn:%d except:%r

Error message

remove conn:%d except:%r

What it means

remove_conn deletes a connection from proxy_session.conn_list inside a try/except; any exception during the dict lookup/deletion is caught and logged with the conn_id and repr of the exception, after which the code continues (resetting target_on_roads if the list became empty). It indicates bookkeeping trouble while tearing down a connection, not a data-path failure.

Source

Thrown at code/default/x_tunnel/local/proxy_session.py:522

        conn_list = dict(self.conn_list)
        for conn_id in conn_list:
            try:
                # xlog.debug("stopping conn:%d", conn_id)
                self.conn_list[conn_id].stop(reason="system reset")
            except Exception as e:
                xlog.warn("stopping conn:%d fail:%r", conn_id, e)
                pass
        # self.conn_list = {}
        xlog.debug("stop all connection finished")

    def remove_conn(self, conn_id):
        try:
            if conn_id in self.conn_list:
                conn = self.conn_list[conn_id]
                # xlog.debug("remove conn:%d %s:%d", conn_id, conn.host, conn.port)
                del self.conn_list[conn_id]
        except Exception as e:
            xlog.warn("remove conn:%d except:%r", conn_id, e)

        if len(self.conn_list) == 0:
            self.target_on_roads = 0

    def send_conn_data(self, conn_id, data):
        if not self.running:
            xlog.warn("send_conn_data but not running")
            return

        # xlog.debug("upload conn:%d, len:%d", conn_id, len(data))
        buf = base_container.WriteBuffer()
        buf.append(struct.pack("<II", conn_id, len(data)))
        buf.append(data)
        self.send_buffer.put(buf)

        if self.oldest_received_time == 0:
            self.oldest_received_time = time.time()
        elif self.send_buffer.pool_size > g.config.max_payload:

View on GitHub (pinned to cfa5bc17b6)

Solutions

  1. Inspect the exception repr in the log to find which operation inside the try block actually raised.
  2. Serialize conn_list mutation with the session lock if you have patched this code, or upgrade to a version that locks remove_conn.
  3. If it only appears during shutdown races, it is benign; verify fd/socket counts return to baseline afterwards.
Defensive patterns

Strategy: try-catch

Try / catch

try:
    session.remove_conn(conn_id)
except Exception:
    pass  # logged internally; verify emptiness separately

Prevention

When it happens

Trigger: do_stop or connection teardown calling remove_conn for a conn_id whose entry is in an inconsistent state, or concurrent mutation of conn_list raising inside the guarded block (e.g. a custom conn object whose __del__/comparison raises during dict operations).

Common situations: Concurrent stop and data-receive threads mutating conn_list; custom/patched connection classes; rare races during rapid churn of short-lived connections.

Related errors


AI-assisted analysis of XX-net/XX-Net@cfa5bc17b6 (2026-08-27). Data as JSON: /api/errors/26c76cbbddfd3d94. Report an issue: GitHub.