Skip to content

Commit

Permalink
Fix race condition in guiEditor
Browse files Browse the repository at this point in the history
Signed-off-by: Loren Eteval <[email protected]>
  • Loading branch information
LorenEteval committed May 13, 2024
1 parent 9a5d353 commit 5218c5e
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 70 deletions.
4 changes: 4 additions & 0 deletions Furious/QtFramework/GuiEditorXXX.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,10 @@ def groupBoxSequence(self) -> Sequence[GuiEditorWidgetQGroupBox]:
def setTabText(self, text: str):
self.tabWidget.setTabText(0, text)

def closeEvent(self, event):
self.accepted.disconnect()
self.rejected.disconnect()

def inputToFactory(self, config: ConfigurationFactory) -> bool:
modified = False

Expand Down
149 changes: 79 additions & 70 deletions Furious/Widget/UserServersQTableWidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
import logging
import icmplib
import functools
import threading

__all__ = ['UserServersQTableWidget']

Expand Down Expand Up @@ -813,8 +812,6 @@ def __init__(self, *args, **kwargs):
# Distinguish double-click and activated
self.doubleClickedFlag = False

self.guiEditorMutex = threading.Lock()

# Signals
self.itemChanged.connect(self.handleItemChanged)
self.itemSelectionChanged.connect(self.handleItemSelectionChanged)
Expand Down Expand Up @@ -918,67 +915,73 @@ def getGuiEditorByFactory(self, factory, **kwargs):

@QtCore.Slot(QTableWidgetItem)
def handleItemDoubleClicked(self, item: QTableWidgetItem):
with self.guiEditorMutex:
self.doubleClickedFlag = True

index = item.row()
factory = AS_UserServers()[index]
self.doubleClickedFlag = True

guiEditor = self.getGuiEditorByFactory(factory, translatable=False)
index = item.row()
factory = AS_UserServers()[index]

if guiEditor is None:
# Unrecognized. Do nothing
return
guiEditor = self.getGuiEditorByFactory(factory, translatable=False)

# Dummy ref
setattr(self, '_guiEditorRef0', guiEditor)
if guiEditor is None:
# Unrecognized. Do nothing
return

guiEditor.setWindowTitle(f'{index + 1} - ' + factory.getExtras('remark'))
guiEditor.setWindowTitle(f'{index + 1} - ' + factory.getExtras('remark'))

try:
guiEditor.factoryToInput(factory)
except Exception as ex:
# Any non-exit exceptions
try:
guiEditor.factoryToInput(factory)
except Exception as ex:
# Any non-exit exceptions

logger.error(f'error while converting factory to input: {ex}')
logger.error(f'error while converting factory to input: {ex}')

guiEditor.accepted.connect(
functools.partial(
self.handleGuiEditorAccepted,
guiEditor,
index,
factory,
)
guiEditor.accepted.connect(
functools.partial(
self.handleGuiEditorAccepted,
guiEditor,
index,
factory,
)
)
guiEditor.rejected.connect(
functools.partial(
self.handleGuiEditorRejected,
guiEditor,
)
guiEditor.open()
)
guiEditor.open()

def handleGuiEditorAccepted(
self,
editor: GuiEditorWidgetQDialog,
index: int,
factory: ConfigurationFactory,
):
with self.guiEditorMutex:
logger.debug(f'guiEditor accepted with index {index}')
logger.debug(f'guiEditor accepted with index {index}')

modified = editor.inputToFactory(factory)
modified = editor.inputToFactory(factory)

# Still flush to row since remark may be modified
self.flushRow(index, factory)
# Still flush to row since remark may be modified
self.flushRow(index, factory)

if modified and index == AS_UserActivatedItemIndex():
try:
if APP().isSystemTrayConnected():
mbox = NewChangesNextTimeMBox()
if modified and index == AS_UserActivatedItemIndex():
try:
if APP().isSystemTrayConnected():
mbox = NewChangesNextTimeMBox()

# Show the MessageBox asynchronously
mbox.open()
except Exception:
# Any non-exit exceptions
# Show the MessageBox asynchronously
mbox.open()
except Exception:
# Any non-exit exceptions

pass
pass

editor.accepted.disconnect()
editor.accepted.disconnect()
editor.rejected.disconnect()

def handleGuiEditorRejected(self, editor: GuiEditorWidgetQDialog):
editor.accepted.disconnect()
editor.rejected.disconnect()

@QtCore.Slot(QtCore.QPoint)
def handleCustomContextMenuRequested(self, point):
Expand Down Expand Up @@ -1079,47 +1082,53 @@ def addServerViaGui(
windowTitle: str = APPLICATION_NAME,
**kwargs,
):
with self.guiEditorMutex:
factory = getEmptyFactory(protocol)

guiEditor = self.getGuiEditorByFactory(factory, **kwargs)
factory = getEmptyFactory(protocol)

if guiEditor is None:
# Unrecognized. Do nothing
return
guiEditor = self.getGuiEditorByFactory(factory, **kwargs)

# Dummy ref
setattr(self, '_guiEditorRef1', guiEditor)
if guiEditor is None:
# Unrecognized. Do nothing
return

guiEditor.setWindowTitle(windowTitle)
guiEditor.setWindowTitle(windowTitle)

try:
guiEditor.factoryToInput(factory)
except Exception as ex:
# Any non-exit exceptions
try:
guiEditor.factoryToInput(factory)
except Exception as ex:
# Any non-exit exceptions

logger.error(f'error while converting factory to input: {ex}')
logger.error(f'error while converting factory to input: {ex}')

guiEditor.accepted.connect(
functools.partial(
self.handleAddServerViaGui,
guiEditor,
factory,
)
guiEditor.accepted.connect(
functools.partial(
self.handleAddServerViaGuiAccepted,
guiEditor,
factory,
)
)
guiEditor.rejected.connect(
functools.partial(
self.handleAddServerViaGuiRejected,
guiEditor,
)
guiEditor.open()
)
guiEditor.open()

def handleAddServerViaGui(
def handleAddServerViaGuiAccepted(
self,
editor: GuiEditorWidgetQDialog,
factory: ConfigurationFactory,
):
with self.guiEditorMutex:
editor.inputToFactory(factory)
editor.inputToFactory(factory)

self.appendNewItemByFactory(factory)
self.appendNewItemByFactory(factory)

editor.accepted.disconnect()
editor.rejected.disconnect()

editor.accepted.disconnect()
def handleAddServerViaGuiRejected(self, editor: GuiEditorWidgetQDialog):
editor.accepted.disconnect()
editor.rejected.disconnect()

def flushRow(self, row: int, item: ConfigurationFactory):
for column in list(range(self.columnCount())):
Expand Down

0 comments on commit 5218c5e

Please sign in to comment.