Skip to content
This repository was archived by the owner on Apr 26, 2023. It is now read-only.

Commit d8788ea

Browse files
committed
Fixes Toufool#86 Stop uncaught exceptions from silently crashing the app
1 parent c1b8c85 commit d8788ea

File tree

3 files changed

+62
-20
lines changed

3 files changed

+62
-20
lines changed

src/AutoSplit.py

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
#!/usr/bin/python3.9
22
# -*- coding: utf-8 -*-
3-
from types import FunctionType
4-
from typing import Callable, List, Optional
3+
import traceback
4+
from types import FunctionType, TracebackType
5+
from typing import Callable, List, Optional, Type
56

67
from copy import copy
78
from PyQt6 import QtCore, QtGui, QtTest, QtWidgets
@@ -1197,22 +1198,47 @@ def exit():
11971198

11981199
def main():
11991200
app = QtWidgets.QApplication(sys.argv)
1200-
app.setWindowIcon(QtGui.QIcon(':/resources/icon.ico'))
1201-
1202-
main_window = AutoSplit()
1203-
main_window.show()
1204-
if main_window.actionCheck_for_Updates_on_Open.isChecked():
1205-
checkForUpdates(main_window, check_for_updates_on_open=True)
1201+
try:
1202+
app.setWindowIcon(QtGui.QIcon(':/resources/icon.ico'))
1203+
main_window = AutoSplit()
1204+
main_window.show()
1205+
# Needs to be after main_window.show() to be shown over
1206+
if main_window.actionCheck_for_Updates_on_Open.isChecked():
1207+
checkForUpdates(main_window, check_for_updates_on_open=True)
1208+
1209+
# Kickoff the event loop every so often so we can handle KeyboardInterrupt (^C)
1210+
timer = QtCore.QTimer()
1211+
timer.timeout.connect(lambda: None)
1212+
timer.start(500)
1213+
1214+
exit_code = app.exec()
1215+
except Exception as exception:
1216+
# Print error to console if not running in executable
1217+
if getattr(sys, 'frozen', False):
1218+
error_messages.exceptionTraceback(
1219+
"AutoSplit encountered an unrecoverable exception and will now close itself.<br/>"
1220+
"Please copy the following message over at<br/>"
1221+
"<a href='https://github.com/Toufool/Auto-Split/issues'>github.com/Toufool/Auto-Split/issues</a>",
1222+
exception)
1223+
else:
1224+
traceback.print_exception(type(exception), exception, exception.__traceback__)
1225+
sys.exit(1)
12061226

1207-
# Kickoff the event loop every so often so we can handle KeyboardInterrupt (^C)
1208-
timer = QtCore.QTimer()
1209-
timer.timeout.connect(lambda: None)
1210-
timer.start(500)
12111227
# Catch Keyboard Interrupts for a clean close
1212-
signal.signal(signal.SIGINT, lambda _, __: sys.exit(app))
1228+
signal.signal(signal.SIGINT, lambda _, __: sys.exit(exit_code))
1229+
1230+
sys.exit(exit_code)
1231+
12131232

1214-
sys.exit(app.exec())
1233+
def excepthook(type: Type[BaseException], exception: BaseException, traceback: Optional[TracebackType]):
1234+
error_messages.exceptionTraceback(
1235+
"AutoSplit encountered an unhandled exception and will try to recover, "
1236+
"however, things may not work quite right.<br/>"
1237+
"Please copy the following message over at<br/>"
1238+
"<a href='https://github.com/Toufool/Auto-Split/issues'>github.com/Toufool/Auto-Split/issues</a>",
1239+
exception)
12151240

12161241

12171242
if __name__ == '__main__':
1243+
sys.excepthook = excepthook
12181244
main()

src/capture_windows.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ def __get_image(hwnd: int, rect: RECT, print_window: bool = False):
5555
# Causes a 10-15x performance drop. But allows recording hardware accelerated windows
5656
if (print_window):
5757
windll.user32.PrintWindow(hwnd, dcObject.GetSafeHdc(), PW_RENDERFULLCONTENT)
58+
else:
59+
windll.user32.PrintWindow(hwnd, dcObject.GetSafeHdc())
5860

5961
compatibleDC = dcObject.CreateCompatibleDC()
6062
bitmap: HBITMAP = win32ui.CreateBitmap()

src/error_messages.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
# Error messages
2-
from PyQt6 import QtWidgets
2+
import traceback
3+
from PyQt6 import QtCore, QtWidgets
34

45

5-
def setTextMessage(message: str):
6-
msgBox = QtWidgets.QMessageBox()
7-
msgBox.setWindowTitle('Error')
8-
msgBox.setText(message)
9-
msgBox.exec()
6+
def setTextMessage(message: str, details: str = ''):
7+
messageBox = QtWidgets.QMessageBox()
8+
messageBox.setWindowTitle('Error')
9+
messageBox.setTextFormat(QtCore.Qt.TextFormat.RichText)
10+
messageBox.setText(message)
11+
if details:
12+
messageBox.setDetailedText(details)
13+
for button in messageBox.buttons():
14+
if messageBox.buttonRole(button) == QtWidgets.QMessageBox.ButtonRole.ActionRole:
15+
button.click()
16+
break
17+
messageBox.exec()
1018

1119

1220
def splitImageDirectoryError():
@@ -83,3 +91,9 @@ def checkForUpdatesError():
8391

8492
def stdinLostError():
8593
setTextMessage("stdin not supported or lost, external control like LiveSplit integration will not work.")
94+
95+
96+
def exceptionTraceback(message: str, exception: Exception):
97+
setTextMessage(
98+
message,
99+
"\n".join(traceback.format_exception(None, exception, exception.__traceback__)))

0 commit comments

Comments
 (0)