X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fcore%2Fcoresession.cpp;h=2ca9627ccd0e0d24f8ac0f55e928b84813eb8873;hp=1d0d5c5f6e2298b17959eba7833880189f6ee194;hb=dd69349ca91776432a4a53aa4d18dd8ef018cd26;hpb=df48c9a36377de3c9e9deeaf539e1446ef7bd49b diff --git a/src/core/coresession.cpp b/src/core/coresession.cpp index 1d0d5c5f..2ca9627c 100644 --- a/src/core/coresession.cpp +++ b/src/core/coresession.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-2015 by the Quassel Project * + * Copyright (C) 2005-2016 by the Quassel Project * * devel@quassel-irc.org * * * * This program is free software; you can redistribute it and/or modify * @@ -27,6 +27,7 @@ #include "corebuffersyncer.h" #include "corebacklogmanager.h" #include "corebufferviewmanager.h" +#include "coredccconfig.h" #include "coreeventmanager.h" #include "coreidentity.h" #include "coreignorelistmanager.h" @@ -64,6 +65,7 @@ CoreSession::CoreSession(UserId uid, bool restoreState, QObject *parent) _bufferSyncer(new CoreBufferSyncer(this)), _backlogManager(new CoreBacklogManager(this)), _bufferViewManager(new CoreBufferViewManager(_signalProxy, this)), + _dccConfig(new CoreDccConfig(this)), _ircListHelper(new CoreIrcListHelper(this)), _networkConfig(new CoreNetworkConfig("GlobalNetworkConfig", this)), _coreInfo(this), @@ -121,6 +123,7 @@ CoreSession::CoreSession(UserId uid, bool restoreState, QObject *parent) p->synchronize(_bufferSyncer); p->synchronize(&aliasManager()); p->synchronize(_backlogManager); + p->synchronize(dccConfig()); p->synchronize(ircListHelper()); p->synchronize(networkConfig()); p->synchronize(&_coreInfo); @@ -137,7 +140,47 @@ CoreSession::CoreSession(UserId uid, bool restoreState, QObject *parent) CoreSession::~CoreSession() { saveSessionState(); + + /* Why partially duplicate CoreNetwork destructor? When each CoreNetwork quits in the + * destructor, disconnections are processed in sequence for each object. For many IRC servers + * on a slow network, this could significantly delay core shutdown [msecs wait * network count]. + * + * Here, CoreSession first calls disconnect on all networks, letting them all start + * disconnecting before beginning to sequentially wait for each network. Ideally, after the + * first network is disconnected, the other networks will have already closed. Worst-case may + * still wait [msecs wait time * num. of networks], but the risk should be much lower. + * + * CoreNetwork should still do cleanup in its own destructor in case a network is deleted + * outside of deleting the whole CoreSession. + * + * If this proves to be problematic in the future, there's an alternative Qt signal-based system + * implemented in another pull request that guarentees a maximum amount of time to disconnect, + * but at the cost of more complex code. + * + * See https://github.com/quassel/quassel/pull/203 + */ + + foreach(CoreNetwork *net, _networks.values()) { + // Request each network properly disconnect, but don't count as user-requested disconnect + if (net->socketConnected()) { + // Only try if the socket's fully connected (not initializing or disconnecting). + // Force an immediate disconnect, jumping the command queue. Ensures the proper QUIT is + // shown even if other messages are queued. + net->disconnectFromIrc(false, QString(), false, true); + } + } + + // Process the putCmd events that trigger the quit. Without this, shutting down the core + // results in abrubtly closing the socket rather than sending the QUIT as expected. + QCoreApplication::processEvents(); + foreach(CoreNetwork *net, _networks.values()) { + // Wait briefly for each network to disconnect. Sometimes it takes a little while to send. + if (!net->forceDisconnect()) { + qWarning() << "Timed out quitting network" << net->networkName() << + "(user ID " << net->userId() << ")"; + } + // Delete the network now that it's closed delete net; } } @@ -621,13 +664,14 @@ void CoreSession::clientsDisconnected() if (!identity->detachAwayReason().isEmpty()) awayReason = identity->detachAwayReason(); net->setAutoAwayActive(true); + // Allow handleAway() to format the current date/time in the string. net->userInputHandler()->handleAway(BufferInfo(), awayReason); } } } -void CoreSession::globalAway(const QString &msg) +void CoreSession::globalAway(const QString &msg, const bool skipFormatting) { QHash::iterator netIter = _networks.begin(); CoreNetwork *net = 0; @@ -638,7 +682,7 @@ void CoreSession::globalAway(const QString &msg) if (!net->isConnected()) continue; - net->userInputHandler()->issueAway(msg, false /* no force away */); + net->userInputHandler()->issueAway(msg, false /* no force away */, skipFormatting); } }