Skip to content

Commit 64a90de

Browse files
committed
fix: 清理任务状态并捕获 nexttrace 启动异常
- app.py:38 调整超时守护线程,只触发 stop_nexttrace_for_sid,并让清理逻辑集中在后续步骤,避免重复删除带 来的竞态。 - app.py:47 新增 cleanup_client_state 并在 emit_complete 调用,统一移除 clients 与 client_last_active, 保证无论自然结束还是被强制停止都能彻底清理。 - app.py:140 引入 emit_error_row,在参数非法或进程启动失败时向前端发送可解析的错误行,同时立即 emit_complete,防止任务悬挂。 - app.py:158 将 subprocess.Popen 包装在 try/except 中,捕获 OSError 后记录日志并清理,避免 nexttrace 缺 失时的僵尸任务。
1 parent 9a34de2 commit 64a90de

File tree

2 files changed

+41
-16
lines changed

2 files changed

+41
-16
lines changed

Dockerfile

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,23 @@ FROM golang:1.25-alpine3.21 AS builder
33
# 安装所需的软件包
44
RUN apk update && apk add --no-cache git
55

6-
# 克隆NEXTTRACE源代码并编译
6+
# 克隆NEXTTRACE源代码并编译(内联计算版本信息并注入到 -ldflags)
77
WORKDIR /build
8-
RUN git clone https://github.com/nxtrace/Ntrace-core.git . && \
9-
go clean -modcache && \
10-
go mod download && \
11-
go build -trimpath -ldflags '-w -s -checklinkname=0' -o nexttrace .
8+
RUN set -eux; \
9+
git clone https://github.com/nxtrace/Ntrace-core.git . ; \
10+
go clean -modcache; \
11+
go mod download; \
12+
BUILD_VERSION="$(git describe --tags --always 2>/dev/null || true)"; \
13+
[ -n "$BUILD_VERSION" ] || BUILD_VERSION=dev; \
14+
BUILD_DATE="$(date -u +'%Y-%m-%dT%H:%M:%SZ')"; \
15+
COMMIT_SHA1="$(git rev-parse --short HEAD 2>/dev/null || true)"; \
16+
[ -n "$COMMIT_SHA1" ] || COMMIT_SHA1=unknown; \
17+
LD_PKG="$(go list -m)/config"; \
18+
LD_BASE="-X ${LD_PKG}.Version=${BUILD_VERSION} \
19+
-X ${LD_PKG}.BuildDate=${BUILD_DATE} \
20+
-X ${LD_PKG}.CommitID=${COMMIT_SHA1} \
21+
-w -s -checklinkname=0"; \
22+
go build -trimpath -ldflags "${LD_BASE}" -o nexttrace .
1223

1324
FROM ubuntu:22.04
1425

app.py

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,17 @@ def check_timeouts():
4141
if time.time() - last_active > time_limit:
4242
logging.debug(f"Client {sid} timed out")
4343
stop_nexttrace_for_sid(sid)
44-
del client_last_active[sid]
4544
time.sleep(1)
4645

4746

47+
def cleanup_client_state(sid):
48+
task_removed = clients.pop(sid, None)
49+
if task_removed:
50+
logging.info(f"Client {sid} removed from clients dictionary")
51+
if client_last_active.pop(sid, None) is not None:
52+
logging.debug(f"Client {sid} removed from last active tracker")
53+
54+
4855
def stop_nexttrace_for_sid(sid):
4956
task = clients.get(sid)
5057
if not task:
@@ -64,10 +71,6 @@ def stop_nexttrace_for_sid(sid):
6471
task.process.kill()
6572
logging.info(f"Process killed forcefully for client {sid}")
6673
task.emit_complete()
67-
if sid in clients:
68-
del clients[sid]
69-
logging.info(f"Client {sid} removed from clients dictionary after process termination")
70-
client_last_active.pop(sid, None)
7174

7275

7376
Thread(target=check_timeouts, daemon=True).start()
@@ -132,6 +135,11 @@ def emit_complete(self):
132135
if not self._complete_emitted:
133136
self._complete_emitted = True
134137
self.socketio.emit('nexttrace_complete', room=self.sid)
138+
cleanup_client_state(self.sid)
139+
140+
def emit_error_row(self, message):
141+
error_payload = json.dumps(['-1', '', '', '0', 'ERROR', '', message], ensure_ascii=False)
142+
self.socketio.emit('nexttrace_output', error_payload, room=self.sid)
135143

136144
def run(self):
137145
fixParam = '--map --raw -q 1 --send-time 1' # -d disable-geoip
@@ -143,14 +151,20 @@ def run(self):
143151

144152
pattern = re.compile(r'[&;<>\"\'()|\[\]{}$#!%*+=]')
145153
if pattern.search(self.params):
146-
self.socketio.emit('nexttrace_output', 'Invalid params', room=self.sid)
154+
self.emit_error_row('参数不合法,任务未启动')
147155
self.emit_complete()
148-
raise ValueError('Invalid params')
156+
return
149157
logging.debug(f"cmd: {[self.nexttrace_path] + self.params.split() + fixParam.split()}")
150-
self.process = subprocess.Popen(
151-
[self.nexttrace_path] + self.params.split() + fixParam.split(),
152-
stdout=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True, env=process_env, bufsize=1
153-
)
158+
try:
159+
self.process = subprocess.Popen(
160+
[self.nexttrace_path] + self.params.split() + fixParam.split(),
161+
stdout=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True, env=process_env, bufsize=1
162+
)
163+
except OSError as exc:
164+
logging.error(f"Failed to start nexttrace for client {self.sid}: {exc}")
165+
self.emit_error_row('启动 nexttrace 失败,请检查服务器配置')
166+
self.emit_complete()
167+
return
154168
output_monitor = OutputMonitor(self.process, self.socketio, self.sid, options)
155169
output_monitor_flag = True
156170

0 commit comments

Comments
 (0)