WalletSynchronizer had a race condition caused by calling the callback before the...
authorAmir Taaki <genjix@riseup.net>
Wed, 29 Aug 2012 19:49:31 +0000 (20:49 +0100)
committerAmir Taaki <genjix@riseup.net>
Wed, 29 Aug 2012 19:53:22 +0000 (20:53 +0100)
electrum
lib/gui_lite.py
lib/gui_qt.py
lib/interface.py

index 914634d..aca8083 100755 (executable)
--- a/electrum
+++ b/electrum
@@ -173,7 +173,8 @@ if __name__ == '__main__':
             sys.exit("Error: Unknown GUI: " + options.gui)
 
         gui = gui.ElectrumGui(wallet)
-        WalletSynchronizer(wallet,True).start()
+        interface = WalletSynchronizer(wallet, True, gui.server_list_changed)
+        interface.start()
 
         try:
             found = wallet.file_exists
index d0997be..f384b45 100644 (file)
@@ -42,14 +42,18 @@ def resize_line_edit_width(line_edit, text_input):
     text_input += "A"
     line_edit.setMinimumWidth(metrics.width(text_input))
 
-class ElectrumGui:
+class ElectrumGui(QObject):
 
     def __init__(self, wallet):
+        super(QObject, self).__init__()
+
         self.wallet = wallet
         self.app = QApplication(sys.argv)
 
     def main(self, url):
         actuator = MiniActuator(self.wallet)
+        self.connect(self, SIGNAL("updateservers()"),
+                     actuator.update_servers_list)
         # Should probably not modify the current path but instead
         # change the behaviour of rsrc(...)
         old_path = QDir.currentPath()
@@ -74,6 +78,9 @@ class ElectrumGui:
 
         self.app.exec_()
 
+    def server_list_changed(self):
+        self.emit(SIGNAL("updateservers()"))
+
     def expand(self):
         """Hide the lite mode window and show pro-mode."""
         self.mini.hide()
@@ -495,16 +502,13 @@ class ReceivePopup(QDialog):
         QCursor.setPos(center_mouse_pos)
         self.show()
 
-class MiniActuator(QObject):
+class MiniActuator:
     """Initialize the definitions relating to themes and 
-    sending/recieving bitcoins.
-    """
+    sending/recieving bitcoins."""
     
     
     def __init__(self, wallet):
         """Retrieve the gui theme used in previous session."""
-        super(QObject, self).__init__()
-
         self.wallet = wallet
         self.theme_name = self.wallet.theme
         self.themes = util.load_theme_paths()
@@ -549,11 +553,9 @@ class MiniActuator(QObject):
     def set_servers_gui_stuff(self, servers_menu, servers_group):
         self.servers_menu = servers_menu
         self.servers_group = servers_group
-        self.connect(self, SIGNAL("updateservers()"), self.update_servers_list)
 
     def populate_servers_menu(self):
         interface = self.wallet.interface
-        interface.servers_loaded_callback = self.server_list_changed
         if not interface.servers:
             print "No servers loaded yet."
             self.servers_list = []
@@ -583,9 +585,6 @@ class MiniActuator(QObject):
             server_action.toggled.connect(delegate)
             self.servers_group.addAction(server_action)
 
-    def server_list_changed(self):
-        self.emit(SIGNAL("updateservers()"))
-
     def update_servers_list(self):
         # Clear servers_group
         for action in self.servers_group.actions():
index 030215b..6693073 100644 (file)
@@ -1430,6 +1430,9 @@ class ElectrumGui:
         if app is None:
             self.app = QApplication(sys.argv)
 
+    def server_list_changed(self):
+        pass
+
     def waiting_dialog(self):
 
         s = Timer()
index ea34796..1af2fa2 100644 (file)
@@ -306,14 +306,15 @@ class TcpStratumInterface(Interface):
 
 class WalletSynchronizer(threading.Thread):
 
-    def __init__(self, wallet, loop=False):
+    def __init__(self, wallet, loop=False, servers_loaded_callback=None):
         threading.Thread.__init__(self)
         self.daemon = True
         self.wallet = wallet
         self.loop = loop
         self.init_interface()
+        self.servers_loaded_callback = servers_loaded_callback
 
-    def init_interface(self, servers_loaded_callback=None):
+    def init_interface(self):
         try:
             host, port, protocol = self.wallet.server.split(':')
             port = int(port)
@@ -332,10 +333,8 @@ class WalletSynchronizer(threading.Thread):
             InterfaceClass = TcpStratumInterface
 
         self.interface = InterfaceClass(host, port, self.wallet.debug_server)
-        self.interface.servers_loaded_callback = servers_loaded_callback
         self.wallet.interface = self.interface
 
-
     def handle_response(self, r):
         if r is None:
             return
@@ -364,8 +363,13 @@ class WalletSynchronizer(threading.Thread):
                 if ports and version:
                     servers.append((host, ports))
             self.interface.servers = servers
-            assert self.interface.servers_loaded_callback is not None
-            self.interface.servers_loaded_callback()
+            # TODO: This assert fails with commands so it should be removed
+            # after we've ascertained it never fails when running the GUI.
+            assert self.servers_loaded_callback is not None
+            # servers_loaded_callback is None for commands, but should
+            # NEVER be None when using the GUI.
+            if self.servers_loaded_callback is not None:
+                self.servers_loaded_callback()
 
         elif method == 'blockchain.address.subscribe':
             addr = params[0]
@@ -429,7 +433,7 @@ class WalletSynchronizer(threading.Thread):
             if self.loop:
                 time.sleep(5)
                 # Server has been changed. Copy callback for new interface.
-                self.init_interface(self.interface.servers_loaded_callback)
+                self.init_interface()
                 self.start_interface()
                 continue
             else: