GUI shutdown improvements
- it shows that it needs to wait for PoW to finish - it waits a bit for new objects to be distributed - it displays a better progress indicator in the status bar Previously, people who don't understand how PyBitmessage works sometimes shut it down immediately after they wrote a message. This would have caused the message to be stuck in the queue locally and not sent. Now, it will indicate that the PoW still needs to work, and it will wait a bit longer so that the message can spread. It's not a completely correct approach, because it does not know whether the message was really retrieved after the "inv" notification was sent.
This commit is contained in:
parent
167da731d0
commit
3dbb4d5ce9
|
@ -67,6 +67,8 @@ from utils import *
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from account import *
|
from account import *
|
||||||
from dialogs import AddAddressDialog
|
from dialogs import AddAddressDialog
|
||||||
|
from class_objectHashHolder import objectHashHolder
|
||||||
|
from class_singleWorker import singleWorker
|
||||||
|
|
||||||
def _translate(context, text):
|
def _translate(context, text):
|
||||||
return QtGui.QApplication.translate(context, text)
|
return QtGui.QApplication.translate(context, text)
|
||||||
|
@ -2644,7 +2646,64 @@ class MyForm(settingsmixin.SMainWindow):
|
||||||
if reply is QtGui.QMessageBox.No:
|
if reply is QtGui.QMessageBox.No:
|
||||||
return
|
return
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
self.statusBar().showMessage(_translate(
|
||||||
|
"MainWindow", "Shutting down PyBitmessage... %1%%").arg(str(0)))
|
||||||
|
|
||||||
|
# check if PoW queue empty
|
||||||
|
maxWorkerQueue = 0
|
||||||
|
curWorkerQueue = 1
|
||||||
|
while curWorkerQueue > 0:
|
||||||
|
# worker queue size
|
||||||
|
curWorkerQueue = shared.workerQueue.qsize()
|
||||||
|
# if worker is busy add 1
|
||||||
|
for thread in threading.enumerate():
|
||||||
|
try:
|
||||||
|
if isinstance(thread, singleWorker):
|
||||||
|
curWorkerQueue += thread.busy
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
if curWorkerQueue > maxWorkerQueue:
|
||||||
|
maxWorkerQueue = curWorkerQueue
|
||||||
|
if curWorkerQueue > 0:
|
||||||
|
self.statusBar().showMessage(_translate("MainWindow", "Waiting for PoW to finish... %1%").arg(str(50 * (maxWorkerQueue - curWorkerQueue) / maxWorkerQueue)))
|
||||||
|
time.sleep(0.5)
|
||||||
|
QtCore.QCoreApplication.processEvents()
|
||||||
|
|
||||||
|
self.statusBar().showMessage(_translate("MainWindow", "Shutting down Pybitmessage... %1%").arg(str(50)))
|
||||||
|
|
||||||
|
QtCore.QCoreApplication.processEvents()
|
||||||
|
if maxWorkerQueue > 0:
|
||||||
|
time.sleep(0.5) # a bit of time so that the hashHolder is populated
|
||||||
|
QtCore.QCoreApplication.processEvents()
|
||||||
|
|
||||||
|
# check if objectHashHolder empty
|
||||||
|
self.statusBar().showMessage(_translate("MainWindow", "Waiting for objects to be sent... %1%").arg(str(50)))
|
||||||
|
maxWaitingObjects = 0
|
||||||
|
curWaitingObjects = 1
|
||||||
|
while curWaitingObjects > 0:
|
||||||
|
curWaitingObjects = 0
|
||||||
|
for thread in threading.enumerate():
|
||||||
|
try:
|
||||||
|
if isinstance(thread, objectHashHolder):
|
||||||
|
curWaitingObjects += thread.hashCount()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
if curWaitingObjects > maxWaitingObjects:
|
||||||
|
maxWaitingObjects = curWaitingObjects
|
||||||
|
if curWaitingObjects > 0:
|
||||||
|
self.statusBar().showMessage(_translate("MainWindow", "Waiting for objects to be sent... %1%").arg(str(50 + 20 * (maxWaitingObjects - curWaitingObjects) / maxWaitingObjects)))
|
||||||
|
time.sleep(0.5)
|
||||||
|
QtCore.QCoreApplication.processEvents()
|
||||||
|
|
||||||
|
QtCore.QCoreApplication.processEvents()
|
||||||
|
if maxWorkerQueue > 0 or maxWaitingObjects > 0:
|
||||||
|
time.sleep(10) # a bit of time so that the other nodes retrieve the objects
|
||||||
|
QtCore.QCoreApplication.processEvents()
|
||||||
|
|
||||||
# save state and geometry self and all widgets
|
# save state and geometry self and all widgets
|
||||||
|
self.statusBar().showMessage(_translate("MainWindow", "Saving settings... %1%").arg(str(70)))
|
||||||
|
QtCore.QCoreApplication.processEvents()
|
||||||
self.saveSettings()
|
self.saveSettings()
|
||||||
for attr, obj in self.ui.__dict__.iteritems():
|
for attr, obj in self.ui.__dict__.iteritems():
|
||||||
if hasattr(obj, "__class__") and isinstance(obj, settingsmixin.SettingsMixin):
|
if hasattr(obj, "__class__") and isinstance(obj, settingsmixin.SettingsMixin):
|
||||||
|
@ -2652,19 +2711,20 @@ class MyForm(settingsmixin.SMainWindow):
|
||||||
if callable (saveMethod):
|
if callable (saveMethod):
|
||||||
obj.saveSettings()
|
obj.saveSettings()
|
||||||
|
|
||||||
|
self.statusBar().showMessage(_translate("MainWindow", "Shutting down core... %1%").arg(str(80)))
|
||||||
|
QtCore.QCoreApplication.processEvents()
|
||||||
shared.doCleanShutdown()
|
shared.doCleanShutdown()
|
||||||
|
self.statusBar().showMessage(_translate("MainWindow", "Stopping notifications... %1%").arg(str(90)))
|
||||||
|
QtCore.QCoreApplication.processEvents()
|
||||||
self.tray.hide()
|
self.tray.hide()
|
||||||
# unregister the messaging system
|
# unregister the messaging system
|
||||||
if self.mmapp is not None:
|
if self.mmapp is not None:
|
||||||
self.mmapp.unregister()
|
self.mmapp.unregister()
|
||||||
|
|
||||||
# settings = QSettings("Bitmessage", "PyBitmessage")
|
self.statusBar().showMessage(_translate("MainWindow", "Shutdown imminent... %1%").arg(str(100)))
|
||||||
# settings.setValue("geometry", self.saveGeometry())
|
QtCore.QCoreApplication.processEvents()
|
||||||
# settings.setValue("state", self.saveState())
|
|
||||||
|
|
||||||
self.statusBar().showMessage(_translate(
|
|
||||||
"MainWindow", "All done. Closing user interface..."))
|
|
||||||
shared.thisapp.cleanup()
|
shared.thisapp.cleanup()
|
||||||
|
logger.info("Shutdown complete")
|
||||||
os._exit(0)
|
os._exit(0)
|
||||||
|
|
||||||
# window close event
|
# window close event
|
||||||
|
|
|
@ -47,6 +47,9 @@ class objectHashHolder(threading.Thread):
|
||||||
|
|
||||||
def holdPeer(self,peerDetails):
|
def holdPeer(self,peerDetails):
|
||||||
self.collectionOfPeerLists[random.randrange(0, self.size)].append(peerDetails)
|
self.collectionOfPeerLists[random.randrange(0, self.size)].append(peerDetails)
|
||||||
|
|
||||||
|
def hashCount(self):
|
||||||
|
return sum([len(x) for x in self.collectionOfHashLists])
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
self.shutdown = True
|
self.shutdown = True
|
||||||
|
|
|
@ -87,7 +87,9 @@ class singleWorker(threading.Thread, StoppableThread):
|
||||||
self.sendBroadcast()
|
self.sendBroadcast()
|
||||||
|
|
||||||
while shared.shutdown == 0:
|
while shared.shutdown == 0:
|
||||||
|
self.busy = 0
|
||||||
command, data = shared.workerQueue.get()
|
command, data = shared.workerQueue.get()
|
||||||
|
self.busy = 1
|
||||||
if command == 'sendmessage':
|
if command == 'sendmessage':
|
||||||
try:
|
try:
|
||||||
self.sendMsg()
|
self.sendMsg()
|
||||||
|
@ -114,6 +116,7 @@ class singleWorker(threading.Thread, StoppableThread):
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
elif command == 'stopThread':
|
elif command == 'stopThread':
|
||||||
|
self.busy = 0
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
logger.error('Probable programming error: The command sent to the workerThread is weird. It is: %s\n' % command)
|
logger.error('Probable programming error: The command sent to the workerThread is weird. It is: %s\n' % command)
|
||||||
|
|
|
@ -522,6 +522,8 @@ def doCleanShutdown():
|
||||||
logger.info('Clean shutdown complete.')
|
logger.info('Clean shutdown complete.')
|
||||||
thisapp.cleanup()
|
thisapp.cleanup()
|
||||||
os._exit(0)
|
os._exit(0)
|
||||||
|
else:
|
||||||
|
logger.info('Core shutdown complete.')
|
||||||
|
|
||||||
# If you want to command all of the sendDataThreads to do something, like shutdown or send some data, this
|
# If you want to command all of the sendDataThreads to do something, like shutdown or send some data, this
|
||||||
# function puts your data into the queues for each of the sendDataThreads. The sendDataThreads are
|
# function puts your data into the queues for each of the sendDataThreads. The sendDataThreads are
|
||||||
|
|
Loading…
Reference in New Issue
Block a user