Skip to content

Commit 74a20c5

Browse files
Fix terminals (#414)
* Fix terminals * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 33d7076 commit 74a20c5

File tree

3 files changed

+27
-47
lines changed

3 files changed

+27
-47
lines changed

jupyverse_api/jupyverse_api/terminals/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,5 +83,5 @@ async def serve(self, websocket, permissions):
8383
...
8484

8585
@abstractmethod
86-
def quit(self, websocket):
86+
async def exit(self):
8787
...

plugins/terminals/fps_terminals/routes.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,7 @@ async def delete_terminal(
4545
name: str,
4646
user: User,
4747
):
48-
for websocket in TERMINALS[name]["server"].websockets:
49-
TERMINALS[name]["server"].quit(websocket)
50-
del TERMINALS[name]
48+
await TERMINALS[name]["server"].exit(TERMINALS, name)
5149
return Response(status_code=HTTPStatus.NO_CONTENT.value)
5250

5351
async def terminal_websocket(
@@ -59,8 +57,4 @@ async def terminal_websocket(
5957
return
6058
websocket, permissions = websocket_permissions
6159
await websocket.accept()
62-
await TERMINALS[name]["server"].serve(websocket, permissions)
63-
if name in TERMINALS:
64-
TERMINALS[name]["server"].quit(websocket)
65-
if not TERMINALS[name]["server"].websockets:
66-
del TERMINALS[name]
60+
await TERMINALS[name]["server"].serve(websocket, permissions, TERMINALS, name)

plugins/terminals/fps_terminals/server.py

Lines changed: 24 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
import struct
77
import termios
88

9-
from fastapi import WebSocketDisconnect
10-
119
from jupyverse_api.terminals import TerminalServer
1210

1311

@@ -25,35 +23,26 @@ class _TerminalServer(TerminalServer):
2523
def __init__(self):
2624
self.fd = open_terminal()
2725
self.p_out = os.fdopen(self.fd, "w+b", 0)
28-
self.websockets = []
29-
30-
async def serve(self, websocket, permissions):
31-
self.websocket = websocket
32-
self.websockets.append(websocket)
33-
self.data_from_terminal = asyncio.Queue()
3426
self.loop = asyncio.get_event_loop()
35-
36-
task = asyncio.create_task(self.send_data()) # noqa: F841
27+
self.data_from_terminal = asyncio.Queue()
28+
self.websockets = []
3729

3830
def on_output():
3931
try:
4032
data = self.p_out.read(65536).decode()
41-
except OSError:
42-
try:
43-
self.loop.remove_reader(self.p_out)
44-
except Exception:
45-
pass
46-
try:
47-
os.close(self.fd)
48-
except OSError:
49-
pass
33+
except Exception:
5034
self.data_from_terminal.put_nowait(None)
51-
self.websockets.clear()
52-
self.quit()
5335
else:
5436
self.data_from_terminal.put_nowait(data)
5537

5638
self.loop.add_reader(self.p_out, on_output)
39+
40+
async def serve(self, websocket, permissions, terminals, name):
41+
self.websocket = websocket
42+
self.websockets.append(websocket)
43+
44+
task = asyncio.create_task(self.send_data(terminals, name)) # noqa: F841
45+
5746
await websocket.send_json(["setup", {}])
5847
can_execute = permissions is None or "execute" in permissions.get("terminals", [])
5948
try:
@@ -65,32 +54,29 @@ def on_output():
6554
elif msg[0] == "set_size":
6655
winsize = struct.pack("HH", msg[1], msg[2])
6756
fcntl.ioctl(self.fd, termios.TIOCSWINSZ, winsize)
68-
except WebSocketDisconnect:
69-
self.quit(websocket)
57+
except Exception:
58+
if websocket in self.websockets:
59+
self.websockets.remove(websocket)
7060

71-
async def send_data(self):
61+
async def send_data(self, terminals, name):
7262
while True:
7363
data = await self.data_from_terminal.get()
7464
if data is None:
75-
try:
76-
await self.websocket.send_json(["disconnect", 1])
77-
except Exception:
78-
pass
65+
await self.exit(terminals, name)
7966
return
8067

8168
for websocket in self.websockets:
8269
await websocket.send_json(["stdout", data])
8370

84-
def quit(self, websocket=None):
85-
if websocket in self.websockets:
86-
self.websockets.remove(websocket)
87-
if not self.websockets:
71+
async def exit(self, terminals, name):
72+
for websocket in self.websockets:
8873
try:
89-
self.loop.remove_reader(self.p_out)
74+
await websocket.send_json(["disconnect", 1])
9075
except Exception:
9176
pass
92-
try:
93-
os.close(self.fd)
94-
except OSError:
95-
pass
96-
self.data_from_terminal.put_nowait(None)
77+
self.websockets.clear()
78+
try:
79+
self.loop.remove_reader(self.p_out)
80+
except Exception:
81+
pass
82+
del terminals[name]

0 commit comments

Comments
 (0)