diff --git a/GUI/LoadingDialog.py b/GUI/LoadingDialog.py
index 13e4fd9a..5efff741 100644
--- a/GUI/LoadingDialog.py
+++ b/GUI/LoadingDialog.py
@@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'LoadingDialog.ui'
#
-# Created: Wed Dec 7 19:30:07 2016
+# Created: Tue Feb 21 22:38:30 2017
# by: PyQt5 UI code generator 5.2.1
#
# WARNING! All changes made in this file will be lost!
@@ -12,9 +12,9 @@
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
- Dialog.resize(195, 40)
- self.gridLayout = QtWidgets.QGridLayout(Dialog)
- self.gridLayout.setObjectName("gridLayout")
+ Dialog.resize(208, 89)
+ self.gridLayout_2 = QtWidgets.QGridLayout(Dialog)
+ self.gridLayout_2.setObjectName("gridLayout_2")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
@@ -34,7 +34,20 @@ def setupUi(self, Dialog):
self.horizontalLayout.addWidget(self.label_StatusText)
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem1)
- self.gridLayout.addLayout(self.horizontalLayout, 0, 0, 1, 1)
+ self.gridLayout_2.addLayout(self.horizontalLayout, 0, 0, 1, 1)
+ self.widget_Cancel = QtWidgets.QWidget(Dialog)
+ self.widget_Cancel.setObjectName("widget_Cancel")
+ self.gridLayout = QtWidgets.QGridLayout(self.widget_Cancel)
+ self.gridLayout.setContentsMargins(0, 0, 0, 0)
+ self.gridLayout.setObjectName("gridLayout")
+ spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.gridLayout.addItem(spacerItem2, 0, 0, 1, 1)
+ self.pushButton_Cancel = QtWidgets.QPushButton(self.widget_Cancel)
+ self.pushButton_Cancel.setObjectName("pushButton_Cancel")
+ self.gridLayout.addWidget(self.pushButton_Cancel, 0, 1, 1, 1)
+ spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.gridLayout.addItem(spacerItem3, 0, 2, 1, 1)
+ self.gridLayout_2.addWidget(self.widget_Cancel, 1, 0, 1, 1)
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
@@ -43,4 +56,5 @@ def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.label_StatusText.setText(_translate("Dialog", "Processing"))
+ self.pushButton_Cancel.setText(_translate("Dialog", "Cancel"))
diff --git a/GUI/LoadingDialog.ui b/GUI/LoadingDialog.ui
index 9e92c0ac..0f6ad516 100644
--- a/GUI/LoadingDialog.ui
+++ b/GUI/LoadingDialog.ui
@@ -6,14 +6,14 @@
0
0
- 195
- 40
+ 208
+ 89
Dialog
-
+
-
-
@@ -67,6 +67,45 @@
+ -
+
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Cancel
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
diff --git a/PINCE.py b/PINCE.py
index 6643c52b..75f17f98 100644
--- a/PINCE.py
+++ b/PINCE.py
@@ -845,6 +845,7 @@ def __init__(self, parent=None):
# Check refresh_table method of FunctionsInfoWidgetForm for exemplary usage
self.background_thread = self.BackgroundThread()
self.background_thread.output_ready.connect(self.accept)
+ self.pushButton_Cancel.clicked.connect(self.cancel_thread)
pince_directory = SysUtils.get_current_script_directory()
self.movie = QMovie(pince_directory + "/media/LoadingDialog/ajax-loader.gif", QByteArray())
self.label_Animated.setMovie(self.movie)
@@ -853,6 +854,11 @@ def __init__(self, parent=None):
self.movie.setSpeed(100)
self.movie.start()
+ # This function only cancels the last command sent
+ # Override this if you want to do dangerous stuff like, God forbid, background_thread.terminate()
+ def cancel_thread(self):
+ GDB_Engine.cancel_last_command()
+
def exec_(self):
self.background_thread.start()
super(LoadingDialogForm, self).exec_()
diff --git a/libPINCE/GDB_Engine.py b/libPINCE/GDB_Engine.py
index 6d329f45..52c4f61d 100644
--- a/libPINCE/GDB_Engine.py
+++ b/libPINCE/GDB_Engine.py
@@ -111,9 +111,21 @@
# See gdb_async_condition's docstrings
gdb_async_output = ""
+#:doc:cancel_send_command
+# A boolean value. Used to cancel the last gdb command sent
+# Use the function cancel_last_command to make use of this variable
+# Return value of the current send_command call will be an empty string
+cancel_send_command = False
+
# The comments next to the regular expressions shows the expected gdb output, hope it helps to the future developers
+def cancel_last_command():
+ """Cancels the last gdb command sent"""
+ global cancel_send_command
+ cancel_send_command = True
+
+
def send_command(command, control=False, cli_output=False, send_with_file=False, file_contents_send=None,
recv_with_file=False):
"""Issues the command sent, raises an exception if the inferior is running or no inferior has been selected
@@ -147,6 +159,7 @@ def send_command(command, control=False, cli_output=False, send_with_file=False,
"""
global child
global gdb_output
+ global cancel_send_command
with lock_send_command:
time0 = time()
if not gdb_initialized:
@@ -178,11 +191,17 @@ def send_command(command, control=False, cli_output=False, send_with_file=False,
if not control:
while gdb_output is "":
sleep(type_defs.CONST_TIME.GDB_INPUT_SLEEP)
- if not control:
- if recv_with_file or cli_output:
- output = pickle.load(open(recv_file, "rb"))
+ if cancel_send_command:
+ break
+ if not cancel_send_command:
+ if recv_with_file or cli_output:
+ output = pickle.load(open(recv_file, "rb"))
+ else:
+ output = gdb_output
else:
- output = gdb_output
+ output = ""
+ child.sendcontrol("c")
+ cancel_send_command = False
else:
output = ""
if type(output) == str:
@@ -302,7 +321,7 @@ def wait_for_stop(timeout=1):
def interrupt_inferior(interrupt_reason=type_defs.STOP_REASON.DEBUG):
- """Interrupt the inferior, can be also used to cancel the current gdb command
+ """Interrupt the inferior
Args:
interrupt_reason (int): Just changes the global variable stop_reason. Can be a member of type_defs.STOP_REASON
@@ -348,6 +367,7 @@ def init_gdb(gdb_path=type_defs.PATHS.GDB_PATH):
global referenced_jumps_dict
global referenced_calls_dict
global gdb_output
+ global cancel_send_command
detach()
# Temporary IPC_PATH, this little hack is needed because send_command requires a valid IPC_PATH
@@ -360,6 +380,7 @@ def init_gdb(gdb_path=type_defs.PATHS.GDB_PATH):
referenced_jumps_dict.clear()
referenced_calls_dict.clear()
gdb_output = ""
+ cancel_send_command = False
libpince_dir = SysUtils.get_libpince_directory()
child = pexpect.spawn('sudo LC_NUMERIC=C ' + gdb_path + ' --interpreter=mi', cwd=libpince_dir,