客户端断开连接后,文件描述符已经被关闭,但仍有事件在处理中:对 app/sockets/terminal_service.py 文件进行了全面修复
This commit is contained in:
@@ -29,8 +29,12 @@ terminal_bp = Blueprint('terminal', __name__, url_prefix='/vsc-like')
|
|||||||
|
|
||||||
|
|
||||||
def set_winsize(fd, row, col, xpix=0, ypix=0):
|
def set_winsize(fd, row, col, xpix=0, ypix=0):
|
||||||
winsize = struct.pack("HHHH", row, col, xpix, ypix)
|
try:
|
||||||
fcntl.ioctl(fd, termios.TIOCSWINSZ, winsize)
|
winsize = struct.pack("HHHH", row, col, xpix, ypix)
|
||||||
|
fcntl.ioctl(fd, termios.TIOCSWINSZ, winsize)
|
||||||
|
except (OSError, IOError):
|
||||||
|
# File descriptor closed or invalid, do nothing
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def read_and_forward_pty_output(fd=None, pid=None, room_id=None,namespace=None):
|
def read_and_forward_pty_output(fd=None, pid=None, room_id=None,namespace=None):
|
||||||
@@ -172,7 +176,13 @@ class VSCLikeNameSpace(Namespace):
|
|||||||
if fd:
|
if fd:
|
||||||
# print("writing to ptd: %s" % data["input"])
|
# print("writing to ptd: %s" % data["input"])
|
||||||
# os.write(fd, data["input"].encode('ascii'))
|
# os.write(fd, data["input"].encode('ascii'))
|
||||||
os.write(fd, data["input"].encode())
|
try:
|
||||||
|
os.write(fd, data["input"].encode())
|
||||||
|
except (OSError, IOError):
|
||||||
|
# File descriptor closed or invalid, clean up
|
||||||
|
disconnect()
|
||||||
|
session['terminal_config'] = TERM_INIT_CONFIG
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
def on_resize(self, data):
|
def on_resize(self, data):
|
||||||
@@ -188,10 +198,29 @@ class VSCLikeNameSpace(Namespace):
|
|||||||
return
|
return
|
||||||
fd = session.get('terminal_config').get('fd')
|
fd = session.get('terminal_config').get('fd')
|
||||||
if fd:
|
if fd:
|
||||||
set_winsize(fd, data["rows"], data["cols"])
|
# 检查文件描述符是否有效
|
||||||
|
try:
|
||||||
|
# 尝试一个简单的操作来检查文件描述符是否有效
|
||||||
|
os.fstat(fd)
|
||||||
|
set_winsize(fd, data["rows"], data["cols"])
|
||||||
|
except (OSError, IOError):
|
||||||
|
# 文件描述符无效,清理资源
|
||||||
|
disconnect()
|
||||||
|
session['terminal_config'] = TERM_INIT_CONFIG
|
||||||
|
return
|
||||||
|
|
||||||
def on_disconnect(self):
|
def on_disconnect(self):
|
||||||
child_pid = session.get('terminal_config', {}).get('child_pid')
|
terminal_config = session.get('terminal_config', {})
|
||||||
|
child_pid = terminal_config.get('child_pid')
|
||||||
|
fd = terminal_config.get('fd')
|
||||||
|
|
||||||
|
# 先关闭文件描述符,避免其他操作尝试使用无效的文件描述符
|
||||||
|
if fd:
|
||||||
|
try:
|
||||||
|
os.close(fd)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
if child_pid:
|
if child_pid:
|
||||||
try:
|
try:
|
||||||
child_process = psutil.Process(child_pid)
|
child_process = psutil.Process(child_pid)
|
||||||
@@ -210,21 +239,14 @@ class VSCLikeNameSpace(Namespace):
|
|||||||
pass
|
pass
|
||||||
except psutil.TimeoutExpired:
|
except psutil.TimeoutExpired:
|
||||||
# If process didn't terminate in time, kill it forcefully
|
# If process didn't terminate in time, kill it forcefully
|
||||||
child_process.kill()
|
|
||||||
try:
|
try:
|
||||||
|
child_process.kill()
|
||||||
child_process.wait(timeout=1)
|
child_process.wait(timeout=1)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
current_app.logger.error(f'Error terminating process: {err}')
|
current_app.logger.error(f'Error terminating process: {err}')
|
||||||
finally:
|
|
||||||
# Close the file descriptor if it's open
|
# Reset session config
|
||||||
fd = session.get('terminal_config', {}).get('fd')
|
session['terminal_config'] = TERM_INIT_CONFIG
|
||||||
if fd:
|
|
||||||
try:
|
|
||||||
os.close(fd)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
# Reset session config
|
|
||||||
session['terminal_config'] = TERM_INIT_CONFIG
|
|
||||||
current_app.logger.debug('Client disconnected')
|
current_app.logger.debug('Client disconnected')
|
||||||
Reference in New Issue
Block a user