From 99b52d4cc128dc7075f5de49ce40b99ff832caaf Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Mon, 29 Feb 2016 19:53:26 +0300
Subject: [PATCH] all deinit moved to Application::aboutToQuit(), mtproto
 connection thread management refactored, disabled -style=0 fake argument for
 Application, beta 9028002

---
 Telegram/Build.bat                            |   1 +
 Telegram/SourceFiles/_other/updater.cpp       |   2 +-
 Telegram/SourceFiles/application.cpp          |  65 ++++++---
 Telegram/SourceFiles/application.h            |   5 +-
 Telegram/SourceFiles/config.h                 |   2 +-
 Telegram/SourceFiles/logs.cpp                 |   4 +-
 Telegram/SourceFiles/logs.h                   |   6 +-
 Telegram/SourceFiles/main.cpp                 |  39 ++----
 Telegram/SourceFiles/mtproto/mtp.cpp          | 128 +++++++++++-------
 Telegram/SourceFiles/mtproto/mtp.h            |  17 ++-
 .../SourceFiles/mtproto/mtpConnection.cpp     | 122 +++++++++--------
 Telegram/SourceFiles/mtproto/mtpConnection.h  |  14 +-
 Telegram/SourceFiles/mtproto/mtpSession.cpp   | 120 ++++++++--------
 Telegram/SourceFiles/mtproto/mtpSession.h     |  16 +--
 Telegram/SourceFiles/pspecific.h              |   6 +-
 Telegram/SourceFiles/pspecific_linux.cpp      |   4 +-
 Telegram/SourceFiles/pspecific_mac.cpp        |   4 +-
 Telegram/SourceFiles/pspecific_wnd.cpp        |   4 +-
 Telegram/SourceFiles/settings.h               |   1 -
 Telegram/Telegram.rc                          |   8 +-
 Telegram/Version                              |   2 +-
 21 files changed, 300 insertions(+), 270 deletions(-)

diff --git a/Telegram/Build.bat b/Telegram/Build.bat
index 6f83a43f2..788f9c766 100644
--- a/Telegram/Build.bat
+++ b/Telegram/Build.bat
@@ -1,4 +1,5 @@
 @echo OFF
+setlocal
 
 FOR /F "tokens=1,2* delims= " %%i in (Version) do set "%%i=%%j"
 
diff --git a/Telegram/SourceFiles/_other/updater.cpp b/Telegram/SourceFiles/_other/updater.cpp
index d89efcd95..7050e9bf3 100644
--- a/Telegram/SourceFiles/_other/updater.cpp
+++ b/Telegram/SourceFiles/_other/updater.cpp
@@ -255,7 +255,7 @@ bool update() {
 				} else {
 					break;
 				}
-			} while (copyTries < 30);
+			} while (copyTries < 100);
 			if (!copyResult) {
 				writeLog(L"Error: failed to copy, asking to retry..");
 				WCHAR errMsg[2048];
diff --git a/Telegram/SourceFiles/application.cpp b/Telegram/SourceFiles/application.cpp
index e128cb5eb..fca1d7df4 100644
--- a/Telegram/SourceFiles/application.cpp
+++ b/Telegram/SourceFiles/application.cpp
@@ -110,6 +110,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
 	connect(&_localSocket, SIGNAL(readyRead()), this, SLOT(socketReading()));
 	connect(&_localServer, SIGNAL(newConnection()), this, SLOT(newInstanceConnected()));
 
+	QTimer::singleShot(0, this, SLOT(startApplication()));
 	connect(this, SIGNAL(aboutToQuit()), this, SLOT(closeApplication()));
 
 #ifndef TDESKTOP_DISABLE_AUTOUPDATE
@@ -127,27 +128,6 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
 	}
 }
 
-Application::~Application() {
-	App::setQuiting();
-
-	Sandbox::finish();
-
-	delete AppObject;
-
-	_localSocket.close();
-	closeApplication();
-
-#ifndef TDESKTOP_DISABLE_AUTOUPDATE
-	delete _updateReply;
-	_updateReply = 0;
-	if (_updateChecker) _updateChecker->deleteLater();
-	_updateChecker = 0;
-	if (_updateThread) _updateThread->quit();
-	_updateThread = 0;
-#endif
-}
-
-
 void Application::socketConnected() {
 	LOG(("Socket connected, this is not the first application instance, sending show command.."));
 	_secondInstance = true;
@@ -333,13 +313,54 @@ void Application::removeClients() {
 	}
 }
 
+void Application::startApplication() {
+	if (App::quiting()) {
+		quit();
+	}
+}
+
 void Application::closeApplication() {
+	App::quit();
+
+	delete AppObject;
+	AppObject = 0;
+
+	Sandbox::finish();
+
 	_localServer.close();
 	for (LocalClients::iterator i = _localClients.begin(), e = _localClients.end(); i != e; ++i) {
 		disconnect(i->first, SIGNAL(disconnected()), this, SLOT(removeClients()));
 		i->first->close();
 	}
 	_localClients.clear();
+
+	_localSocket.close();
+
+#ifndef TDESKTOP_DISABLE_AUTOUPDATE
+	delete _updateReply;
+	_updateReply = 0;
+	if (_updateChecker) _updateChecker->deleteLater();
+	_updateChecker = 0;
+	if (_updateThread) _updateThread->quit();
+	_updateThread = 0;
+#endif
+
+	DEBUG_LOG(("Telegram finished, result: %1").arg("unknown"));
+
+#ifndef TDESKTOP_DISABLE_AUTOUPDATE
+	if (cRestartingUpdate()) {
+		DEBUG_LOG(("Application Info: executing updater to install update.."));
+		psExecUpdater();
+	} else
+#endif
+	if (cRestarting()) {
+		DEBUG_LOG(("Application Info: executing Telegram, because of restart.."));
+		psExecTelegram();
+	}
+
+	SignalHandlers::finish();
+	PlatformSpecific::finish();
+	Logs::finish();
 }
 
 #ifndef TDESKTOP_DISABLE_AUTOUPDATE
