Skip to content

Commit 8602d3d

Browse files
authored
Merge pull request #414 from simvue-io/hotfix/kill-all-on-exception
Add runtime error handling for Remote class to prevent heartbeat thread hang
2 parents b56427b + 6c0b08f commit 8602d3d

File tree

1 file changed

+77
-18
lines changed

1 file changed

+77
-18
lines changed

simvue/run.py

Lines changed: 77 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -168,12 +168,16 @@ def __exit__(
168168
self.set_status("completed")
169169
else:
170170
if self._active:
171-
self.log_event(f"{exc_type.__name__}: {value}")
171+
# If the dispatcher has already been aborted then this will
172+
# fail so just continue without the event
173+
with contextlib.suppress(RuntimeError):
174+
self.log_event(f"{exc_type.__name__}: {value}")
172175
if exc_type.__name__ in ("KeyboardInterrupt",) and self._active:
173176
self.set_status("terminated")
174177
else:
175178
if traceback and self._active:
176-
self.log_event(f"Traceback: {traceback}")
179+
with contextlib.suppress(RuntimeError):
180+
self.log_event(f"Traceback: {traceback}")
177181
self.set_status("failed")
178182
else:
179183
if self._shutdown_event is not None:
@@ -984,7 +988,12 @@ def update_tags(self, tags: list[str]) -> bool:
984988

985989
if not self._simvue:
986990
return False
987-
current_tags: list[str] = self._simvue.list_tags() or []
991+
992+
try:
993+
current_tags: list[str] = self._simvue.list_tags() or []
994+
except RuntimeError as e:
995+
self._error(f"{e.args[0]}")
996+
return False
988997

989998
try:
990999
self.set_tags(list(set(current_tags + tags)))
@@ -1012,6 +1021,9 @@ def log_event(self, message: str, timestamp: typing.Optional[str] = None) -> boo
10121021
bool
10131022
whether event log was successful
10141023
"""
1024+
if self._aborted:
1025+
return False
1026+
10151027
if self._mode == "disabled":
10161028
self._error("Cannot log events in 'disabled' state")
10171029
return True
@@ -1169,7 +1181,13 @@ def save_object(
11691181
}
11701182

11711183
# Register file
1172-
return self._simvue is not None and self._simvue.save_file(data) is not None
1184+
try:
1185+
file_save = self._simvue.save_file(data)
1186+
except RuntimeError as e:
1187+
self._error(f"{e.args[0]}")
1188+
return False
1189+
1190+
return self._simvue is not None and file_save is not None
11731191

11741192
@skip_if_failed("_aborted", "_suppress_errors", False)
11751193
@check_run_initialised
@@ -1256,7 +1274,11 @@ def save_file(
12561274
return True
12571275

12581276
# Register file
1259-
return self._simvue.save_file(data) is not None
1277+
try:
1278+
return self._simvue.save_file(data) is not None
1279+
except RuntimeError as e:
1280+
self._error(f"{e.args[0]}")
1281+
return False
12601282

12611283
@skip_if_failed("_aborted", "_suppress_errors", False)
12621284
@check_run_initialised
@@ -1386,7 +1408,13 @@ def set_status(
13861408
data: dict[str, str] = {"name": self._name, "status": status}
13871409
self._status = status
13881410

1389-
if self._simvue and self._simvue.update(data):
1411+
try:
1412+
updated = self._simvue.update(data)
1413+
except RuntimeError as e:
1414+
self._error(f"{e.args[0]}")
1415+
return False
1416+
1417+
if self._simvue and updated:
13901418
return True
13911419

13921420
return False
@@ -1496,8 +1524,12 @@ def set_folder_details(
14961524
if description:
14971525
data["description"] = description
14981526

1499-
if self._simvue.set_folder_details(data):
1500-
return True
1527+
try:
1528+
if self._simvue.set_folder_details(data):
1529+
return True
1530+
except RuntimeError as e:
1531+
self._error(f"{e.args[0]}")
1532+
return False
15011533

15021534
return False
15031535

@@ -1531,10 +1563,14 @@ def add_alerts(
15311563
names = names or []
15321564

15331565
if names and not ids:
1534-
if alerts := self._simvue.list_alerts():
1535-
for alert in alerts:
1536-
if alert["name"] in names:
1537-
ids.append(alert["id"])
1566+
try:
1567+
if alerts := self._simvue.list_alerts():
1568+
for alert in alerts:
1569+
if alert["name"] in names:
1570+
ids.append(alert["id"])
1571+
except RuntimeError as e:
1572+
self._error(f"{e.args[0]}")
1573+
return False
15381574
else:
15391575
self._error("No existing alerts")
15401576
return False
@@ -1544,8 +1580,12 @@ def add_alerts(
15441580

15451581
data: dict[str, typing.Any] = {"id": self._id, "alerts": ids}
15461582

1547-
if self._simvue.update(data):
1548-
return True
1583+
try:
1584+
if self._simvue.update(data):
1585+
return True
1586+
except RuntimeError as e:
1587+
self._error(f"{e.args[0]}")
1588+
return False
15491589

15501590
return False
15511591

@@ -1689,7 +1729,12 @@ def create_alert(
16891729

16901730
# Check if the alert already exists
16911731
alert_id: typing.Optional[str] = None
1692-
alerts = self._simvue.list_alerts()
1732+
try:
1733+
alerts = self._simvue.list_alerts()
1734+
except RuntimeError as e:
1735+
self._error(f"{e.args[0]}")
1736+
return alerts
1737+
16931738
if alerts:
16941739
for existing_alert in alerts:
16951740
if existing_alert["name"] == alert["name"]:
@@ -1699,7 +1744,11 @@ def create_alert(
16991744
break
17001745

17011746
if not alert_id:
1702-
response = self._simvue.add_alert(alert)
1747+
try:
1748+
response = self._simvue.add_alert(alert)
1749+
except RuntimeError as e:
1750+
self._error(f"{e.args[0]}")
1751+
return False
17031752
if response:
17041753
if "id" in response:
17051754
alert_id = response["id"]
@@ -1710,7 +1759,12 @@ def create_alert(
17101759
if alert_id:
17111760
# TODO: What if we keep existing alerts/add a new one later?
17121761
data = {"id": self._id, "alerts": [alert_id], "abort": trigger_abort}
1713-
self._simvue.update(data)
1762+
1763+
try:
1764+
self._simvue.update(data)
1765+
except RuntimeError as e:
1766+
self._error(f"{e.args[0]}")
1767+
return False
17141768

17151769
return alert_id
17161770

@@ -1740,6 +1794,11 @@ def log_alert(
17401794
if not self._simvue:
17411795
self._error("Cannot log alert, run not initialised")
17421796
return False
1743-
self._simvue.set_alert_state(identifier, state)
1797+
1798+
try:
1799+
self._simvue.set_alert_state(identifier, state)
1800+
except RuntimeError as e:
1801+
self._error(f"{e.args[0]}")
1802+
return False
17441803

17451804
return True

0 commit comments

Comments
 (0)