Example #1
0
def doCleanShutdown():
    state.shutdown = 1  #Used to tell proof of work worker threads and the objectProcessorThread to exit.
    objectProcessorQueue.put(('checkShutdownVariable', 'no data'))
    for thread in threading.enumerate():
        if thread.isAlive() and isinstance(thread, StoppableThread):
            thread.stopThread()

    UISignalQueue.put(
        ('updateStatusBar', 'Saving the knownNodes list of peers to disk...'))
    logger.info('Saving knownNodes list of peers to disk')
    saveKnownNodes()
    logger.info('Done saving knownNodes list of peers to disk')
    UISignalQueue.put(('updateStatusBar',
                       'Done saving the knownNodes list of peers to disk.'))
    logger.info('Flushing inventory in memory out to disk...')
    UISignalQueue.put((
        'updateStatusBar',
        'Flushing inventory in memory out to disk. This should normally only take a second...'
    ))
    Inventory().flush()

    # Verify that the objectProcessor has finished exiting. It should have incremented the
    # shutdown variable from 1 to 2. This must finish before we command the sqlThread to exit.
    while state.shutdown == 1:
        time.sleep(.1)

    # This one last useless query will guarantee that the previous flush committed and that the
    # objectProcessorThread committed before we close the program.
    sqlQuery('SELECT address FROM subscriptions')
    logger.info('Finished flushing inventory.')
    sqlStoredProcedure('exit')

    # Wait long enough to guarantee that any running proof of work worker threads will check the
    # shutdown variable and exit. If the main thread closes before they do then they won't stop.
    time.sleep(.25)

    for thread in threading.enumerate():
        if thread is not threading.currentThread() and isinstance(
                thread, StoppableThread):
            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 shared.thisapp.daemon:
        logger.info('Clean shutdown complete.')
        shared.thisapp.cleanup()
        os._exit(0)
    else:
        logger.info('Core shutdown complete.')
    for thread in threading.enumerate():
        logger.debug("Thread %s still running", thread.name)
Example #2
0
 def HandleDeleteAndVacuum(self, params):
     if not params:
         sqlStoredProcedure('deleteandvacuume')
         return 'done'