@@ -899,7 +920,7 @@ void AppClass::killDownloadSessions() {
 	for (QMap<int32, uint64>::iterator i = killDownloadSessionTimes.begin(); i != killDownloadSessionTimes.end(); ) {
 		if (i.value() <= ms) {
 			for (int j = 0; j < MTPDownloadSessionsCount; ++j) {
-				MTP::stopSession(MTP::dld[j] + i.key());
+				MTP::stopSession(MTP::dld(j) + i.key());
 			}
 			i = killDownloadSessionTimes.erase(i);
 		} else {
diff --git a/Telegram/SourceFiles/application.h b/Telegram/SourceFiles/application.h
index acae49607..1f69aaaa4 100644
--- a/Telegram/SourceFiles/application.h
+++ b/Telegram/SourceFiles/application.h
@@ -30,7 +30,6 @@ class Application : public QApplication {
 public:
 
 	Application(int &argc, char **argv);
-	~Application();
 
 // Single instance application
 public slots:
@@ -41,11 +40,13 @@ public slots:
 	void socketWritten(qint64 bytes);
 	void socketReading();
 	void newInstanceConnected();
-	void closeApplication();
 
 	void readClients();
 	void removeClients();
 
+	void startApplication(); // will be done in exec()
+	void closeApplication(); // will be done in aboutToQuit()
+
 private:
 
 	typedef QPair<QLocalSocket*, QByteArray> LocalClient;
diff --git a/Telegram/SourceFiles/config.h b/Telegram/SourceFiles/config.h
index 1bffe5ad4..5e68c9995 100644
--- a/Telegram/SourceFiles/config.h
+++ b/Telegram/SourceFiles/config.h
@@ -23,7 +23,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 static const int32 AppVersion = 9028;
 static const wchar_t *AppVersionStr = L"0.9.28";
 static const bool DevVersion = false;
-#define BETA_VERSION (9028001ULL) // just comment this line to build public version
+#define BETA_VERSION (9028002ULL) // just comment this line to build public version
 
 static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)";
 static const wchar_t *AppName = L"Telegram Desktop";
diff --git a/Telegram/SourceFiles/logs.cpp b/Telegram/SourceFiles/logs.cpp
index 4a90c14aa..67c1e55af 100644
--- a/Telegram/SourceFiles/logs.cpp
+++ b/Telegram/SourceFiles/logs.cpp
@@ -292,7 +292,7 @@ namespace SignalHandlers {
 
 namespace Logs {
 
-	Initializer::Initializer() {
+	void start() {
 		t_assert(LogsData == 0);
 
 		if (!Sandbox::CheckBetaVersionDir()) {
@@ -378,7 +378,7 @@ namespace Logs {
 		LOG(("Logs started"));
 	}
 
-	Initializer::~Initializer() {
+	void finish() {
 		delete LogsData;
 		LogsData = 0;
 
diff --git a/Telegram/SourceFiles/logs.h b/Telegram/SourceFiles/logs.h
index 451fb8179..df2398117 100644
--- a/Telegram/SourceFiles/logs.h
+++ b/Telegram/SourceFiles/logs.h
@@ -23,11 +23,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 class MTPlong;
 namespace Logs {
 
-	struct Initializer {
-		Initializer();
-		~Initializer();
-	};
+	void start();
 	bool started();
+	void finish();
 
 	bool instanceChecked();
 	void multipleInstances();
diff --git a/Telegram/SourceFiles/main.cpp b/Telegram/SourceFiles/main.cpp
index 508fb9052..2cbe3e078 100644
--- a/Telegram/SourceFiles/main.cpp
+++ b/Telegram/SourceFiles/main.cpp
@@ -25,8 +25,6 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 #include "localstorage.h"
 
 int main(int argc, char *argv[]) {
-	int result = 0;
-
 	settingsParseArgs(argc, argv);
 	if (cLaunchMode() == LaunchModeFixPrevious) {
 		return psFixPrevious();
@@ -36,34 +34,15 @@ int main(int argc, char *argv[]) {
 		return showCrashReportWindow(QFileInfo(cStartUrl()).absoluteFilePath());
 	}
 
-	Logs::Initializer _logs;
-	{
-		PlatformSpecific::Initializer _ps;
+	// both are finished in Application::closeApplication
+	Logs::start(); // must be started before PlatformSpecific is started
+	PlatformSpecific::start(); // must be started before QApplication is created
 
-		QByteArray args[] = { "-style=0" }; // prepare fake args to disable QT_STYLE_OVERRIDE env variable
-		static const int a_cnt = sizeof(args) / sizeof(args[0]);
-		int a_argc = a_cnt + 1;
-		char *a_argv[a_cnt + 1] = { argv[0], args[0].data() };
+	//QByteArray args[] = { "-style=0" }; // prepare fake args to disable QT_STYLE_OVERRIDE env variable
+	//static const int a_cnt = sizeof(args) / sizeof(args[0]);
+	//int a_argc = a_cnt + 1;
+	//char *a_argv[a_cnt + 1] = { argv[0], args[0].data() };
 
-		Application app(a_argc, a_argv);
-		if (!App::quiting()) {
-			result = app.exec();
-		}
-	}
-
-	DEBUG_LOG(("Telegram finished, result: %1").arg(result));
-
-	#ifndef TDESKTOP_DISABLE_AUTOUPDATE
-	if (cRestartingUpdate()) {
-		DEBUG_LOG(("Application Info: executing updater to install update.."));
-		psExecUpdater();
-	} else
-	#endif
-	if (cRestarting()) {
-		DEBUG_LOG(("Application Info: executing Telegram, because of restart.."));
-		psExecTelegram();
-	}
-
-	SignalHandlers::finish();
-	return result;
+	Application app(argc, argv);
+	return app.exec();
 }
diff --git a/Telegram/SourceFiles/mtproto/mtp.cpp b/Telegram/SourceFiles/mtproto/mtp.cpp
index 1770bcef1..4c2ce87fb 100644
--- a/Telegram/SourceFiles/mtproto/mtp.cpp
+++ b/Telegram/SourceFiles/mtproto/mtp.cpp
@@ -24,10 +24,9 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 #include "localstorage.h"
 
 namespace {
-	typedef QMap<int32, MTProtoSessionPtr> Sessions;
+	typedef QMap<int32, MTProtoSession*> Sessions;
 	Sessions sessions;
-	QVector<MTProtoSessionPtr> sessionsToKill;
-	MTProtoSessionPtr mainSession;
+	MTProtoSession *mainSession;
 
 	typedef QMap<mtpRequestId, int32> RequestsByDC; // holds dcWithShift for request to this dc or -dc for request to main dc
 	RequestsByDC requestsByDC;
@@ -62,13 +61,16 @@ namespace {
 	typedef QMap<int32, DCAuthWaiters> AuthWaiters; // holds request ids waiting for auth import to specific dc
 	AuthWaiters authWaiters;
 
+	typedef OrderedSet<MTProtoConnection*> MTPQuittingConnections;
+	MTPQuittingConnections quittingConnections;
+
 	QMutex toClearLock;
 	RPCCallbackClears toClear;
 
 	RPCResponseHandler globalHandler;
 	MTPStateChangedHandler stateChangedHandler = 0;
 	MTPSessionResetHandler sessionResetHandler = 0;
-	_mtp_internal::RequestResender *resender = 0;
+	_mtp_internal::GlobalSlotCarrier *_globalSlotCarrier = 0;
 
 	void importDone(const MTPauth_Authorization &result, mtpRequestId req) {
 		QMutexLocker locker1(&requestByDCLock);
@@ -111,7 +113,7 @@ namespace {
 					}
 					DEBUG_LOG(("MTP Info: resending request %1 to dc %2 after import auth").arg(requestId).arg(k.value()));
 				}
-				if (MTProtoSessionPtr session = _mtp_internal::getSession(dcWithShift)) {
+				if (MTProtoSession *session = _mtp_internal::getSession(dcWithShift)) {
 					session->sendPrepared(j.value());
 				}
 			}
@@ -202,7 +204,7 @@ namespace {
 				}
 				req = i.value();
 			}
-			if (MTProtoSessionPtr session = _mtp_internal::getSession(newdcWithShift)) {
+			if (MTProtoSession *session = _mtp_internal::getSession(newdcWithShift)) {
 				_mtp_internal::registerRequest(requestId, (dcWithShift < 0) ? -newdcWithShift : newdcWithShift);
 				session->sendPrepared(req);
 			}
@@ -230,7 +232,7 @@ namespace {
 			}
 			delayedRequests.insert(i, DelayedRequest(requestId, sendAt));
 
-			if (resender) resender->checkDelayed();
+			if (_globalSlotCarrier) _globalSlotCarrier->checkDelayed();
 
 			return true;
 		} else if (code == 401 || (badGuestDC && badGuestDCRequests.constFind(requestId) == badGuestDCRequests.cend())) {
@@ -281,7 +283,7 @@ namespace {
 			}
 			if (!dcWithShift) return false;
 
-			if (MTProtoSessionPtr session = _mtp_internal::getSession(dcWithShift < 0 ? (-dcWithShift) : dcWithShift)) {
+			if (MTProtoSession *session = _mtp_internal::getSession(dcWithShift < 0 ? (-dcWithShift) : dcWithShift)) {
 				req->needsLayer = true;
 				session->sendPrepared(req);
 			}
@@ -319,7 +321,7 @@ namespace {
 			if (!dcWithShift) return false;
 
 			if (!req->after) {
-				if (MTProtoSessionPtr session = _mtp_internal::getSession(dcWithShift < 0 ? (-dcWithShift) : dcWithShift)) {
+				if (MTProtoSession *session = _mtp_internal::getSession(dcWithShift < 0 ? (-dcWithShift) : dcWithShift)) {
 					req->needsLayer = true;
 					session->sendPrepared(req);
 				}
@@ -346,7 +348,7 @@ namespace {
 						delayedRequests.insert(i, DelayedRequest(requestId, i->second));
 					}
 
-					if (resender) resender->checkDelayed();
+					if (_globalSlotCarrier) _globalSlotCarrier->checkDelayed();
 				}
 			}
 			return true;
@@ -360,21 +362,18 @@ namespace {
 }
 
 namespace _mtp_internal {
-	MTProtoSessionPtr getSession(int32 dcWithShift) {
-		if (!_started) return MTProtoSessionPtr();
+	MTProtoSession *getSession(int32 dcWithShift) {
+		if (!_started) return 0;
 		if (!dcWithShift) return mainSession;
 		if (!(dcWithShift % _mtp_internal::dcShift)) {
 			dcWithShift += (mainSession->getDcWithShift() % _mtp_internal::dcShift);
 		}
 
 		Sessions::const_iterator i = sessions.constFind(dcWithShift);
-		if (i != sessions.cend()) return *i;
-
-		MTProtoSessionPtr result(new MTProtoSession());
-		result->start(dcWithShift);
-
-		sessions.insert(dcWithShift, result);
-		return result;
+		if (i == sessions.cend()) {
+			i = sessions.insert(dcWithShift, new MTProtoSession(dcWithShift));
+		}
+		return i.value();
 	}
 
 	bool paused() {
@@ -580,11 +579,11 @@ namespace _mtp_internal {
 		return true;
 	}
 
-	RequestResender::RequestResender() {
+	GlobalSlotCarrier::GlobalSlotCarrier() {
 		connect(&_timer, SIGNAL(timeout()), this, SLOT(checkDelayed()));
 	}
 
-	void RequestResender::checkDelayed() {
+	void GlobalSlotCarrier::checkDelayed() {
 		uint64 now = getms(true);
 		while (!delayedRequests.isEmpty() && now >= delayedRequests.front().second) {
 			mtpRequestId requestId = delayedRequests.front().first;
@@ -612,7 +611,7 @@ namespace _mtp_internal {
 				}
 				req = j.value();
 			}
-			if (MTProtoSessionPtr session = _mtp_internal::getSession(dcWithShift < 0 ? (-dcWithShift) : dcWithShift)) {
+			if (MTProtoSession *session = _mtp_internal::getSession(dcWithShift < 0 ? (-dcWithShift) : dcWithShift)) {
 				session->sendPrepared(req);
 			}
 		}
@@ -621,6 +620,25 @@ namespace _mtp_internal {
 			_timer.start(delayedRequests.front().second - now);
 		}
 	}
+
+	void GlobalSlotCarrier::connectionFinished(MTProtoConnection *connection) {
+		MTPQuittingConnections::iterator i = quittingConnections.find(connection);
+		if (i != quittingConnections.cend()) {
+			quittingConnections.erase(i);
+		}
+
+		connection->waitTillFinish();
+		delete connection;
+	}
+
+	GlobalSlotCarrier *globalSlotCarrier() {
+		return _globalSlotCarrier;
+	}
+
+	void queueQuittingConnection(MTProtoConnection *connection) {
+		quittingConnections.insert(connection);
+	}
+
 };
 
 namespace MTP {
@@ -637,12 +655,12 @@ namespace MTP {
 
 		MTProtoDCMap &dcs(mtpDCMap());
 
-		mainSession = MTProtoSessionPtr(new MTProtoSession());
-		mainSession->start(mtpMainDC());
-		sessions[mainSession->getDcWithShift()] = mainSession;
+		_globalSlotCarrier = new _mtp_internal::GlobalSlotCarrier();
+
+		mainSession = new MTProtoSession(mtpMainDC());
+		sessions.insert(mainSession->getDcWithShift(), mainSession);
 
 		_started = true;
-		resender = new _mtp_internal::RequestResender();
 
 		if (mtpNeedConfig()) {
 			mtpConfigLoader()->load();
@@ -657,7 +675,7 @@ namespace MTP {
 		if (!_started) return;
 
 		for (Sessions::const_iterator i = sessions.cbegin(), e = sessions.cend(); i != e; ++i) {
-			(*i)->restart();
+			i.value()->restart();
 		}
 	}
 
@@ -666,8 +684,8 @@ namespace MTP {
 
 		dcMask %= _mtp_internal::dcShift;
 		for (Sessions::const_iterator i = sessions.cbegin(), e = sessions.cend(); i != e; ++i) {
-			if (((*i)->getDcWithShift() % int(_mtp_internal::dcShift)) == dcMask) {
-				(*i)->restart();
+			if ((i.value()->getDcWithShift() % int(_mtp_internal::dcShift)) == dcMask) {
+				i.value()->restart();
 			}
 		}
 	}
@@ -681,7 +699,7 @@ namespace MTP {
 		if (!_started) return;
 		_paused = false;
 		for (Sessions::const_iterator i = sessions.cbegin(), e = sessions.cend(); i != e; ++i) {
-			(*i)->unpaused();
+			i.value()->unpaused();
 		}
 	}
 
@@ -714,7 +732,7 @@ namespace MTP {
 		}
 
 		Sessions::const_iterator i = sessions.constFind(dc);
-		if (i != sessions.cend()) return (*i)->getState();
+		if (i != sessions.cend()) return i.value()->getState();
 
 		return MTProtoConnection::Disconnected;
 	}
@@ -728,13 +746,13 @@ namespace MTP {
 		}
 
 		Sessions::const_iterator i = sessions.constFind(dc);
-		if (i != sessions.cend()) return (*i)->transport();
+		if (i != sessions.cend()) return i.value()->transport();
 
 		return QString();
 	}
 
 	void ping() {
-		if (MTProtoSessionPtr session = _mtp_internal::getSession(0)) {
+		if (MTProtoSession *session = _mtp_internal::getSession(0)) {
 			session->ping();
 		}
 	}
@@ -754,7 +772,7 @@ namespace MTP {
 			QMutexLocker locker(&requestByDCLock);
 			RequestsByDC::iterator i = requestsByDC.find(requestId);
 			if (i != requestsByDC.end()) {
-				if (MTProtoSessionPtr session = _mtp_internal::getSession(abs(i.value()))) {
+				if (MTProtoSession *session = _mtp_internal::getSession(abs(i.value()))) {
 					session->cancel(requestId, msgId);
 				}
 				requestsByDC.erase(i);
@@ -763,26 +781,25 @@ namespace MTP {
 		_mtp_internal::clearCallbacks(requestId);
 	}
 
-	void killSessionsDelayed() {
-		if (!sessionsToKill.isEmpty()) {
-			sessionsToKill.clear();
-		}
-	}
-
 	void killSession(int32 dc) {
 		Sessions::iterator i = sessions.find(dc);
-		if (i != sessions.end()) {
+		if (i != sessions.cend()) {
 			bool wasMain = (i.value() == mainSession);
 
 			i.value()->kill();
-			if (sessionsToKill.isEmpty()) QTimer::singleShot(0, killSessionsDelayed);
-			sessionsToKill.push_back(i.value());
+			i.value()->deleteLater();
 			sessions.erase(i);
 
 			if (wasMain) {
-				mainSession = MTProtoSessionPtr(new MTProtoSession());
-				mainSession->start(mtpMainDC());
-				sessions[mainSession->getDcWithShift()] = mainSession;
+				mainSession = new MTProtoSession(mtpMainDC());
+				int32 newdc = mainSession->getDcWithShift();
+				i = sessions.find(newdc);
+				if (i != sessions.cend()) {
+					i.value()->kill();
+					i.value()->deleteLater();
+					sessions.erase(i);
+				}
+				sessions.insert(newdc, mainSession);
 			}
 		}
 	}
@@ -801,14 +818,14 @@ namespace MTP {
 			QMutexLocker locker(&requestByDCLock);
 			RequestsByDC::iterator i = requestsByDC.find(requestId);
 			if (i != requestsByDC.end()) {
-				if (MTProtoSessionPtr session = _mtp_internal::getSession(abs(i.value()))) {
+				if (MTProtoSession *session = _mtp_internal::getSession(abs(i.value()))) {
 					return session->requestState(requestId);
 				}
 				return MTP::RequestConnecting;
 			}
 			return MTP::RequestSent;
 		}
-		if (MTProtoSessionPtr session = _mtp_internal::getSession(-requestId)) {
+		if (MTProtoSession *session = _mtp_internal::getSession(-requestId)) {
 			return session->requestState(0);
 		}
 		return MTP::RequestConnecting;
@@ -817,11 +834,20 @@ namespace MTP {
 	void stop() {
 		for (Sessions::iterator i = sessions.begin(), e = sessions.end(); i != e; ++i) {
 			i.value()->kill();
+			delete i.value();
 		}
 		sessions.clear();
-		mainSession = MTProtoSessionPtr();
-		delete resender;
-		resender = 0;
+		mainSession = nullptr;
+
+		for (MTPQuittingConnections::const_iterator i = quittingConnections.cbegin(), e = quittingConnections.cend(); i != e; ++i) {
+			i.key()->waitTillFinish();
+			delete i.key();
+		}
+		quittingConnections.clear();
+
+		delete _globalSlotCarrier;
+		_globalSlotCarrier = nullptr;
+
 		mtpDestroyConfigLoader();
 
 		_started = false;
diff --git a/Telegram/SourceFiles/mtproto/mtp.h b/Telegram/SourceFiles/mtproto/mtp.h
index ac79f5e3c..a59c092b9 100644
--- a/Telegram/SourceFiles/mtproto/mtp.h
+++ b/Telegram/SourceFiles/mtproto/mtp.h
@@ -24,7 +24,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 #include "mtproto/mtpFileLoader.h"
 
 namespace _mtp_internal {
-	MTProtoSessionPtr getSession(int32 dc = 0); // 0 - current set dc
+	MTProtoSession *getSession(int32 dc); // 0 - current set dc
 
 	bool paused();
 
@@ -49,21 +49,28 @@ namespace _mtp_internal {
 		return rpcErrorOccured(requestId, handler.onFail, err);
 	}
 
-	class RequestResender : public QObject {
+	// used for:
+	// - resending requests by timer which were postponed by flood delay
+	// - destroying MTProtoConnections whose thread has finished
+	class GlobalSlotCarrier : public QObject {
 		Q_OBJECT
 
 	public:
 
-		RequestResender();
+		GlobalSlotCarrier();
 
 	public slots:
 
 		void checkDelayed();
+		void connectionFinished(MTProtoConnection *connection);
 
 	private:
 
 		SingleTimer _timer;
 	};
+
+	GlobalSlotCarrier *globalSlotCarrier();
+	void queueQuittingConnection(MTProtoConnection *connection);
 };
 
 namespace MTP {
@@ -99,7 +106,7 @@ namespace MTP {
 
 	template <typename TRequest>
 	inline mtpRequestId send(const TRequest &request, RPCResponseHandler callbacks = RPCResponseHandler(), int32 dc = 0, uint64 msCanWait = 0, mtpRequestId after = 0) {
-		if (MTProtoSessionPtr session = _mtp_internal::getSession(dc)) {
+		if (MTProtoSession *session = _mtp_internal::getSession(dc)) {
 			return session->send(request, callbacks, msCanWait, true, !dc, after);
 		}
 		return 0;
@@ -109,7 +116,7 @@ namespace MTP {
 		return send(request, RPCResponseHandler(onDone, onFail), dc, msCanWait, after);
 	}
 	inline void sendAnything(int32 dc = 0, uint64 msCanWait = 0) {
-		if (MTProtoSessionPtr session = _mtp_internal::getSession(dc)) {
+		if (MTProtoSession *session = _mtp_internal::getSession(dc)) {
 			return session->sendAnything(msCanWait);
 		}
 	}
diff --git a/Telegram/SourceFiles/mtproto/mtpConnection.cpp b/Telegram/SourceFiles/mtproto/mtpConnection.cpp
index e5959811b..ae2fd2373 100644
--- a/Telegram/SourceFiles/mtproto/mtpConnection.cpp
+++ b/Telegram/SourceFiles/mtproto/mtpConnection.cpp
@@ -252,8 +252,6 @@ namespace {
 	typedef QMap<uint64, mtpPublicRSA> PublicRSAKeys;
 	PublicRSAKeys gPublicRSA;
 
-	MTProtoConnection gMainConnection;
-
 	bool gConfigInited = false;
 	void initRSAConfig() {
 		if (gConfigInited) return;
@@ -277,66 +275,75 @@ namespace {
 	}
 }
 
-MTPThread::MTPThread(QObject *parent) : QThread(parent) {
-	static uint32 gThreadId = 0;
-	threadId = ++gThreadId;
+uint32 MTPThreadIdIncrement = 0;
+
+MTPThread::MTPThread() : QThread(0)
+, _threadId(++MTPThreadIdIncrement) {
 }
 
 uint32 MTPThread::getThreadId() const {
-	return threadId;
+	return _threadId;
 }
 
-MTProtoConnection::MTProtoConnection() : thread(0), data(0) {
+MTPThread::~MTPThread() {
+}
+
+MTProtoConnection::MTProtoConnection() : thread(nullptr), data(nullptr) {
 }
 
 int32 MTProtoConnection::start(MTPSessionData *sessionData, int32 dc) {
+	t_assert(thread == nullptr && data == nullptr);
+
 	initRSAConfig();
 
-	if (thread) {
-		DEBUG_LOG(("MTP Info: MTP start called for already working connection"));
-		return dc;
-	}
-
-	thread = new MTPThread(QApplication::instance());
+	thread = new MTPThread();
 	data = new MTProtoConnectionPrivate(thread, this, sessionData, dc);
 
 	dc = data->getDC();
 	if (!dc) {
 		delete data;
+		data = nullptr;
 		delete thread;
-		data = 0;
-		thread = 0;
+		thread = nullptr;
 		return 0;
 	}
+
 	thread->start();
 	return dc;
 }
 
-void MTProtoConnection::stop() {
-	if (data) data->stop();
-	if (thread) thread->quit();
+void MTProtoConnection::kill() {
+	t_assert(data != nullptr && thread != nullptr);
+	data->stop();
+	data = nullptr; // will be deleted in thread::finished signal
+	thread->quit();
+	_mtp_internal::queueQuittingConnection(this);
 }
 
-void MTProtoConnection::stopped() {
-	if (thread) thread->deleteLater();
-	if (data) data->deleteLater();
-	thread = 0;
-	data = 0;
-	delete this;
+void MTProtoConnection::waitTillFinish() {
+	t_assert(data == nullptr && thread != nullptr);
+
+	thread->wait();
+	delete thread;
+	thread = nullptr;
 }
 
 int32 MTProtoConnection::state() const {
-	if (!data) return Disconnected;
+	t_assert(data != nullptr && thread != nullptr);
 
 	return data->getState();
 }
 
 QString MTProtoConnection::transport() const {
-	if (!data) return QString();
+	t_assert(data != nullptr && thread != nullptr);
 
 	return data->transport();
 }
 
+MTProtoConnection::~MTProtoConnection() {
+	t_assert(data == nullptr && thread == nullptr);
+}
+
 namespace {
 	mtpBuffer _handleHttpResponse(QNetworkReply *reply) {
 		QByteArray response = reply->readAll();
@@ -1311,30 +1318,31 @@ void MTProtoConnectionPrivate::destroyConn(MTPabstractConnection **conn) {
 	}
 }
 
-MTProtoConnectionPrivate::MTProtoConnectionPrivate(QThread *thread, MTProtoConnection *owner, MTPSessionData *data, uint32 _dc)
-	: QObject(0)
-	, _state(MTProtoConnection::Disconnected)
-	, _needSessionReset(false)
-	, dc(_dc)
-    , _owner(owner)
-	, _conn(0), _conn4(0), _conn6(0)
-    , retryTimeout(1)
-    , oldConnection(true)
-    , _waitForReceived(MTPMinReceiveDelay)
-	, _waitForConnected(MTPMinConnectDelay)
-    , firstSentAt(-1)
-    , _pingId(0)
-	, _pingIdToSend(0)
-	, _pingSendAt(0)
-    , _pingMsgId(0)
-    , restarted(false)
-    , keyId(0)
+MTProtoConnectionPrivate::MTProtoConnectionPrivate(QThread *thread, MTProtoConnection *owner, MTPSessionData *data, uint32 _dc) : QObject(0)
+, _state(MTProtoConnection::Disconnected)
+, _needSessionReset(false)
+, dc(_dc)
+, _owner(owner)
+, _conn(0)
+, _conn4(0)
+, _conn6(0)
+, retryTimeout(1)
+, oldConnection(true)
+, _waitForReceived(MTPMinReceiveDelay)
+, _waitForConnected(MTPMinConnectDelay)
+, firstSentAt(-1)
+, _pingId(0)
+, _pingIdToSend(0)
+, _pingSendAt(0)
+, _pingMsgId(0)
+, restarted(false)
+, _finished(false)
+, keyId(0)
 //	, sessionDataMutex(QReadWriteLock::Recursive)
-    , sessionData(data)
-    , myKeyLock(false)
-	, authKeyData(0)
-	, authKeyStrings(0) {
-
+, sessionData(data)
+, myKeyLock(false)
+, authKeyData(0)
+, authKeyStrings(0) {
 	oldConnectionTimer.moveToThread(thread);
 	_waitForConnectedTimer.moveToThread(thread);
 	_waitForReceivedTimer.moveToThread(thread);
@@ -1357,6 +1365,7 @@ MTProtoConnectionPrivate::MTProtoConnectionPrivate(QThread *thread, MTProtoConne
 
 	connect(thread, SIGNAL(started()), this, SLOT(socketStart()));
 	connect(thread, SIGNAL(finished()), this, SLOT(doFinish()));
+	connect(this, SIGNAL(finished(MTProtoConnection*)), _mtp_internal::globalSlotCarrier(), SLOT(connectionFinished(MTProtoConnection*)), Qt::QueuedConnection);
 
 	connect(&retryTimer, SIGNAL(timeout()), this, SLOT(retryByTimer()));
 	connect(&_waitForConnectedTimer, SIGNAL(timeout()), this, SLOT(onWaitConnectedFailed()));
@@ -1966,6 +1975,10 @@ void MTProtoConnectionPrivate::restartNow() {
 }
 
 void MTProtoConnectionPrivate::socketStart(bool afterConfig) {
+	if (_finished) {
+		DEBUG_LOG(("MTP Error: socketStart() called for finished connection!"));
+		return;
+	}
 	bool isDldDc = (dc >= MTP::dldStart) && (dc < MTP::dldEnd);
 	if (isDldDc) { // using media_only addresses only if key for this dc is already created
 		QReadLocker lockFinished(&sessionDataMutex);
@@ -2231,7 +2244,9 @@ void MTProtoConnectionPrivate::doDisconnect() {
 
 void MTProtoConnectionPrivate::doFinish() {
 	doDisconnect();
-	_owner->stopped();
+	_finished = true;
+	emit finished(_owner);
+	deleteLater();
 }
 
 void MTProtoConnectionPrivate::handleReceived() {
@@ -3928,7 +3943,7 @@ void MTProtoConnectionPrivate::unlockKey() {
 }
 
 MTProtoConnectionPrivate::~MTProtoConnectionPrivate() {
-	doDisconnect();
+	t_assert(_finished && _conn == nullptr && _conn4 == nullptr && _conn6 == nullptr);
 }
 
 void MTProtoConnectionPrivate::stop() {
@@ -3939,9 +3954,6 @@ void MTProtoConnectionPrivate::stop() {
 			sessionData->keyMutex()->unlock();
 			myKeyLock = false;
 		}
-		sessionData = 0;
+		sessionData = nullptr;
 	}
 }
-
-MTProtoConnection::~MTProtoConnection() {
-}
diff --git a/Telegram/SourceFiles/mtproto/mtpConnection.h b/Telegram/SourceFiles/mtproto/mtpConnection.h
index 1d2d684cf..8ac08b94b 100644
--- a/Telegram/SourceFiles/mtproto/mtpConnection.h
+++ b/Telegram/SourceFiles/mtproto/mtpConnection.h
@@ -58,11 +58,13 @@ class MTPThread : public QThread {
 	Q_OBJECT
 
 public:
-	MTPThread(QObject *parent = 0);
+	MTPThread();
 	uint32 getThreadId() const;
+	~MTPThread();
 
 private:
-	uint32 threadId;
+	uint32 _threadId;
+
 };
 
 class MTProtoConnection {
@@ -75,8 +77,8 @@ public:
 
 	MTProtoConnection();
 	int32 start(MTPSessionData *data, int32 dc = 0); // return dc
-	void stop();
-	void stopped();
+	void kill();
+	void waitTillFinish();
 	~MTProtoConnection();
 
 	enum {
@@ -358,6 +360,8 @@ signals:
 	void resendManyAsync(QVector<quint64> msgIds, quint64 msCanWait, bool forceContainer, bool sendMsgStateInfo);
 	void resendAllAsync();
 
+	void finished(MTProtoConnection *connection);
+
 public slots:
 
 	void retryByTimer();
@@ -466,7 +470,7 @@ private:
 	template <typename TResponse>
 	bool readResponseNotSecure(TResponse &response);
 
-	bool restarted;
+	bool restarted, _finished;
 
 	uint64 keyId;
 	QReadWriteLock sessionDataMutex;
diff --git a/Telegram/SourceFiles/mtproto/mtpSession.cpp b/Telegram/SourceFiles/mtproto/mtpSession.cpp
index 54ed49cb9..a6d6d918c 100644
--- a/Telegram/SourceFiles/mtproto/mtpSession.cpp
+++ b/Telegram/SourceFiles/mtproto/mtpSession.cpp
@@ -66,7 +66,8 @@ void MTPSessionData::clear() {
 }
 
 
-MTProtoSession::MTProtoSession() : QObject()
+MTProtoSession::MTProtoSession(int32 dcenter) : QObject()
+, _connection(0)
 , _killed(false)
 , _needToReceive(false)
 , data(this)
@@ -75,9 +76,6 @@ MTProtoSession::MTProtoSession() : QObject()
 , msSendCall(0)
 , msWait(0)
 , _ping(false) {
-}
-
-void MTProtoSession::start(int32 dcenter) {
 	if (_killed) {
 		DEBUG_LOG(("Session Error: can't start a killed session"));
 		return;
@@ -96,37 +94,32 @@ void MTProtoSession::start(int32 dcenter) {
 
 	MTProtoDCMap &dcs(mtpDCMap());
 
-	connections.reserve(cConnectionsInSession());
-	for (uint32 i = 0; i < cConnectionsInSession(); ++i) {
-		connections.push_back(new MTProtoConnection());
-		dcWithShift = connections.back()->start(&data, dcenter);
-		if (!dcWithShift) {
-			for (MTProtoConnections::const_iterator j = connections.cbegin(), e = connections.cend(); j != e; ++j) {
-				delete *j;
-			}
-			connections.clear();
-			DEBUG_LOG(("Session Info: could not start connection %1 to dc %2").arg(i).arg(dcenter));
-			return;
+	_connection = new MTProtoConnection();
+	dcWithShift = _connection->start(&data, dcenter);
+	if (!dcWithShift) {
+		delete _connection;
+		_connection = 0;
+		DEBUG_LOG(("Session Info: could not start connection to dc %1").arg(dcenter));
+		return;
+	}
+	if (!dc) {
+		dcenter = dcWithShift;
+		int32 dcId = dcWithShift % _mtp_internal::dcShift;
+		MTProtoDCMap::const_iterator dcIndex = dcs.constFind(dcId);
+		if (dcIndex == dcs.cend()) {
+			dc = MTProtoDCPtr(new MTProtoDC(dcId, mtpAuthKeyPtr()));
+			dcs.insert(dcWithShift % _mtp_internal::dcShift, dc);
+		} else {
+			dc = dcIndex.value();
 		}
-		if (!dc) {
-			dcenter = dcWithShift;
-			int32 dcId = dcWithShift % _mtp_internal::dcShift;
-			MTProtoDCMap::const_iterator dcIndex = dcs.constFind(dcId);
-			if (dcIndex == dcs.cend()) {
-				dc = MTProtoDCPtr(new MTProtoDC(dcId, mtpAuthKeyPtr()));
-				dcs.insert(dcWithShift % _mtp_internal::dcShift, dc);
-			} else {
-				dc = dcIndex.value();
-			}
 
-			ReadLockerAttempt lock(keyMutex());
-			data.setKey(lock ? dc->getKey() : mtpAuthKeyPtr(0));
-			if (lock && dc->connectionInited()) {
-				data.setLayerWasInited(true);
-			}
-			connect(dc.data(), SIGNAL(authKeyCreated()), this, SLOT(authKeyCreatedForDC()), Qt::QueuedConnection);
-			connect(dc.data(), SIGNAL(layerWasInited(bool)), this, SLOT(layerWasInitedForDC(bool)), Qt::QueuedConnection);
+		ReadLockerAttempt lock(keyMutex());
+		data.setKey(lock ? dc->getKey() : mtpAuthKeyPtr(0));
+		if (lock && dc->connectionInited()) {
+			data.setLayerWasInited(true);
 		}
+		connect(dc.data(), SIGNAL(authKeyCreated()), this, SLOT(authKeyCreatedForDC()), Qt::QueuedConnection);
+		connect(dc.data(), SIGNAL(layerWasInited(bool)), this, SLOT(layerWasInitedForDC(bool)), Qt::QueuedConnection);
 	}
 }
 
@@ -139,10 +132,14 @@ void MTProtoSession::restart() {
 }
 
 void MTProtoSession::stop() {
+	if (_killed) {
+		DEBUG_LOG(("Session Error: can't kill a killed session"));
+		return;
+	}
 	DEBUG_LOG(("Session Info: stopping session dcWithShift %1").arg(dcWithShift));
-	while (!connections.isEmpty()) {
-		connections.back()->stop();
-		connections.pop_back();
+	if (_connection) {
+		_connection->kill();
+		_connection = 0;
 	}
 }
 
@@ -194,22 +191,17 @@ void MTProtoSession::needToResumeAndSend() {
 		DEBUG_LOG(("Session Info: can't resume a killed session"));
 		return;
 	}
-	if (connections.isEmpty()) {
+	if (!_connection) {
 		DEBUG_LOG(("Session Info: resuming session dcWithShift %1").arg(dcWithShift));
 		MTProtoDCMap &dcs(mtpDCMap());
 
-		connections.reserve(cConnectionsInSession());
-		for (uint32 i = 0; i < cConnectionsInSession(); ++i) {
-			connections.push_back(new MTProtoConnection());
-			if (!connections.back()->start(&data, dcWithShift)) {
-				for (MTProtoConnections::const_iterator j = connections.cbegin(), e = connections.cend(); j != e; ++j) {
-					delete *j;
-				}
-				connections.clear();
-				DEBUG_LOG(("Session Info: could not start connection %1 to dcWithShift %2").arg(i).arg(dcWithShift));
-				dcWithShift = 0;
-				return;
-			}
+		_connection = new MTProtoConnection();
+		if (!_connection->start(&data, dcWithShift)) {
+			delete _connection;
+			_connection = 0;
+			DEBUG_LOG(("Session Info: could not start connection to dcWithShift %1").arg(dcWithShift));
+			dcWithShift = 0;
+			return;
 		}
 	}
 	if (_ping) {
@@ -324,12 +316,13 @@ void MTProtoSession::ping() {
 }
 
 int32 MTProtoSession::requestState(mtpRequestId requestId) const {
-	MTProtoConnections::const_iterator j = connections.cbegin(), e = connections.cend();
 	int32 result = MTP::RequestSent;
-	for (; j != e; ++j) {
-		int32 s = (*j)->state();
+
+	bool connected = false;
+	if (_connection) {
+		int32 s = _connection->state();
 		if (s == MTProtoConnection::Connected) {
-			break;
+			connected = true;
 		} else if (s == MTProtoConnection::Connecting || s == MTProtoConnection::Disconnected) {
 			if (result < 0 || result == MTP::RequestSent) {
 				result = MTP::RequestConnecting;
@@ -340,7 +333,7 @@ int32 MTProtoSession::requestState(mtpRequestId requestId) const {
 			}
 		}
 	}
-	if (j == e) { // no one is connected
+	if (!connected) {
 		return result;
 	}
 	if (!requestId) return MTP::RequestSent;
@@ -356,10 +349,10 @@ int32 MTProtoSession::requestState(mtpRequestId requestId) const {
 }
 
 int32 MTProtoSession::getState() const {
-	MTProtoConnections::const_iterator j = connections.cbegin(), e = connections.cend();
 	int32 result = -86400000;
-	for (; j != e; ++j) {
-		int32 s = (*j)->state();
+
+	if (_connection) {
+		int32 s = _connection->state();
 		if (s == MTProtoConnection::Connected) {
 			return s;
 		} else if (s == MTProtoConnection::Connecting || s == MTProtoConnection::Disconnected) {
@@ -379,12 +372,7 @@ int32 MTProtoSession::getState() const {
 }
 
 QString MTProtoSession::transport() const {
-	MTProtoConnections::const_iterator j = connections.cbegin(), e = connections.cend();
-	for (; j != e; ++j) {
-		QString s = (*j)->transport();
-		if (!s.isEmpty()) return s;
-	}
-	return QString();
+	return _connection ? _connection->transport() : QString();
 }
 
 mtpRequestId MTProtoSession::resend(quint64 msgId, quint64 msCanWait, bool forceContainer, bool sendMsgStateInfo) {
@@ -507,6 +495,10 @@ int32 MTProtoSession::getDcWithShift() const {
 }
 
 void MTProtoSession::tryToReceive() {
+	if (_killed) {
+		DEBUG_LOG(("Session Error: can't receive in a killed session"));
+		return;
+	}
 	if (_mtp_internal::paused()) {
 		_needToReceive = true;
 		return;
@@ -537,9 +529,7 @@ void MTProtoSession::tryToReceive() {
 }
 
 MTProtoSession::~MTProtoSession() {
-	for (MTProtoConnections::const_iterator i = connections.cbegin(), e = connections.cend(); i != e; ++i) {
-		delete *i;
-	}
+	t_assert(_connection == 0);
 }
 
 MTPrpcError rpcClientError(const QString &type, const QString &description) {
diff --git a/Telegram/SourceFiles/mtproto/mtpSession.h b/Telegram/SourceFiles/mtproto/mtpSession.h
index 23db4fba3..a635372f1 100644
--- a/Telegram/SourceFiles/mtproto/mtpSession.h
+++ b/Telegram/SourceFiles/mtproto/mtpSession.h
@@ -28,7 +28,7 @@ class MTProtoSession;
 
 class MTPSessionData {
 public:
-	
+
 	MTPSessionData(MTProtoSession *creator)
 	: _session(0), _salt(0)
 	, _messagesSent(0), _fakeRequestId(-2000000000)
@@ -222,9 +222,8 @@ class MTProtoSession : public QObject {
 
 public:
 
-	MTProtoSession();
+	MTProtoSession(int32 dcenter);
 
-	void start(int32 dcenter = 0);
 	void restart();
 	void stop();
 	void kill();
@@ -278,13 +277,12 @@ public slots:
 	void sendMsgsStateInfo(quint64 msgId, QByteArray data);
 
 private:
-	
-	typedef QList<MTProtoConnection*> MTProtoConnections;
-	MTProtoConnections connections;
+
+	MTProtoConnection *_connection;
 
 	bool _killed;
 	bool _needToReceive;
-	
+
 	MTPSessionData data;
 
 	int32 dcWithShift;
@@ -304,7 +302,3 @@ inline QReadWriteLock *MTPSessionData::keyMutex() const {
 }
 
 MTPrpcError rpcClientError(const QString &type, const QString &description = QString());
-
-// here
-
-typedef QSharedPointer<MTProtoSession> MTProtoSessionPtr;
diff --git a/Telegram/SourceFiles/pspecific.h b/Telegram/SourceFiles/pspecific.h
index 7362f15da..7003daa42 100644
--- a/Telegram/SourceFiles/pspecific.h
+++ b/Telegram/SourceFiles/pspecific.h
@@ -38,10 +38,8 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 
 namespace PlatformSpecific {
 
-	struct Initializer {
-		Initializer();
-		~Initializer();
-	};
+	void start();
+	void finish();
 
 	namespace ThirdParty {
 		void start();
diff --git a/Telegram/SourceFiles/pspecific_linux.cpp b/Telegram/SourceFiles/pspecific_linux.cpp
index 650c51f10..2134e97dd 100644
--- a/Telegram/SourceFiles/pspecific_linux.cpp
+++ b/Telegram/SourceFiles/pspecific_linux.cpp
@@ -1237,10 +1237,10 @@ void psShowInFolder(const QString &name) {
 
 namespace PlatformSpecific {
 
-	Initializer::Initializer() {
+	void start() {
 	}
 
-	Initializer::~Initializer() {
+	void finish() {
 		delete _psEventFilter;
 		_psEventFilter = 0;
 	}
diff --git a/Telegram/SourceFiles/pspecific_mac.cpp b/Telegram/SourceFiles/pspecific_mac.cpp
index 854ff00d2..f674e84e6 100644
--- a/Telegram/SourceFiles/pspecific_mac.cpp
+++ b/Telegram/SourceFiles/pspecific_mac.cpp
@@ -850,11 +850,11 @@ void psShowInFolder(const QString &name) {
 
 namespace PlatformSpecific {
 
-	Initializer::Initializer() {
+	void start() {
 		objc_start();
 	}
 
-	Initializer::~Initializer() {
+	void finish() {
 		delete _psEventFilter;
 		_psEventFilter = 0;
 
diff --git a/Telegram/SourceFiles/pspecific_wnd.cpp b/Telegram/SourceFiles/pspecific_wnd.cpp
index 1a2e46140..3dc358887 100644
--- a/Telegram/SourceFiles/pspecific_wnd.cpp
+++ b/Telegram/SourceFiles/pspecific_wnd.cpp
@@ -2159,10 +2159,10 @@ void psShowInFolder(const QString &name) {
 
 namespace PlatformSpecific {
 
-	Initializer::Initializer() {
+	void start() {
 	}
 
-	Initializer::~Initializer() {
+	void finish() {
 		delete _psEventFilter;
 		_psEventFilter = 0;
 
diff --git a/Telegram/SourceFiles/settings.h b/Telegram/SourceFiles/settings.h
index b57a6b4f1..93524bba8 100644
--- a/Telegram/SourceFiles/settings.h
+++ b/Telegram/SourceFiles/settings.h
@@ -77,7 +77,6 @@ inline QString cInlineGifBotUsername() {
 	return cTestMode() ? qstr("contextbot") : qstr("gif");
 }
 DeclareSetting(QString, LoggedPhoneNumber);
-DeclareReadSetting(uint32, ConnectionsInSession);
 DeclareSetting(bool, AutoStart);
 DeclareSetting(bool, StartMinimized);
 DeclareSetting(bool, StartInTray);
diff --git a/Telegram/Telegram.rc b/Telegram/Telegram.rc
index 6ad208fd0..f82064666 100644
--- a/Telegram/Telegram.rc
+++ b/Telegram/Telegram.rc
@@ -34,8 +34,8 @@ IDI_ICON1               ICON                    "SourceFiles\\art\\icon256.ico"
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,9,28,1
- PRODUCTVERSION 0,9,28,1
+ FILEVERSION 0,9,28,2
+ PRODUCTVERSION 0,9,28,2
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -51,10 +51,10 @@ BEGIN
         BLOCK "040904b0"
         BEGIN
             VALUE "CompanyName", "Telegram Messenger LLP"
-            VALUE "FileVersion", "0.9.28.1"
+            VALUE "FileVersion", "0.9.28.2"
             VALUE "LegalCopyright", "Copyright (C) 2014-2016"
             VALUE "ProductName", "Telegram Desktop"
-            VALUE "ProductVersion", "0.9.28.1"
+            VALUE "ProductVersion", "0.9.28.2"
         END
     END
     BLOCK "VarFileInfo"
diff --git a/Telegram/Version b/Telegram/Version
index e3f6eee41..c6c53f35a 100644
--- a/Telegram/Version
+++ b/Telegram/Version
@@ -3,4 +3,4 @@ AppVersionStrMajor 0.9
 AppVersionStrSmall 0.9.28
 AppVersionStr      0.9.28
 DevChannel         0
-BetaVersion        9028001
+BetaVersion        9028002