{"record":{"id":"c1cffaec0123eeb6","repo":"XX-net/XX-Net","slug":"session-try-to-run-but-is-running","errorCode":null,"errorMessage":"session try to run but is running.","messagePattern":"session try to run but is running\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"code/default/x_tunnel/local/proxy_session.py","lineNumber":119,"sourceCode":"        # if no data left, set to 0\n        self.oldest_received_time = 0\n\n        self.last_state = {\n            \"timeout\": 0,\n        }\n        if g.config.enable_tls_relay:\n            threading.Thread(target=self.reporter, name=\"reporter\").start()\n\n        if g.config.upload_logs:\n            threading.Thread(target=upload_logs_thread, name=\"upload_logs\").start()\n\n        self.timeout_check_th = threading.Thread(target=self.timeout_checker, name=\"timeout_check\")\n        self.timeout_check_th.start()\n\n    def start(self):\n        with self.lock:\n            if self.running is True:\n                xlog.warn(\"session try to run but is running.\")\n                return True\n\n            self.session_id = utils.to_bytes(utils.generate_random_lowercase(8))\n            self.last_conn_id = 0\n            self.last_transfer_no = 0\n            self.conn_list = {}\n            self.transfer_list = {}\n            self.last_send_time = time.time()\n            self.last_receive_time = 0\n\n            # speed calculation\n            self.traffic_upload = 0\n            self.traffic_download = 0\n            self.last_traffic_upload = 0\n            self.last_traffic_download = 0\n            self.last_traffic_reset_time = time.time()\n\n            # sn => (payload, send_time)","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/XX-net/XX-Net/blob/cfa5bc17b67676e467f37ec50766127e0ab5f0aa/code/default/x_tunnel/local/proxy_session.py#L101-L137","documentation":"proxy_session.start() was called while self.running was already True. The session is a singleton-ish long-running multiplexed tunnel; start() guards against double-start and just logs this warning and returns True (treating it as already started) without reinitializing state.","triggerScenarios":"Calling start() twice, e.g. from two worker threads, or from both auto-start logic and an explicit user start, without waiting for the previous session to stop.","commonSituations":"Launcher code that starts the tunnel on config change while it is already running; race between an auto-restart thread and manual start; plugin reload re-invoking initialization.","solutions":["Guard calls to start() with your own running check or call stop() before start() when you intend to restart.","Audit for double invocation paths (auto-start thread plus explicit start) and serialize them with a lock.","Treat this warning as benign if intentional (idempotent start) — no state is corrupted."],"exampleFix":"# before\nsession.start()  # may be called twice\n\n# after\nif not session.running:\n    session.start()","handlingStrategy":"validation","validationCode":"if not session.running:\n    session.start()\nelse:\n    pass  # already started; skip","typeGuard":"def is_started(session) -> bool:\n    return bool(getattr(session, 'running', False))","tryCatchPattern":null,"preventionTips":["Call start() from a single place guarded by a lock.","Check session.running before invoking start().","Call stop() before start() when intentionally restarting."],"tags":["lifecycle","concurrency","double-start"],"backgroundTag":"double-start-guard","analyzedSha":"cfa5bc17b67676e467f37ec50766127e0ab5f0aa","analyzedAt":"2026-08-27T19:28:28.225Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}