Example #3
0
    def accept(self):
        """A callback for accepted event of buttonBox (OK button pressed)"""
        # pylint: disable=too-many-branches,too-many-statements
        super(SettingsDialog, self).accept()
        if self.firstrun:
            self.config.remove_option('bitmessagesettings', 'dontconnect')
        self.config.set('bitmessagesettings', 'startonlogon',
                        str(self.checkBoxStartOnLogon.isChecked()))
        self.config.set('bitmessagesettings', 'minimizetotray',
                        str(self.checkBoxMinimizeToTray.isChecked()))
        self.config.set('bitmessagesettings', 'trayonclose',
                        str(self.checkBoxTrayOnClose.isChecked()))
        self.config.set(
            'bitmessagesettings', 'hidetrayconnectionnotifications',
            str(self.checkBoxHideTrayConnectionNotifications.isChecked()))
        self.config.set('bitmessagesettings', 'showtraynotifications',
                        str(self.checkBoxShowTrayNotifications.isChecked()))
        self.config.set('bitmessagesettings', 'startintray',
                        str(self.checkBoxStartInTray.isChecked()))
        self.config.set('bitmessagesettings', 'willinglysendtomobile',
                        str(self.checkBoxWillinglySendToMobile.isChecked()))
        self.config.set('bitmessagesettings', 'useidenticons',
                        str(self.checkBoxUseIdenticons.isChecked()))
        self.config.set('bitmessagesettings', 'replybelow',
                        str(self.checkBoxReplyBelow.isChecked()))

        lang = str(
            self.languageComboBox.itemData(
                self.languageComboBox.currentIndex()).toString())
        self.config.set('bitmessagesettings', 'userlocale', lang)
        self.parent.change_translation()

        if int(self.config.get('bitmessagesettings', 'port')) != int(
                self.lineEditTCPPort.text()):
            self.config.set('bitmessagesettings', 'port',
                            str(self.lineEditTCPPort.text()))
            if not self.config.safeGetBoolean('bitmessagesettings',
                                              'dontconnect'):
                self.net_restart_needed = True

        if self.checkBoxUPnP.isChecked() != self.config.safeGetBoolean(
                'bitmessagesettings', 'upnp'):
            self.config.set('bitmessagesettings', 'upnp',
                            str(self.checkBoxUPnP.isChecked()))
            if self.checkBoxUPnP.isChecked():
                import upnp
                upnpThread = upnp.uPnPThread()
                upnpThread.start()

        proxytype_index = self.comboBoxProxyType.currentIndex()
        if proxytype_index == 0:
            if self._proxy_type and state.statusIconColor != 'red':
                self.net_restart_needed = True
        elif self.comboBoxProxyType.currentText() != self._proxy_type:
            self.net_restart_needed = True
            self.parent.statusbar.clearMessage()

        self.config.set(
            'bitmessagesettings', 'socksproxytype',
            'none' if self.comboBoxProxyType.currentIndex() == 0 else str(
                self.comboBoxProxyType.currentText()))
        if proxytype_index > 2:  # last literal proxytype in ui
            start_proxyconfig()

        self.config.set('bitmessagesettings', 'socksauthentication',
                        str(self.checkBoxAuthentication.isChecked()))
        self.config.set('bitmessagesettings', 'sockshostname',
                        str(self.lineEditSocksHostname.text()))
        self.config.set('bitmessagesettings', 'socksport',
                        str(self.lineEditSocksPort.text()))
        self.config.set('bitmessagesettings', 'socksusername',
                        str(self.lineEditSocksUsername.text()))
        self.config.set('bitmessagesettings', 'sockspassword',
                        str(self.lineEditSocksPassword.text()))
        self.config.set('bitmessagesettings', 'sockslisten',
                        str(self.checkBoxSocksListen.isChecked()))
        if self.checkBoxOnionOnly.isChecked() \
                and not self.config.safeGetBoolean('bitmessagesettings', 'onionservicesonly'):
            self.net_restart_needed = True
        self.config.set('bitmessagesettings', 'onionservicesonly',
                        str(self.checkBoxOnionOnly.isChecked()))
        try:
            # Rounding to integers just for aesthetics
            self.config.set(
                'bitmessagesettings', 'maxdownloadrate',
                str(int(float(self.lineEditMaxDownloadRate.text()))))
            self.config.set('bitmessagesettings', 'maxuploadrate',
                            str(int(float(self.lineEditMaxUploadRate.text()))))
        except ValueError:
            QtGui.QMessageBox.about(
                self, _translate("MainWindow", "Number needed"),
                _translate(
                    "MainWindow",
                    "Your maximum download and upload rate must be numbers."
                    " Ignoring what you typed."))
        else:
            set_rates(
                self.config.safeGetInt('bitmessagesettings',
                                       'maxdownloadrate'),
                self.config.safeGetInt('bitmessagesettings', 'maxuploadrate'))

        self.config.set(
            'bitmessagesettings', 'maxoutboundconnections',
            str(int(float(self.lineEditMaxOutboundConnections.text()))))

        self.config.set('bitmessagesettings', 'namecoinrpctype',
                        self.getNamecoinType())
        self.config.set('bitmessagesettings', 'namecoinrpchost',
                        str(self.lineEditNamecoinHost.text()))
        self.config.set('bitmessagesettings', 'namecoinrpcport',
                        str(self.lineEditNamecoinPort.text()))
        self.config.set('bitmessagesettings', 'namecoinrpcuser',
                        str(self.lineEditNamecoinUser.text()))
        self.config.set('bitmessagesettings', 'namecoinrpcpassword',
                        str(self.lineEditNamecoinPassword.text()))
        self.parent.resetNamecoinConnection()

        # Demanded difficulty tab
        if float(self.lineEditTotalDifficulty.text()) >= 1:
            self.config.set(
                'bitmessagesettings', 'defaultnoncetrialsperbyte',
                str(
                    int(
                        float(self.lineEditTotalDifficulty.text()) *
                        defaults.networkDefaultProofOfWorkNonceTrialsPerByte)))
        if float(self.lineEditSmallMessageDifficulty.text()) >= 1:
            self.config.set(
                'bitmessagesettings', 'defaultpayloadlengthextrabytes',
                str(
                    int(
                        float(self.lineEditSmallMessageDifficulty.text()) *
                        defaults.networkDefaultPayloadLengthExtraBytes)))

        if self.comboBoxOpenCL.currentText().toUtf8() != self.config.safeGet(
                'bitmessagesettings', 'opencl'):
            self.config.set('bitmessagesettings', 'opencl',
                            str(self.comboBoxOpenCL.currentText()))
            queues.workerQueue.put(('resetPoW', ''))

        acceptableDifficultyChanged = False

        if (float(self.lineEditMaxAcceptableTotalDifficulty.text()) >= 1 or
                float(self.lineEditMaxAcceptableTotalDifficulty.text()) == 0):
            if self.config.get(
                    'bitmessagesettings', 'maxacceptablenoncetrialsperbyte'
            ) != str(
                    int(
                        float(
                            self.lineEditMaxAcceptableTotalDifficulty.text()) *
                        defaults.networkDefaultProofOfWorkNonceTrialsPerByte)):
                # the user changed the max acceptable total difficulty
                acceptableDifficultyChanged = True
                self.config.set(
                    'bitmessagesettings', 'maxacceptablenoncetrialsperbyte',
                    str(
                        int(
                            float(self.lineEditMaxAcceptableTotalDifficulty.
                                  text()) * defaults.
                            networkDefaultProofOfWorkNonceTrialsPerByte)))
        if (float(self.lineEditMaxAcceptableSmallMessageDifficulty.text()) >= 1
                or float(
                    self.lineEditMaxAcceptableSmallMessageDifficulty.text())
                == 0):
            if self.config.get(
                    'bitmessagesettings',
                    'maxacceptablepayloadlengthextrabytes'
            ) != str(
                    int(
                        float(self.lineEditMaxAcceptableSmallMessageDifficulty.
                              text()) *
                        defaults.networkDefaultPayloadLengthExtraBytes)):
                # the user changed the max acceptable small message difficulty
                acceptableDifficultyChanged = True
                self.config.set(
                    'bitmessagesettings',
                    'maxacceptablepayloadlengthextrabytes',
                    str(
                        int(
                            float(self.
                                  lineEditMaxAcceptableSmallMessageDifficulty.
                                  text()) *
                            defaults.networkDefaultPayloadLengthExtraBytes)))
        if acceptableDifficultyChanged:
            # It might now be possible to send msgs which were previously
            # marked as toodifficult. Let us change them to 'msgqueued'.
            # The singleWorker will try to send them and will again mark
            # them as toodifficult if the receiver's required difficulty
            # is still higher than we are willing to do.
            sqlExecute("UPDATE sent SET status='msgqueued'"
                       " WHERE status='toodifficult'")
            queues.workerQueue.put(('sendmessage', ''))

        stopResendingDefaults = False

        # UI setting to stop trying to send messages after X days/months
        # I'm open to changing this UI to something else if someone has a better idea.
        if self.lineEditDays.text() == '' and self.lineEditMonths.text() == '':
            # We need to handle this special case. Bitmessage has its
            # default behavior. The input is blank/blank
            self.config.set('bitmessagesettings', 'stopresendingafterxdays',
                            '')
            self.config.set('bitmessagesettings', 'stopresendingafterxmonths',
                            '')
            state.maximumLengthOfTimeToBotherResendingMessages = float('inf')
            stopResendingDefaults = True

        try:
            days = float(self.lineEditDays.text())
        except ValueError:
            self.lineEditDays.setText("0")
            days = 0.0
        try:
            months = float(self.lineEditMonths.text())
        except ValueError:
            self.lineEditMonths.setText("0")
            months = 0.0

        if days >= 0 and months >= 0 and not stopResendingDefaults:
            state.maximumLengthOfTimeToBotherResendingMessages = \
                days * 24 * 60 * 60 + months * 60 * 60 * 24 * 365 / 12
            if state.maximumLengthOfTimeToBotherResendingMessages < 432000:
                # If the time period is less than 5 hours, we give
                # zero values to all fields. No message will be sent again.
                QtGui.QMessageBox.about(
                    self, _translate("MainWindow", "Will not resend ever"),
                    _translate(
                        "MainWindow",
                        "Note that the time limit you entered is less"
                        " than the amount of time Bitmessage waits for"
                        " the first resend attempt therefore your"
                        " messages will never be resent."))
                self.config.set('bitmessagesettings',
                                'stopresendingafterxdays', '0')
                self.config.set('bitmessagesettings',
                                'stopresendingafterxmonths', '0')
                state.maximumLengthOfTimeToBotherResendingMessages = 0.0
            else:
                self.config.set('bitmessagesettings',
                                'stopresendingafterxdays', str(days))
                self.config.set('bitmessagesettings',
                                'stopresendingafterxmonths', str(months))

        self.config.save()

        if self.net_restart_needed:
            self.net_restart_needed = False
            self.config.setTemp('bitmessagesettings', 'dontconnect', 'true')
            self.timer.singleShot(
                5000, lambda: self.config.setTemp('bitmessagesettings',
                                                  'dontconnect', 'false'))

        self.parent.updateStartOnLogon()

        if (state.appdata != paths.lookupExeFolder()
                and self.checkBoxPortableMode.isChecked()):
            # If we are NOT using portable mode now but the user selected
            # that we should...
            # Write the keys.dat file to disk in the new location
            sqlStoredProcedure('movemessagstoprog')
            with open(paths.lookupExeFolder() + 'keys.dat',
                      'wb') as configfile:
                self.config.write(configfile)
            # Write the knownnodes.dat file to disk in the new location
            knownnodes.saveKnownNodes(paths.lookupExeFolder())
            os.remove(state.appdata + 'keys.dat')
            os.remove(state.appdata + 'knownnodes.dat')
            previousAppdataLocation = state.appdata
            state.appdata = paths.lookupExeFolder()
            debug.resetLogging()
            try:
                os.remove(previousAppdataLocation + 'debug.log')
                os.remove(previousAppdataLocation + 'debug.log.1')
            except Exception:
                pass

        if (state.appdata == paths.lookupExeFolder()
                and not self.checkBoxPortableMode.isChecked()):
            # If we ARE using portable mode now but the user selected
            # that we shouldn't...
            state.appdata = paths.lookupAppdataFolder()
            if not os.path.exists(state.appdata):
                os.makedirs(state.appdata)
            sqlStoredProcedure('movemessagstoappdata')
            # Write the keys.dat file to disk in the new location
            self.config.save()
            # Write the knownnodes.dat file to disk in the new location
            knownnodes.saveKnownNodes(state.appdata)
            os.remove(paths.lookupExeFolder() + 'keys.dat')
            os.remove(paths.lookupExeFolder() + 'knownnodes.dat')
            debug.resetLogging()
            try:
                os.remove(paths.lookupExeFolder() + 'debug.log')
                os.remove(paths.lookupExeFolder() + 'debug.log.1')
            except Exception:
                pass
