Skip to content

Commit 965d462

Browse files
committed
Fixed deadlocks in page event handling
1 parent 8f0dfbb commit 965d462

6 files changed

Lines changed: 87 additions & 18 deletions

File tree

examples/autoscroll.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
import logging
2+
13
import pglet
2-
from pglet import Text, Stack, Button, Image
4+
from pglet import Button, Image, Stack, Text
5+
6+
logging.basicConfig(level=logging.DEBUG)
37

48
page = pglet.page("autoscroll", update=False, no_window=True, permissions="")
59
# page.theme_primary_color = "green"

examples/chat.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import logging
2+
23
import pglet
3-
from pglet import Stack, Button, Textbox, Text, Dialog
4+
from pglet import Button, Dialog, Stack, Text, Textbox
45

56
logging.basicConfig(level=logging.DEBUG)
67

examples/stack.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import logging
2+
3+
import pglet
4+
from pglet import Slider, Stack, Text
5+
6+
logging.basicConfig(level=logging.DEBUG)
7+
8+
with pglet.page("horizontal-stack-wrapping") as page:
9+
10+
bg_color = "#ddddee"
11+
page.horizontal_align = "stretch"
12+
13+
def items(count):
14+
items = []
15+
for i in range(1, count + 1):
16+
items.append(
17+
Text(
18+
value=i,
19+
align="center",
20+
vertical_align="center",
21+
width=30,
22+
height=30,
23+
bgcolor="BlueMagenta10",
24+
color="white",
25+
padding=5,
26+
)
27+
)
28+
return items
29+
30+
def wrap_slider_change(e):
31+
print("wrap_slider_change", e)
32+
width = int(e.control.value)
33+
wrap_stack.width = f"{width}%"
34+
wrap_stack.update()
35+
36+
wrap_slider = Slider(
37+
"Change the stack width to see how child items wrap onto multiple rows:",
38+
min=0,
39+
max=100,
40+
step=1,
41+
value=100,
42+
show_value=True,
43+
value_format="{value}%",
44+
on_change=wrap_slider_change,
45+
)
46+
47+
wrap_stack = Stack(
48+
horizontal=True, wrap=True, bgcolor=bg_color, gap=20, controls=items(10)
49+
)
50+
51+
page.add(wrap_slider, wrap_stack)
52+
53+
input()

pglet/connection.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@
44
import uuid
55

66
from pglet.event import Event
7-
8-
from pglet.reconnecting_websocket import ReconnectingWebSocket
97
from pglet.protocol import *
8+
from pglet.reconnecting_websocket import ReconnectingWebSocket
109

1110

1211
class Connection:
@@ -49,7 +48,16 @@ def _on_message(self, data):
4948
evt.set()
5049
elif msg.action == Actions.PAGE_EVENT_TO_HOST:
5150
if self._on_event != None:
52-
self._on_event(self, PageEventPayload(**msg.payload))
51+
th = threading.Thread(
52+
target=self._on_event,
53+
args=(
54+
self,
55+
PageEventPayload(**msg.payload),
56+
),
57+
daemon=True,
58+
)
59+
th.start()
60+
# self._on_event(self, PageEventPayload(**msg.payload))
5361
elif msg.action == Actions.SESSION_CREATED:
5462
if self._on_session_created != None:
5563
th = threading.Thread(

pglet/page.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import logging
33
import threading
44
from typing import List, Literal, Optional
5+
56
from beartype import beartype
67

78
from pglet import constants
@@ -149,8 +150,8 @@ def error(self, message=""):
149150
def on_event(self, e):
150151
logging.info(f"page.on_event: {e.target} {e.name} {e.data}")
151152

152-
if e.target == "page" and e.name == "change":
153-
with self._lock:
153+
with self._lock:
154+
if e.target == "page" and e.name == "change":
154155
for props in json.loads(e.data):
155156
id = props["i"]
156157
if id in self._index:
@@ -160,17 +161,17 @@ def on_event(self, e):
160161
name, props[name], dirty=False
161162
)
162163

163-
elif e.target in self._index:
164-
self._last_event = ControlEvent(
165-
e.target, e.name, e.data, self._index[e.target], self
166-
)
167-
handler = self._index[e.target].event_handlers.get(e.name)
168-
if handler:
169-
t = threading.Thread(
170-
target=handler, args=(self._last_event,), daemon=True
164+
elif e.target in self._index:
165+
self._last_event = ControlEvent(
166+
e.target, e.name, e.data, self._index[e.target], self
171167
)
172-
t.start()
173-
self._event_available.set()
168+
handler = self._index[e.target].event_handlers.get(e.name)
169+
if handler:
170+
t = threading.Thread(
171+
target=handler, args=(self._last_event,), daemon=True
172+
)
173+
t.start()
174+
self._event_available.set()
174175

175176
def wait_event(self):
176177
self._event_available.clear()

pglet/reconnecting_websocket.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import logging
2-
import random, threading
2+
import random
3+
import threading
34

45
import websocket
56

@@ -80,6 +81,7 @@ def _connect_loop(self):
8081
while not self.exit.is_set():
8182
logging.info(f"Connecting Pglet Server at {self._url}...")
8283
r = self.wsapp.run_forever()
84+
logging.debug(f"Exited run_forever()")
8385
self.connected.clear()
8486
if r != True:
8587
return

0 commit comments

Comments
 (0)