Browse Source

Allow syncronizer to be GC-ed

Proper fix for #1525.
Using python's GC module, I've verified that the daemon, when running,
now releases all verifiers, synchronizers and wallets - all the resources
we care about releasing.
master
Neil Booth 10 years ago
parent
commit
8cc3b58364
  1. 7
      lib/network.py
  2. 3
      lib/synchronizer.py
  3. 5
      lib/wallet.py

7
lib/network.py

@ -556,6 +556,13 @@ class Network(util.DaemonThread):
message_id = self.queue_request(method, params) message_id = self.queue_request(method, params)
self.unanswered_requests[message_id] = method, params, callback self.unanswered_requests[message_id] = method, params, callback
def unsubscribe(self, callback):
'''Unsubscribe a callback to free object references to enable GC.'''
# Note: we can't unsubscribe from the server, so if we receive
# subsequent notifications process_response() will emit a harmless
# "received unexpected notification" warning
self.subscriptions.pop(callback, None)
def connection_down(self, server): def connection_down(self, server):
'''A connection to server either went down, or was never made. '''A connection to server either went down, or was never made.
We distinguish by whether it is in self.interfaces.''' We distinguish by whether it is in self.interfaces.'''

3
lib/synchronizer.py

@ -56,6 +56,9 @@ class Synchronizer(ThreadJob):
return (not self.requested_tx and not self.requested_histories return (not self.requested_tx and not self.requested_histories
and not self.requested_addrs) and not self.requested_addrs)
def release(self):
self.network.unsubscribe(self.addr_subscription_response)
def add(self, address): def add(self, address):
'''This can be called from the proxy or GUI threads.''' '''This can be called from the proxy or GUI threads.'''
with self.lock: with self.lock:

5
lib/wallet.py

@ -36,6 +36,7 @@ from transaction import Transaction
from plugins import run_hook from plugins import run_hook
import bitcoin import bitcoin
from synchronizer import Synchronizer from synchronizer import Synchronizer
from verifier import SPV
from mnemonic import Mnemonic from mnemonic import Mnemonic
import paymentrequest import paymentrequest
@ -1128,7 +1129,6 @@ class Abstract_Wallet(PrintError):
self.transactions.pop(tx_hash) self.transactions.pop(tx_hash)
def start_threads(self, network): def start_threads(self, network):
from verifier import SPV
self.network = network self.network = network
if self.network is not None: if self.network is not None:
self.prepare_for_verifier() self.prepare_for_verifier()
@ -1142,8 +1142,11 @@ class Abstract_Wallet(PrintError):
def stop_threads(self): def stop_threads(self):
if self.network: if self.network:
self.network.remove_jobs([self.synchronizer, self.verifier]) self.network.remove_jobs([self.synchronizer, self.verifier])
self.synchronizer.release()
self.synchronizer = None self.synchronizer = None
self.verifier = None self.verifier = None
# Now no references to the syncronizer or verifier
# remain so they will be GC-ed
self.storage.put('stored_height', self.get_local_height(), True) self.storage.put('stored_height', self.get_local_height(), True)
def wait_until_synchronized(self, callback=None): def wait_until_synchronized(self, callback=None):

Loading…
Cancel
Save