Electrum: Hanging "Please wait" window

Created on 21 Feb 2018  路  13Comments  路  Source: spesmilo/electrum

If I attempt to make a transaction and type a wrong password I get a hanging "Please wait" window.
It is not possible to close the window.
screenshot from 2018-02-21 21-34-18

appmenu-qt: registerWindow 206 "&File"
appmenu-qt: registerWindow 206 "&Wallet"
appmenu-qt: registerWindow 206 "&View"
appmenu-qt: registerWindow 206 "&Tools"
appmenu-qt: registerWindow 206 "&Help"
Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/electrum/bitcoin.py", line 167, in aes_decrypt_with_iv
    return strip_PKCS7_padding(data)
  File "/usr/local/lib/python3.5/dist-packages/electrum/bitcoin.py", line 138, in strip_PKCS7_padding
    raise InvalidPadding("invalid padding byte (large)")
electrum.bitcoin.InvalidPadding: invalid padding byte (large)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/electrum/bitcoin.py", line 196, in pw_decode
    d = to_string(DecodeAES(secret, s), "utf8")
  File "/usr/local/lib/python3.5/dist-packages/electrum/bitcoin.py", line 182, in DecodeAES
    s = aes_decrypt_with_iv(secret, iv, e)
  File "/usr/local/lib/python3.5/dist-packages/electrum/bitcoin.py", line 169, in aes_decrypt_with_iv
    raise InvalidPassword()
electrum.util.InvalidPassword: Incorrect password

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/electrum_gui/qt/util.py", line 587, in run
    result = task.task()
  File "/usr/local/lib/python3.5/dist-packages/electrum/wallet.py", line 1153, in sign_transaction
    k.sign_transaction(tx, password)
  File "/usr/local/lib/python3.5/dist-packages/electrum/keystore.py", line 99, in sign_transaction
    self.check_password(password)
  File "/usr/local/lib/python3.5/dist-packages/electrum/keystore.py", line 291, in check_password
    xprv = pw_decode(self.xprv, password)
  File "/usr/local/lib/python3.5/dist-packages/electrum/bitcoin.py", line 198, in pw_decode
    raise InvalidPassword()
electrum.util.InvalidPassword: Incorrect password

Observed on Electrum 3.0.5 / Linux

bug 馃悶 user-interface 馃敳

Most helpful comment

Oh wait, actually; let's do this:

diff --git a/gui/qt/util.py b/gui/qt/util.py
index 369c05e8..9f975e00 100644
--- a/gui/qt/util.py
+++ b/gui/qt/util.py
@@ -225,6 +225,7 @@ class WaitingDialog(WindowModalDialog):
         if isinstance(parent, MessageBoxMixin):
             parent = parent.top_level_window()
         WindowModalDialog.__init__(self, parent, _("Please wait"))
+        self.setAttribute(Qt.WA_DeleteOnClose)  # see #3956
         vbox = QVBoxLayout(self)
         vbox.addWidget(QLabel(message))
         self.accepted.connect(self.on_accepted)

All 13 comments

Hmm. Well I can't reproduce that on Debian 9.3.
I get the exact same trace (on 3.0.5) but the popup closes as expected for me.
What distro are you using?

Your pic looks a bit weird. Have you used some image manipulation program to obfuscate some detail or is that how it actually looks?

Maybe it's a QT quirk...
Can you run in a python3 interpreter:

from PyQt5.QtCore import QT_VERSION_STR
from PyQt5.Qt import PYQT_VERSION_STR
from sip import SIP_VERSION_STR

print("Qt version:", QT_VERSION_STR)
print("SIP version:", SIP_VERSION_STR)
print("PyQt version:", PYQT_VERSION_STR)

For me it prints

Qt version: 5.9.1
SIP version: 4.19.7
PyQt version: 5.9

I cannot reproduce it either, but I do not like the fact that no reference is held to the WaitingDialog.
maybe some signals get lost because of that.

could you try this patch?

iff --git a/gui/qt/main_window.py b/gui/qt/main_window.py
index 6b4a1f9b..da99d776 100644
--- a/gui/qt/main_window.py
+++ b/gui/qt/main_window.py
@@ -1559,8 +1559,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
             # call hook to see if plugin needs gui interaction
             run_hook('sign_tx', self, tx)
             task = partial(self.wallet.sign_transaction, tx, password)
-        WaitingDialog(self, _('Signing transaction...'), task,
-                      on_signed, on_failed)
+        self.signing_dialog = WaitingDialog(self, _('Signing transaction...'), task, on_signed, on_failed)

     def broadcast_transaction(self, tx, tx_desc):


@SomberNight Yes, it's weird. The image was not manipulated in any way.
I'm running on Ubuntu 16.04.3 LTS.

It looks like I'm running on older Qt, SIP and PyQT versions:

Qt version: 5.5.1
SIP version: 4.17
PyQt version: 5.5.1

@ecdsa I applied the patch but it did not fix the bug.

Ok, I can reproduce.
(also on Ubuntu 16.04 and same QT versions)

It seems we are trying to close the dialog too soon... ? It's not even fully painted when we are closing it.
After we "close it" it gets into a weird state for some reason.

I maintain a reference to it to test some things:

>> window.wd.close()
True

The window does not disappear. The docs say:
Closes this widget. Returns true if the widget was closed; otherwise returns false.
So apparently the widget "was closed"...

>> window.wd.isVisible()
False

But I can see it :P

>> window.wd.destroy()

^ That closes (and deletes) it properly.


If we wait for it to get painted that seems to resolve the issue... this is a bit ugly, but it works:

diff --git a/gui/qt/util.py b/gui/qt/util.py
index 7f0cb238..b18fa590 100644
--- a/gui/qt/util.py
+++ b/gui/qt/util.py
@@ -225,17 +225,30 @@ class WaitingDialog(WindowModalDialog):
         WindowModalDialog.__init__(self, parent, _("Please wait"))
         vbox = QVBoxLayout(self)
         vbox.addWidget(QLabel(message))
+        self.is_painted = False
+        self.is_finished = False
         self.accepted.connect(self.on_accepted)
         self.show()
         self.thread = TaskThread(self)
-        self.thread.add(task, on_success, self.accept, on_error)
+        self.thread.add(task, on_success, self._close, on_error)

     def wait(self):
         self.thread.wait()

+    def _close(self):
+        self.is_finished = True
+        if self.is_painted:
+            self.accept()
+
     def on_accepted(self):
         self.thread.stop()

+    def paintEvent(self, event):
+        super().paintEvent(event)
+        self.is_painted = True
+        if self.is_finished:
+            self.accept()
+

 def line_dialog(parent, title, label, ok_label, default=None):
     dialog = WindowModalDialog(parent, title)

EDIT: made "patch" less ugly

how did you reproduce the issue?

@ecdsa In a VirtualBox running a Ubuntu 16.04 guest, with the same QT versions as OP said. It happens for me with about a 30% chance.

It doesn't actually depend on the QT version..
I've updated pyqt5, and it still happens.

Qt version: 5.10.0
SIP version: 4.19.7
PyQt version: 5.10

BUT it does not happen with KDE...


Ok, so it happens on Ubuntu 16.04 with Unity; irrespective of QT version.

@SomberNight I am not sure if we really want to add that kind of fix to electrum, because it seems to be a Qt bug. perhaps we should consider this as "out of scope" ?

@danielcft Can you confirm you too used Unity, when experiencing this?

@ecdsa I am not fully certain it is a Qt bug.. How about monkey-patching it for this specific case as below:

diff --git a/gui/qt/main_window.py b/gui/qt/main_window.py
index ddaafc4b..d1661127 100644
--- a/gui/qt/main_window.py
+++ b/gui/qt/main_window.py
@@ -1554,6 +1554,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
         def on_signed(result):
             callback(True)
         def on_failed(exc_info):
+            wd.destroy()  # sometimes it won't close... see #3956
             self.on_error(exc_info)
             callback(False)

@@ -1564,8 +1565,8 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
             # call hook to see if plugin needs gui interaction
             run_hook('sign_tx', self, tx)
             task = partial(self.wallet.sign_transaction, tx, password)
-        WaitingDialog(self, _('Signing transaction...'), task,
-                      on_signed, on_failed)
+        wd = WaitingDialog(self, _('Signing transaction...'), task,
+                           on_signed, on_failed)

     def broadcast_transaction(self, tx, tx_desc):

Oh wait, actually; let's do this:

diff --git a/gui/qt/util.py b/gui/qt/util.py
index 369c05e8..9f975e00 100644
--- a/gui/qt/util.py
+++ b/gui/qt/util.py
@@ -225,6 +225,7 @@ class WaitingDialog(WindowModalDialog):
         if isinstance(parent, MessageBoxMixin):
             parent = parent.top_level_window()
         WindowModalDialog.__init__(self, parent, _("Please wait"))
+        self.setAttribute(Qt.WA_DeleteOnClose)  # see #3956
         vbox = QVBoxLayout(self)
         vbox.addWidget(QLabel(message))
         self.accepted.connect(self.on_accepted)

Ok, well this doesn't quite work...
There is a race condition, and occasionally this deletion happens too soon :(

QThread: Destroyed while thread is still running
Segmentation fault (core dumped)
Was this page helpful?
0 / 5 - 0 ratings

Related issues

Sancap picture Sancap  路  5Comments

gtklocker picture gtklocker  路  4Comments

dl3br picture dl3br  路  4Comments

GuestInCorle picture GuestInCorle  路  3Comments

Kixunil picture Kixunil  路  4Comments