This commit is contained in:
dengqichen 2025-12-31 09:54:03 +08:00
parent d9b8142028
commit c82bb937d1

View File

@ -713,6 +713,9 @@ public abstract class AbstractSSHWebSocketHandler extends TextWebSocketHandler {
/** /**
* 发送输出消息到前端使用强类型Response * 发送输出消息到前端使用强类型Response
* *
* <p> 线程安全使用synchronized同步防止stdout和stderr线程并发写入导致
* {@code IllegalStateException: TEXT_PARTIAL_WRITING} 错误
*
* @param session WebSocket会话 * @param session WebSocket会话
* @param output 输出内容 * @param output 输出内容
*/ */
@ -734,7 +737,13 @@ public abstract class AbstractSSHWebSocketHandler extends TextWebSocketHandler {
// 创建消息 // 创建消息
SSHWebSocketMessage msg = new SSHWebSocketMessage(SSHMessageType.OUTPUT, data); SSHWebSocketMessage msg = new SSHWebSocketMessage(SSHMessageType.OUTPUT, data);
session.sendMessage(new TextMessage(JsonUtils.toJson(msg)));
// 关键同步发送防止并发写入导致TEXT_PARTIAL_WRITING错误
synchronized (session) {
if (session.isOpen()) {
session.sendMessage(new TextMessage(JsonUtils.toJson(msg)));
}
}
} catch (IOException e) { } catch (IOException e) {
log.error("发送输出消息失败(IOException): sessionId={}", sessionId, e); log.error("发送输出消息失败(IOException): sessionId={}", sessionId, e);
} catch (Exception e) { } catch (Exception e) {
@ -744,6 +753,8 @@ public abstract class AbstractSSHWebSocketHandler extends TextWebSocketHandler {
/** /**
* 发送状态消息到前端使用强类型Response * 发送状态消息到前端使用强类型Response
*
* <p> 线程安全使用synchronized同步防止并发写入
*/ */
protected void sendStatus(WebSocketSession session, SSHStatusEnum status) { protected void sendStatus(WebSocketSession session, SSHStatusEnum status) {
try { try {
@ -761,7 +772,13 @@ public abstract class AbstractSSHWebSocketHandler extends TextWebSocketHandler {
// 创建消息 // 创建消息
SSHWebSocketMessage msg = new SSHWebSocketMessage(SSHMessageType.STATUS, data); SSHWebSocketMessage msg = new SSHWebSocketMessage(SSHMessageType.STATUS, data);
session.sendMessage(new TextMessage(JsonUtils.toJson(msg)));
// 同步发送防止并发写入
synchronized (session) {
if (session.isOpen()) {
session.sendMessage(new TextMessage(JsonUtils.toJson(msg)));
}
}
} catch (IOException e) { } catch (IOException e) {
log.error("发送状态消息失败: sessionId={}", session.getId(), e); log.error("发送状态消息失败: sessionId={}", session.getId(), e);
} }
@ -769,6 +786,8 @@ public abstract class AbstractSSHWebSocketHandler extends TextWebSocketHandler {
/** /**
* 发送错误消息到前端使用强类型Response * 发送错误消息到前端使用强类型Response
*
* <p> 线程安全使用synchronized同步防止并发写入
*/ */
protected void sendError(WebSocketSession session, String error) { protected void sendError(WebSocketSession session, String error) {
try { try {
@ -786,7 +805,13 @@ public abstract class AbstractSSHWebSocketHandler extends TextWebSocketHandler {
// 创建消息 // 创建消息
SSHWebSocketMessage msg = new SSHWebSocketMessage(SSHMessageType.ERROR, data); SSHWebSocketMessage msg = new SSHWebSocketMessage(SSHMessageType.ERROR, data);
session.sendMessage(new TextMessage(JsonUtils.toJson(msg)));
// 同步发送防止并发写入
synchronized (session) {
if (session.isOpen()) {
session.sendMessage(new TextMessage(JsonUtils.toJson(msg)));
}
}
} catch (IOException e) { } catch (IOException e) {
if (session.isOpen()) { if (session.isOpen()) {
log.error("发送错误消息失败: sessionId={}", session.getId(), e); log.error("发送错误消息失败: sessionId={}", session.getId(), e);