Example #4
0
def doCleanShutdown():
    state.shutdown = 1  #Used to tell proof of work worker threads and the objectProcessorThread to exit.

    #Stop sources of new threads
    for thread in threading.enumerate():
        if type(thread).__name__ not in ('outgoingSynSender',
                                         'singleListener'):
            continue
        thread.stopThread()
        thread.join()

    protocol.broadcastToSendDataQueues((0, 'shutdown', 'no data'))
    objectProcessorQueue.put(('checkShutdownVariable', 'no data'))
    for thread in threading.enumerate():
        if thread.isAlive() and isinstance(thread, StoppableThread):
            thread.stopThread()

    UISignalQueue.put(
        ('updateStatusBar', 'Saving the knownNodes list of peers to disk...'))
    logger.info('Saving knownNodes list of peers to disk')
    saveKnownNodes()
    logger.info('Done saving knownNodes list of peers to disk')
    UISignalQueue.put(('updateStatusBar',
                       'Done saving the knownNodes list of peers to disk.'))
    logger.info('Flushing inventory in memory out to disk...')
    UISignalQueue.put((
        'updateStatusBar',
        'Flushing inventory in memory out to disk. This should normally only take a second...'
    ))
    Inventory().flush()

    # Verify that the objectProcessor has finished exiting. It should have incremented the
    # shutdown variable from 1 to 2. This must finish before we command the sqlThread to exit.
    for thread in threading.enumerate():
        if type(thread).__name__ != 'objectProcessor':
            continue
        thread.join()
        break

    # This will guarantee that the previous flush committed and that the
    # objectProcessorThread committed before we close the program.
    sqlStoredProcedure('commit')
    logger.info('Finished flushing inventory.')
    sqlStoredProcedure('exit')
    for thread in threading.enumerate():
        if type(thread).__name__ != 'sqlThread':
            continue
        thread.join()
        break

    # Wait long enough to guarantee that any running proof of work worker threads will check the
    # shutdown variable and exit. If the main thread closes before they do then they won't stop.
    time.sleep(.25)

    for thread in threading.enumerate():
        if isinstance(thread, sendDataThread):
            thread.sendDataThreadQueue.put((0, 'shutdown', 'no data'))
        if thread is not threading.currentThread() and isinstance(
                thread,
                StoppableThread) and not isinstance(thread, outgoingSynSender):
            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

    logger.info('Clean shutdown complete.')

    for thread in threading.enumerate():
        if thread is threading.currentThread():
            continue
        logger.debug("Thread %s still running", thread.name)

    if BMConfigParser().safeGetBoolean('bitmessagesettings', 'daemon'):
        shared.thisapp.cleanup()
        os._exit(0)