From 9ed59dd8250ceaf7131009b7fad5e21e7eff4385 Mon Sep 17 00:00:00 2001 From: Peter Surda Date: Mon, 16 Jan 2017 23:38:18 +0100 Subject: [PATCH] Shutdown procedure cleanup --- src/bitmessageqt/__init__.py | 14 ++++++++++++++ src/class_outgoingSynSender.py | 8 ++++++-- src/class_sendDataThread.py | 3 +++ src/shared.py | 11 +++++++++++ 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/bitmessageqt/__init__.py b/src/bitmessageqt/__init__.py index 04562fe6..b5f036a7 100644 --- a/src/bitmessageqt/__init__.py +++ b/src/bitmessageqt/__init__.py @@ -636,6 +636,9 @@ class MyForm(settingsmixin.SMainWindow): # switch back to this when replying self.replyFromTab = None + + # so that quit won't loop + self.quitAccepted = False self.init_file_menu() self.init_inbox_popup_menu() @@ -2693,6 +2696,9 @@ class MyForm(settingsmixin.SMainWindow): return ''' + if self.quitAccepted: + return + self.show() self.raise_() self.activateWindow() @@ -2734,6 +2740,8 @@ class MyForm(settingsmixin.SMainWindow): elif reply == QtGui.QMessageBox.Cancel: return + self.quitAccepted = True + self.statusBar().showMessage(_translate( "MainWindow", "Shutting down PyBitmessage... %1%").arg(str(0))) @@ -2813,6 +2821,8 @@ class MyForm(settingsmixin.SMainWindow): self.statusBar().showMessage(_translate("MainWindow", "Shutdown imminent... %1%").arg(str(100))) shared.thisapp.cleanup() logger.info("Shutdown complete") + super(MyForm, myapp).close() + #return os._exit(0) # window close event @@ -2827,6 +2837,10 @@ class MyForm(settingsmixin.SMainWindow): pass # always ignore, it shuts down by itself + if self.quitAccepted: + event.accept() + return + event.ignore() if not trayonclose: # quit the application diff --git a/src/class_outgoingSynSender.py b/src/class_outgoingSynSender.py index b8e3193f..11f755de 100644 --- a/src/class_outgoingSynSender.py +++ b/src/class_outgoingSynSender.py @@ -44,7 +44,7 @@ class outgoingSynSender(threading.Thread, StoppableThread): peer, = random.sample(shared.knownNodes[self.streamNumber], 1) except ValueError: # no known nodes shared.knownNodesLock.release() - time.sleep(1) + self.stop.wait(1) continue priority = (183600 - (time.time() - shared.knownNodes[self.streamNumber][peer])) / 183600 # 2 days and 3 hours shared.knownNodesLock.release() @@ -61,7 +61,7 @@ class outgoingSynSender(threading.Thread, StoppableThread): priority = 0.001 if (random.random() <= priority): break - time.sleep(0.01) # prevent CPU hogging if something is broken + self.stop.wait(0.01) # prevent CPU hogging if something is broken try: return peer except NameError: @@ -190,6 +190,10 @@ class outgoingSynSender(threading.Thread, StoppableThread): try: self.sock.connect((peer.host, peer.port)) + if self._stopped: + self.sock.shutdown(socket.SHUT_RDWR) + self.sock.close() + return someObjectsOfWhichThisRemoteNodeIsAlreadyAware = {} # This is not necessairly a complete list; we clear it from time to time to save memory. sendDataThreadQueue = Queue.Queue(100) # Used to submit information to the send data thread for this connection. diff --git a/src/class_sendDataThread.py b/src/class_sendDataThread.py index 55e674cb..2ea03e22 100644 --- a/src/class_sendDataThread.py +++ b/src/class_sendDataThread.py @@ -26,6 +26,7 @@ class sendDataThread(threading.Thread): state.sendDataQueues.append(self.sendDataThreadQueue) self.data = '' self.objectHashHolderInstance = objectHashHolder(self.sendDataThreadQueue) + self.objectHashHolderInstance.daemon = True self.objectHashHolderInstance.start() self.connectionIsOrWasFullyEstablished = False @@ -83,6 +84,8 @@ class sendDataThread(threading.Thread): amountSent = self.sslSock.send(self.buffer[:throttle.SendThrottle().chunkSize]) else: amountSent = self.sock.send(self.buffer[:throttle.SendThrottle().chunkSize]) + except socket.timeout: + continue except socket.error as e: if e.errno == errno.EAGAIN: continue diff --git a/src/shared.py b/src/shared.py index 022fa4b3..cd70d6c8 100644 --- a/src/shared.py +++ b/src/shared.py @@ -234,12 +234,23 @@ def doCleanShutdown(): logger.debug("Waiting for thread %s", thread.name) thread.join() + # flush queued + for queue in (workerQueue, UISignalQueue, addressGeneratorQueue, objectProcessorQueue): + while True: + try: + queue.get(False) + queue.task_done() + except Queue.Empty: + break + if BMConfigParser().safeGetBoolean('bitmessagesettings','daemon'): logger.info('Clean shutdown complete.') thisapp.cleanup() os._exit(0) else: logger.info('Core shutdown complete.') + for thread in threading.enumerate(): + logger.debug("Thread %s still running", thread.name) def fixPotentiallyInvalidUTF8Data(text): try: