Move some code around.

Move logs:SignalHandlers to core/crash_reports:CrashReports.
Move all pre-launch windows to core/crash_report_window module.
Move some global code to core/launcher:Launcher.
It should replace settings / platform_specific module in some way.
This commit is contained in:
John Preston 2017-12-11 18:45:29 +04:00
parent 9d4558de2b
commit 97c15865a5
48 changed files with 2873 additions and 2373 deletions

View File

@ -946,7 +946,7 @@ void ApiWrap::saveStickerSets(const Stickers::Order &localOrder, const Stickers:
request(base::take(_stickersClearRecentRequestId)).cancel();
auto writeInstalled = true, writeRecent = false, writeCloudRecent = false, writeFaved = false, writeArchived = false;
auto &recent = cGetRecentStickers();
auto &recent = Stickers::GetRecentPack();
auto &sets = Auth().data().stickerSetsRef();
_stickersOrder = localOrder;

View File

@ -46,6 +46,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "numbers.h"
#include "observer_peer.h"
#include "auth_session.h"
#include "core/crash_reports.h"
#include "storage/storage_facade.h"
#include "storage/storage_shared_media.h"
#include "window/themes/window_theme.h"
@ -472,7 +473,7 @@ namespace {
QString pname = (showPhoneChanged || phoneChanged || nameChanged) ? ((showPhone && !phone.isEmpty()) ? formatPhone(phone) : QString()) : data->nameOrPhone;
if (!minimal && d.is_self() && uname != data->username) {
SignalHandlers::setCrashAnnotation("Username", uname);
CrashReports::SetAnnotation("Username", uname);
}
data->setName(fname, lname, pname, uname);
if (d.has_photo()) {

View File

@ -26,8 +26,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "storage/localstorage.h"
#include "autoupdater.h"
#include "window/notifications_manager.h"
#include "core/crash_reports.h"
#include "messenger.h"
#include "base/timer.h"
#include "core/crash_report_window.h"
namespace {
@ -71,8 +73,13 @@ QString _escapeFrom7bit(const QString &str) {
} // namespace
Application::Application(int &argc, char **argv) : QApplication(argc, argv) {
QByteArray d(QFile::encodeName(QDir(cWorkingDir()).absolutePath()));
Application::Application(
not_null<Core::Launcher*> launcher,
int &argc,
char **argv)
: QApplication(argc, argv)
, _launcher(launcher) {
const auto d = QFile::encodeName(QDir(cWorkingDir()).absolutePath());
char h[33] = { 0 };
hashMd5Hex(d.constData(), d.size(), h);
#ifndef OS_MAC_STORE
@ -206,12 +213,12 @@ void Application::singleInstanceChecked() {
if (!Logs::started() || (!cManyInstance() && !Logs::instanceChecked())) {
new NotStartedWindow();
} else {
SignalHandlers::Status status = SignalHandlers::start();
if (status == SignalHandlers::CantOpen) {
const auto status = CrashReports::Start();
if (status == CrashReports::CantOpen) {
new NotStartedWindow();
} else if (status == SignalHandlers::LastCrashed) {
} else if (status == CrashReports::LastCrashed) {
if (Sandbox::LastCrashDump().isEmpty()) { // don't handle bad closing for now
if (SignalHandlers::restart() == SignalHandlers::CantOpen) {
if (CrashReports::Restart() == CrashReports::CantOpen) {
new NotStartedWindow();
} else {
Sandbox::launch();
@ -313,7 +320,7 @@ void Application::startApplication() {
void Application::createMessenger() {
Expects(!App::quitting());
_messengerInstance = std::make_unique<Messenger>();
_messengerInstance = std::make_unique<Messenger>(_launcher);
}
void Application::closeApplication() {

View File

@ -21,11 +21,16 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#pragma once
class UpdateChecker;
namespace Core {
class Launcher;
} // namespace Core
class Application : public QApplication {
Q_OBJECT
public:
Application(int &argc, char **argv);
Application(not_null<Core::Launcher*> launcher, int &argc, char **argv);
bool event(QEvent *e) override;
@ -55,6 +60,7 @@ private:
typedef QPair<QLocalSocket*, QByteArray> LocalClient;
typedef QList<LocalClient> LocalClients;
not_null<Core::Launcher*> _launcher;
std::unique_ptr<Messenger> _messengerInstance;
QString _localServerName, _localSocketReadData;

View File

@ -1551,13 +1551,13 @@ int StickersBox::Inner::fillSetCount(const Stickers::Set &set) const {
auto customIt = Auth().data().stickerSets().constFind(Stickers::CustomSetId);
if (customIt != Auth().data().stickerSets().cend()) {
added = customIt->stickers.size();
for_const (auto &sticker, cGetRecentStickers()) {
for_const (auto &sticker, Stickers::GetRecentPack()) {
if (customIt->stickers.indexOf(sticker.first) < 0) {
++added;
}
}
} else {
added = cGetRecentStickers().size();
added = Stickers::GetRecentPack().size();
}
}
return result + added;

View File

@ -347,7 +347,7 @@ void SetsReceived(const QVector<MTPStickerSet> &data, int32 hash) {
}
}
auto writeRecent = false;
auto &recent = cGetRecentStickers();
auto &recent = GetRecentPack();
for (auto it = sets.begin(), e = sets.end(); it != e;) {
bool installed = (it->flags & MTPDstickerSet::Flag::f_installed);
bool featured = (it->flags & MTPDstickerSet_ClientFlag::f_featured);
@ -449,7 +449,7 @@ void SpecialSetReceived(uint64 setId, const QString &setTitle, const QVector<MTP
}
auto writeRecent = false;
auto &recent = cGetRecentStickers();
auto &recent = GetRecentPack();
for (auto i = recent.begin(); i != recent.cend();) {
if (it->stickers.indexOf(i->first) >= 0 && pack.indexOf(i->first) < 0) {
i = recent.erase(i);
@ -748,7 +748,7 @@ Set *FeedSetFull(const MTPmessages_StickerSet &data) {
}
auto writeRecent = false;
auto &recent = cGetRecentStickers();
auto &recent = GetRecentPack();
for (auto i = recent.begin(); i != recent.cend();) {
if (set->stickers.indexOf(i->first) >= 0 && pack.indexOf(i->first) < 0) {
i = recent.erase(i);
@ -816,4 +816,56 @@ QString GetSetTitle(const MTPDstickerSet &s) {
return title;
}
RecentStickerPack &GetRecentPack() {
if (cRecentStickers().isEmpty() && !cRecentStickersPreload().isEmpty()) {
const auto p = cRecentStickersPreload();
cSetRecentStickersPreload(RecentStickerPreload());
auto &recent = cRefRecentStickers();
recent.reserve(p.size());
for (const auto &preloaded : p) {
const auto document = App::document(preloaded.first);
if (!document || !document->sticker()) continue;
recent.push_back(qMakePair(document, preloaded.second));
}
}
return cRefRecentStickers();
}
void IncrementRecentHashtag(RecentHashtagPack &recent, const QString &tag) {
auto i = recent.begin(), e = recent.end();
for (; i != e; ++i) {
if (i->first == tag) {
++i->second;
if (qAbs(i->second) > 0x4000) {
for (auto j = recent.begin(); j != e; ++j) {
if (j->second > 1) {
j->second /= 2;
} else if (j->second > 0) {
j->second = 1;
}
}
}
for (; i != recent.begin(); --i) {
if (qAbs((i - 1)->second) > qAbs(i->second)) {
break;
}
qSwap(*i, *(i - 1));
}
break;
}
}
if (i == e) {
while (recent.size() >= 64) recent.pop_back();
recent.push_back(qMakePair(tag, 1));
for (i = recent.end() - 1; i != recent.begin(); --i) {
if ((i - 1)->second > i->second) {
break;
}
qSwap(*i, *(i - 1));
}
}
}
} // namespace Stickers

View File

@ -85,4 +85,8 @@ Set *FeedSetFull(const MTPmessages_StickerSet &data);
QString GetSetTitle(const MTPDstickerSet &s);
RecentStickerPack &GetRecentPack();
void IncrementRecentHashtag(RecentHashtagPack &recent, const QString &tag);
} // namespace Stickers

View File

@ -1090,7 +1090,7 @@ void StickersListWidget::removeRecentSticker(int section, int index) {
clearSelection();
bool refresh = false;
auto sticker = _mySets[section].pack[index];
auto &recent = cGetRecentStickers();
auto &recent = Stickers::GetRecentPack();
for (int32 i = 0, l = recent.size(); i < l; ++i) {
if (recent.at(i).first == sticker) {
recent.removeAt(i);
@ -1302,7 +1302,7 @@ void StickersListWidget::refreshRecentStickers(bool performResize) {
_custom.clear();
clearSelection();
auto &sets = Auth().data().stickerSets();
auto &recent = cGetRecentStickers();
auto &recent = Stickers::GetRecentPack();
auto customIt = sets.constFind(Stickers::CustomSetId);
auto cloudIt = sets.constFind(Stickers::CloudRecentSetId);
@ -1773,7 +1773,7 @@ void StickersListWidget::removeSet(uint64 setId) {
request(MTPmessages_UninstallStickerSet(MTP_inputStickerSetShortName(MTP_string(it->shortName)))).send();
}
auto writeRecent = false;
auto &recent = cGetRecentStickers();
auto &recent = Stickers::GetRecentPack();
for (auto i = recent.begin(); i != recent.cend();) {
if (it->stickers.indexOf(i->first) >= 0) {
i = recent.erase(i);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,226 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
class PreLaunchWindow : public QWidget {
public:
PreLaunchWindow(QString title = QString());
void activate();
int basicSize() const {
return _size;
}
~PreLaunchWindow();
static PreLaunchWindow *instance();
protected:
int _size;
};
class PreLaunchLabel : public QLabel {
public:
PreLaunchLabel(QWidget *parent);
void setText(const QString &text);
};
class PreLaunchInput : public QLineEdit {
public:
PreLaunchInput(QWidget *parent, bool password = false);
};
class PreLaunchLog : public QTextEdit {
public:
PreLaunchLog(QWidget *parent);
};
class PreLaunchButton : public QPushButton {
public:
PreLaunchButton(QWidget *parent, bool confirm = true);
void setText(const QString &text);
};
class PreLaunchCheckbox : public QCheckBox {
public:
PreLaunchCheckbox(QWidget *parent);
void setText(const QString &text);
};
class NotStartedWindow : public PreLaunchWindow {
public:
NotStartedWindow();
protected:
void closeEvent(QCloseEvent *e);
void resizeEvent(QResizeEvent *e);
private:
void updateControls();
PreLaunchLabel _label;
PreLaunchLog _log;
PreLaunchButton _close;
};
class LastCrashedWindow : public PreLaunchWindow {
Q_OBJECT
public:
LastCrashedWindow();
public slots:
void onViewReport();
void onSaveReport();
void onSendReport();
void onGetApp();
void onNetworkSettings();
void onNetworkSettingsSaved(QString host, quint32 port, QString username, QString password);
void onContinue();
void onCheckingFinished();
void onSendingError(QNetworkReply::NetworkError e);
void onSendingFinished();
void onSendingProgress(qint64 uploaded, qint64 total);
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
void onUpdateRetry();
void onUpdateSkip();
void onUpdateChecking();
void onUpdateLatest();
void onUpdateDownloading(qint64 ready, qint64 total);
void onUpdateReady();
void onUpdateFailed();
#endif // !TDESKTOP_DISABLE_AUTOUPDATE
protected:
void closeEvent(QCloseEvent *e);
void resizeEvent(QResizeEvent *e);
private:
QString minidumpFileName();
void updateControls();
QString _host, _username, _password;
quint32 _port;
PreLaunchLabel _label, _pleaseSendReport, _yourReportName, _minidump;
PreLaunchLog _report;
PreLaunchButton _send, _sendSkip, _networkSettings, _continue, _showReport, _saveReport, _getApp;
PreLaunchCheckbox _includeUsername;
QString _minidumpName, _minidumpFull, _reportText;
QString _reportUsername, _reportTextNoUsername;
QByteArray getCrashReportRaw() const;
bool _reportShown, _reportSaved;
void excludeReportUsername();
enum SendingState {
SendingNoReport,
SendingUpdateCheck,
SendingNone,
SendingTooOld,
SendingTooMany,
SendingUnofficial,
SendingProgress,
SendingUploading,
SendingFail,
SendingDone,
};
SendingState _sendingState;
PreLaunchLabel _updating;
qint64 _sendingProgress, _sendingTotal;
QNetworkAccessManager _sendManager;
QNetworkReply *_checkReply, *_sendReply;
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
PreLaunchButton _updatingCheck, _updatingSkip;
enum UpdatingState {
UpdatingNone,
UpdatingCheck,
UpdatingLatest,
UpdatingDownload,
UpdatingFail,
UpdatingReady
};
UpdatingState _updatingState;
QString _newVersionDownload;
void setUpdatingState(UpdatingState state, bool force = false);
void setDownloadProgress(qint64 ready, qint64 total);
#endif // !TDESKTOP_DISABLE_AUTOUPDATE
QString getReportField(const QLatin1String &name, const QLatin1String &prefix);
void addReportFieldPart(const QLatin1String &name, const QLatin1String &prefix, QHttpMultiPart *multipart);
};
class NetworkSettingsWindow : public PreLaunchWindow {
Q_OBJECT
public:
NetworkSettingsWindow(QWidget *parent, QString host, quint32 port, QString username, QString password);
signals:
void saved(QString host, quint32 port, QString username, QString password);
public slots:
void onSave();
protected:
void closeEvent(QCloseEvent *e);
void resizeEvent(QResizeEvent *e);
private:
void updateControls();
PreLaunchLabel _hostLabel, _portLabel, _usernameLabel, _passwordLabel;
PreLaunchInput _hostInput, _portInput, _usernameInput, _passwordInput;
PreLaunchButton _save, _cancel;
QWidget *_parent;
};
class ShowCrashReportWindow : public PreLaunchWindow {
public:
ShowCrashReportWindow(const QString &text);
protected:
void resizeEvent(QResizeEvent *e);
void closeEvent(QCloseEvent *e);
private:
PreLaunchLog _log;
};

View File

@ -0,0 +1,576 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "core/crash_reports.h"
#include "platform/platform_specific.h"
#include <signal.h>
#include <new>
#include <mutex>
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
// see https://blog.inventic.eu/2012/08/qt-and-google-breakpad/
#ifdef Q_OS_WIN
#pragma warning(push)
#pragma warning(disable:4091)
#include "client/windows/handler/exception_handler.h"
#pragma warning(pop)
#elif defined Q_OS_MAC // Q_OS_WIN
#include <execinfo.h>
#include <signal.h>
#include <sys/syscall.h>
#include <dlfcn.h>
#include <unistd.h>
#ifdef MAC_USE_BREAKPAD
#include "client/mac/handler/exception_handler.h"
#else // MAC_USE_BREAKPAD
#include "client/crashpad_client.h"
#endif // else for MAC_USE_BREAKPAD
#elif defined Q_OS_LINUX64 || defined Q_OS_LINUX32 // Q_OS_MAC
#include <execinfo.h>
#include <signal.h>
#include <sys/syscall.h>
#include "client/linux/handler/exception_handler.h"
#endif // Q_OS_LINUX64 || Q_OS_LINUX32
#endif // !TDESKTOP_DISABLE_CRASH_REPORTS
namespace CrashReports {
namespace {
using Annotations = std::map<std::string, std::string>;
using AnnotationRefs = std::map<std::string, const QString*>;
Annotations ProcessAnnotations;
AnnotationRefs ProcessAnnotationRefs;
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
QString ReportPath;
FILE *ReportFile = nullptr;
int ReportFileNo = 0;
char LaunchedDateTimeStr[32] = { 0 };
char LaunchedBinaryName[256] = { 0 };
void SafeWriteChar(char ch) {
fwrite(&ch, 1, 1, ReportFile);
}
template <bool Unsigned, typename Type>
struct writeNumberSignAndRemoveIt {
static void call(Type &number) {
if (number < 0) {
SafeWriteChar('-');
number = -number;
}
}
};
template <typename Type>
struct writeNumberSignAndRemoveIt<true, Type> {
static void call(Type &number) {
}
};
template <typename Type>
const dump &SafeWriteNumber(const dump &stream, Type number) {
if (!ReportFile) return stream;
writeNumberSignAndRemoveIt<(Type(-1) > Type(0)), Type>::call(number);
Type upper = 1, prev = number / 10;
while (prev >= upper) {
upper *= 10;
}
while (upper > 0) {
int digit = (number / upper);
SafeWriteChar('0' + digit);
number -= digit * upper;
upper /= 10;
}
return stream;
}
using ReservedMemoryChunk = std::array<gsl::byte, 1024 * 1024>;
std::unique_ptr<ReservedMemoryChunk> ReservedMemory;
void InstallOperatorNewHandler() {
ReservedMemory = std::make_unique<ReservedMemoryChunk>();
std::set_new_handler([] {
std::set_new_handler(nullptr);
ReservedMemory.reset();
Unexpected("Could not allocate!");
});
}
Qt::HANDLE ReportingThreadId = nullptr;
bool ReportingHeaderWritten = false;
QMutex ReportingMutex;
const char *BreakpadDumpPath = nullptr;
const wchar_t *BreakpadDumpPathW = nullptr;
#if defined Q_OS_MAC || defined Q_OS_LINUX32 || defined Q_OS_LINUX64
struct sigaction SIG_def[32];
void SignalHandler(int signum, siginfo_t *info, void *ucontext) {
if (signum > 0) {
sigaction(signum, &SIG_def[signum], 0);
}
#else // Q_OS_MAC || Q_OS_LINUX32 || Q_OS_LINUX64
void SignalHandler(int signum) {
#endif // else for Q_OS_MAC || Q_OS_LINUX || Q_OS_LINUX64
const char* name = 0;
switch (signum) {
case SIGABRT: name = "SIGABRT"; break;
case SIGSEGV: name = "SIGSEGV"; break;
case SIGILL: name = "SIGILL"; break;
case SIGFPE: name = "SIGFPE"; break;
#ifndef Q_OS_WIN
case SIGBUS: name = "SIGBUS"; break;
case SIGSYS: name = "SIGSYS"; break;
#endif // !Q_OS_WIN
}
Qt::HANDLE thread = QThread::currentThreadId();
if (thread == ReportingThreadId) return;
QMutexLocker lock(&ReportingMutex);
ReportingThreadId = thread;
if (!ReportingHeaderWritten) {
ReportingHeaderWritten = true;
auto dec2hex = [](int value) -> char {
if (value >= 0 && value < 10) {
return '0' + value;
} else if (value >= 10 && value < 16) {
return 'a' + (value - 10);
}
return '#';
};
for (const auto &i : ProcessAnnotationRefs) {
QByteArray utf8 = i.second->toUtf8();
std::string wrapped;
wrapped.reserve(4 * utf8.size());
for (auto ch : utf8) {
auto uch = static_cast<uchar>(ch);
wrapped.append("\\x", 2).append(1, dec2hex(uch >> 4)).append(1, dec2hex(uch & 0x0F));
}
ProcessAnnotations[i.first] = wrapped;
}
const Annotations c_ProcessAnnotations(ProcessAnnotations);
for (const auto &i : c_ProcessAnnotations) {
dump() << i.first.c_str() << ": " << i.second.c_str() << "\n";
}
psWriteDump();
dump() << "\n";
}
if (name) {
dump() << "Caught signal " << signum << " (" << name << ") in thread " << uint64(thread) << "\n";
} else if (signum == -1) {
dump() << "Google Breakpad caught a crash, minidump written in thread " << uint64(thread) << "\n";
if (BreakpadDumpPath) {
dump() << "Minidump: " << BreakpadDumpPath << "\n";
} else if (BreakpadDumpPathW) {
dump() << "Minidump: " << BreakpadDumpPathW << "\n";
}
} else {
dump() << "Caught signal " << signum << " in thread " << uint64(thread) << "\n";
}
// see https://github.com/benbjohnson/bandicoot
#if defined Q_OS_MAC || defined Q_OS_LINUX32 || defined Q_OS_LINUX64
ucontext_t *uc = (ucontext_t*)ucontext;
void *caller = 0;
if (uc) {
#if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_6)
/* OSX < 10.6 */
#if defined(__x86_64__)
caller = (void*)uc->uc_mcontext->__ss.__rip;
#elif defined(__i386__)
caller = (void*)uc->uc_mcontext->__ss.__eip;
#else
caller = (void*)uc->uc_mcontext->__ss.__srr0;
#endif
#elif defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_6)
/* OSX >= 10.6 */
#if defined(_STRUCT_X86_THREAD_STATE64) && !defined(__i386__)
caller = (void*)uc->uc_mcontext->__ss.__rip;
#else
caller = (void*)uc->uc_mcontext->__ss.__eip;
#endif
#elif defined(__linux__)
/* Linux */
#if defined(__i386__)
caller = (void*)uc->uc_mcontext.gregs[14]; /* Linux 32 */
#elif defined(__X86_64__) || defined(__x86_64__)
caller = (void*)uc->uc_mcontext.gregs[16]; /* Linux 64 */
#elif defined(__ia64__) /* Linux IA64 */
caller = (void*)uc->uc_mcontext.sc_ip;
#endif
#endif
}
void *addresses[132] = { 0 };
size_t size = backtrace(addresses, 128);
/* overwrite sigaction with caller's address */
if (caller) {
for (int i = size; i > 1; --i) {
addresses[i + 3] = addresses[i];
}
addresses[2] = (void*)0x1;
addresses[3] = caller;
addresses[4] = (void*)0x1;
}
#ifdef Q_OS_MAC
dump() << "\nBase image addresses:\n";
for (size_t i = 0; i < size; ++i) {
Dl_info info;
dump() << i << " ";
if (dladdr(addresses[i], &info)) {
dump() << uint64(info.dli_fbase) << " (" << info.dli_fname << ")\n";
} else {
dump() << "_unknown_module_\n";
}
}
#endif // Q_OS_MAC
dump() << "\nBacktrace:\n";
backtrace_symbols_fd(addresses, size, ReportFileNo);
#else // Q_OS_MAC || Q_OS_LINUX32 || Q_OS_LINUX64
dump() << "\nBacktrace:\n";
psWriteStackTrace();
#endif // else for Q_OS_MAC || Q_OS_LINUX32 || Q_OS_LINUX64
dump() << "\n";
ReportingThreadId = nullptr;
}
bool SetSignalHandlers = true;
bool CrashLogged = false;
#if !defined Q_OS_MAC || defined MAC_USE_BREAKPAD
google_breakpad::ExceptionHandler* BreakpadExceptionHandler = 0;
#ifdef Q_OS_WIN
bool DumpCallback(const wchar_t* _dump_dir, const wchar_t* _minidump_id, void* context, EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion, bool success)
#elif defined Q_OS_MAC // Q_OS_WIN
bool DumpCallback(const char* _dump_dir, const char* _minidump_id, void *context, bool success)
#elif defined Q_OS_LINUX64 || defined Q_OS_LINUX32 // Q_OS_MAC
bool DumpCallback(const google_breakpad::MinidumpDescriptor &md, void *context, bool success)
#endif // Q_OS_LINUX64 || Q_OS_LINUX32
{
if (CrashLogged) return success;
CrashLogged = true;
#ifdef Q_OS_WIN
BreakpadDumpPathW = _minidump_id;
SignalHandler(-1);
#else // Q_OS_WIN
#ifdef Q_OS_MAC
BreakpadDumpPath = _minidump_id;
#else // Q_OS_MAC
BreakpadDumpPath = md.path();
#endif // else for Q_OS_MAC
SignalHandler(-1, 0, 0);
#endif // else for Q_OS_WIN
return success;
}
#endif // !Q_OS_MAC || MAC_USE_BREAKPAD
#endif // !TDESKTOP_DISABLE_CRASH_REPORTS
} // namespace
void StartCatching() {
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
ProcessAnnotations["Binary"] = cExeName().toUtf8().constData();
ProcessAnnotations["ApiId"] = QString::number(ApiId).toUtf8().constData();
ProcessAnnotations["Version"] = (cBetaVersion() ? qsl("%1 beta").arg(cBetaVersion()) : (cAlphaVersion() ? qsl("%1 alpha") : qsl("%1")).arg(AppVersion)).toUtf8().constData();
ProcessAnnotations["Launched"] = QDateTime::currentDateTime().toString("dd.MM.yyyy hh:mm:ss").toUtf8().constData();
ProcessAnnotations["Platform"] = cPlatformString().toUtf8().constData();
ProcessAnnotations["UserTag"] = QString::number(Sandbox::UserTag(), 16).toUtf8().constData();
QString dumpspath = cWorkingDir() + qsl("tdata/dumps");
QDir().mkpath(dumpspath);
#ifdef Q_OS_WIN
BreakpadExceptionHandler = new google_breakpad::ExceptionHandler(
dumpspath.toStdWString(),
google_breakpad::ExceptionHandler::FilterCallback(nullptr),
DumpCallback,
(void*)nullptr, // callback_context
google_breakpad::ExceptionHandler::HANDLER_ALL,
MINIDUMP_TYPE(MiniDumpNormal),
// MINIDUMP_TYPE(MiniDumpWithFullMemory | MiniDumpWithHandleData | MiniDumpWithThreadInfo | MiniDumpWithProcessThreadData | MiniDumpWithFullMemoryInfo | MiniDumpWithUnloadedModules | MiniDumpWithFullAuxiliaryState | MiniDumpIgnoreInaccessibleMemory | MiniDumpWithTokenInformation),
(const wchar_t*)nullptr, // pipe_name
(const google_breakpad::CustomClientInfo*)nullptr
);
#elif defined Q_OS_MAC // Q_OS_WIN
#ifdef MAC_USE_BREAKPAD
#ifndef _DEBUG
BreakpadExceptionHandler = new google_breakpad::ExceptionHandler(
QFile::encodeName(dumpspath).toStdString(),
/*FilterCallback*/ 0,
DumpCallback,
/*context*/ 0,
true,
0
);
#endif // !_DEBUG
SetSignalHandlers = false;
#else // MAC_USE_BREAKPAD
crashpad::CrashpadClient crashpad_client;
std::string handler = (cExeDir() + cExeName() + qsl("/Contents/Helpers/crashpad_handler")).toUtf8().constData();
std::string database = QFile::encodeName(dumpspath).constData();
if (crashpad_client.StartHandler(base::FilePath(handler),
base::FilePath(database),
std::string(),
ProcessAnnotations,
std::vector<std::string>(),
false)) {
crashpad_client.UseHandler();
}
#endif // else for MAC_USE_BREAKPAD
#elif defined Q_OS_LINUX64 || defined Q_OS_LINUX32
BreakpadExceptionHandler = new google_breakpad::ExceptionHandler(
google_breakpad::MinidumpDescriptor(QFile::encodeName(dumpspath).toStdString()),
/*FilterCallback*/ 0,
DumpCallback,
/*context*/ 0,
true,
-1
);
#endif // Q_OS_LINUX64 || Q_OS_LINUX32
#endif // !TDESKTOP_DISABLE_CRASH_REPORTS
}
void FinishCatching() {
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
#if !defined Q_OS_MAC || defined MAC_USE_BREAKPAD
delete base::take(BreakpadExceptionHandler);
#endif // !Q_OS_MAC || MAC_USE_BREAKPAD
#endif // !TDESKTOP_DISABLE_CRASH_REPORTS
}
Status Start() {
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
ReportPath = cWorkingDir() + qsl("tdata/working");
#ifdef Q_OS_WIN
FILE *f = nullptr;
if (_wfopen_s(&f, ReportPath.toStdWString().c_str(), L"rb") != 0) {
f = nullptr;
} else {
#else // !Q_OS_WIN
if (FILE *f = fopen(QFile::encodeName(ReportPath).constData(), "rb")) {
#endif // else for !Q_OS_WIN
QByteArray lastdump;
char buffer[256 * 1024] = { 0 };
int32 read = fread(buffer, 1, 256 * 1024, f);
if (read > 0) {
lastdump.append(buffer, read);
}
fclose(f);
Sandbox::SetLastCrashDump(lastdump);
LOG(("Opened '%1' for reading, the previous Telegram Desktop launch was not finished properly :( Crash log size: %2").arg(ReportPath).arg(lastdump.size()));
return LastCrashed;
}
#endif // !TDESKTOP_DISABLE_CRASH_REPORTS
return Restart();
}
Status Restart() {
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
if (ReportFile) {
return Started;
}
#ifdef Q_OS_WIN
if (_wfopen_s(&ReportFile, ReportPath.toStdWString().c_str(), L"wb") != 0) {
ReportFile = nullptr;
}
#else // Q_OS_WIN
ReportFile = fopen(QFile::encodeName(ReportPath).constData(), "wb");
#endif // else for Q_OS_WIN
if (ReportFile) {
#ifdef Q_OS_WIN
ReportFileNo = _fileno(ReportFile);
#else // Q_OS_WIN
ReportFileNo = fileno(ReportFile);
#endif // else for Q_OS_WIN
if (SetSignalHandlers) {
#ifndef Q_OS_WIN
struct sigaction sigact;
sigact.sa_sigaction = SignalHandler;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
sigaction(SIGABRT, &sigact, &SIG_def[SIGABRT]);
sigaction(SIGSEGV, &sigact, &SIG_def[SIGSEGV]);
sigaction(SIGILL, &sigact, &SIG_def[SIGILL]);
sigaction(SIGFPE, &sigact, &SIG_def[SIGFPE]);
sigaction(SIGBUS, &sigact, &SIG_def[SIGBUS]);
sigaction(SIGSYS, &sigact, &SIG_def[SIGSYS]);
#else // !Q_OS_WIN
signal(SIGABRT, SignalHandler);
signal(SIGSEGV, SignalHandler);
signal(SIGILL, SignalHandler);
signal(SIGFPE, SignalHandler);
#endif // else for !Q_OS_WIN
}
InstallOperatorNewHandler();
return Started;
}
LOG(("FATAL: Could not open '%1' for writing!").arg(ReportPath));
return CantOpen;
#else // !TDESKTOP_DISABLE_CRASH_REPORTS
return Started;
#endif // else for !TDESKTOP_DISABLE_CRASH_REPORTS
}
void Finish() {
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
FinishCatching();
if (ReportFile) {
fclose(ReportFile);
ReportFile = nullptr;
#ifdef Q_OS_WIN
_wunlink(ReportPath.toStdWString().c_str());
#else // Q_OS_WIN
unlink(ReportPath.toUtf8().constData());
#endif // else for Q_OS_WIN
}
#endif // !TDESKTOP_DISABLE_CRASH_REPORTS
}
void SetAnnotation(const std::string &key, const QString &value) {
static QMutex mutex;
QMutexLocker lock(&mutex);
if (!value.trimmed().isEmpty()) {
ProcessAnnotations[key] = value.toUtf8().constData();
} else {
ProcessAnnotations.erase(key);
}
}
void SetAnnotationRef(const std::string &key, const QString *valuePtr) {
if (valuePtr) {
ProcessAnnotationRefs[key] = valuePtr;
} else {
ProcessAnnotationRefs.erase(key);
}
}
dump::~dump() {
if (ReportFile) {
fflush(ReportFile);
}
}
const dump &operator<<(const dump &stream, const char *str) {
if (!ReportFile) return stream;
fwrite(str, 1, strlen(str), ReportFile);
return stream;
}
const dump &operator<<(const dump &stream, const wchar_t *str) {
if (!ReportFile) return stream;
for (int i = 0, l = wcslen(str); i < l; ++i) {
if (str[i] >= 0 && str[i] < 128) {
SafeWriteChar(char(str[i]));
} else {
SafeWriteChar('?');
}
}
return stream;
}
const dump &operator<<(const dump &stream, int num) {
return SafeWriteNumber(stream, num);
}
const dump &operator<<(const dump &stream, unsigned int num) {
return SafeWriteNumber(stream, num);
}
const dump &operator<<(const dump &stream, unsigned long num) {
return SafeWriteNumber(stream, num);
}
const dump &operator<<(const dump &stream, unsigned long long num) {
return SafeWriteNumber(stream, num);
}
const dump &operator<<(const dump &stream, double num) {
if (num < 0) {
SafeWriteChar('-');
num = -num;
}
SafeWriteNumber(stream, uint64(floor(num)));
SafeWriteChar('.');
num -= floor(num);
for (int i = 0; i < 4; ++i) {
num *= 10;
int digit = int(floor(num));
SafeWriteChar('0' + digit);
num -= digit;
}
return stream;
}
} // namespace CrashReports

View File

@ -0,0 +1,81 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
namespace CrashReports {
struct dump {
~dump();
};
const dump &operator<<(const dump &stream, const char *str);
const dump &operator<<(const dump &stream, const wchar_t *str);
const dump &operator<<(const dump &stream, int num);
const dump &operator<<(const dump &stream, unsigned int num);
const dump &operator<<(const dump &stream, unsigned long num);
const dump &operator<<(const dump &stream, unsigned long long num);
const dump &operator<<(const dump &stream, double num);
enum Status {
CantOpen,
LastCrashed,
Started
};
Status Start();
Status Restart(); // can be only CantOpen or Started
void Finish();
void SetAnnotation(const std::string &key, const QString &value);
inline void ClearAnnotation(const std::string &key) {
SetAnnotation(key, QString());
}
// Remembers value pointer and tries to add the value to the crash report.
// Attention! You should call clearCrashAnnotationRef(key) before destroying value.
void SetAnnotationRef(const std::string &key, const QString *valuePtr);
inline void ClearAnnotationRef(const std::string &key) {
SetAnnotationRef(key, nullptr);
}
void StartCatching();
void FinishCatching();
} // namespace CrashReports
namespace base {
namespace assertion {
inline void log(const char *message, const char *file, int line) {
const auto info = QStringLiteral("%1 %2:%3"
).arg(message
).arg(file
).arg(line
);
const auto entry = QStringLiteral("Assertion Failed! ") + info;
#ifdef LOG
LOG((entry));
#endif // LOG
CrashReports::SetAnnotation("Assertion", info);
}
} // namespace assertion
} // namespace base

View File

@ -0,0 +1,106 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "core/launcher.h"
#include "platform/platform_launcher.h"
#include "platform/platform_specific.h"
#include "core/crash_reports.h"
#include "application.h"
namespace Core {
namespace {
QStringList ReadArguments(int argc, char *argv[]) {
auto result = QStringList();
result.reserve(argc);
for (auto i = 0; i != argc; ++i) {
result.push_back(fromUtf8Safe(argv[i]));
}
return result;
}
} // namespace
std::unique_ptr<Launcher> Launcher::Create(int argc, char *argv[]) {
return std::make_unique<Platform::Launcher>(argc, argv);
}
Launcher::Launcher(int argc, char *argv[])
: _argc(argc)
, _argv(argv)
, _arguments(ReadArguments(argc, argv)) {
InitFromCommandLine(argc, argv);
}
void Launcher::init() {
QCoreApplication::setApplicationName(qsl("TelegramDesktop"));
#ifndef OS_MAC_OLD
QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling, true);
#endif // OS_MAC_OLD
initHook();
}
int Launcher::exec() {
init();
if (cLaunchMode() == LaunchModeFixPrevious) {
return psFixPrevious();
} else if (cLaunchMode() == LaunchModeCleanup) {
return psCleanup();
}
// both are finished in Application::closeApplication
Logs::start(this); // must be started before Platform is started
Platform::start(); // must be started before QApplication is created
auto result = 0;
{
Application app(this, _argc, _argv);
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 // !TDESKTOP_DISABLE_AUTOUPDATE
if (cRestarting()) {
DEBUG_LOG(("Application Info: executing Telegram, because of restart..."));
psExecTelegram();
}
CrashReports::Finish();
Platform::finish();
Logs::finish();
return result;
}
QString Launcher::argumentsString() const {
return _arguments.join(' ');
}
} // namespace Core

View File

@ -0,0 +1,45 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
namespace Core {
class Launcher {
public:
Launcher(int argc, char *argv[]);
static std::unique_ptr<Launcher> Create(int argc, char *argv[]);
int exec();
QString argumentsString() const;
private:
void init();
virtual void initHook() = 0;
int _argc;
char **_argv;
QStringList _arguments;
};
} // namespace Core

View File

@ -36,6 +36,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "apiwrap.h"
#include "window/themes/window_theme.h"
#include "observer_peer.h"
#include "chat_helpers/stickers.h"
#include "auth_session.h"
#include "window/notifications_manager.h"
#include "window/window_controller.h"
@ -2123,7 +2124,7 @@ void DialogsInner::saveRecentHashtags(const QString &text) {
recent = cRecentSearchHashtags();
}
found = true;
incrementRecentHashtag(recent, text.mid(i + 1, next - i - 1));
Stickers::IncrementRecentHashtag(recent, text.mid(i + 1, next - i - 1));
}
if (found) {
cSetRecentSearchHashtags(recent);

View File

@ -38,6 +38,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "storage/storage_facade.h"
#include "storage/storage_shared_media.h"
#include "data/data_channel_admins.h"
#include "core/crash_reports.h"
namespace {
@ -1499,7 +1500,7 @@ void History::addToSharedMedia(std::vector<MsgId> (&medias)[kSharedMediaTypeCoun
}
value.push_back(indices.join(","));
}
SignalHandlers::setCrashAnnotation("full", value.join(";"));
CrashReports::SetAnnotation("full", value.join(";"));
Assert(!"History desync caught!");
//// Logging
@ -1631,11 +1632,11 @@ void History::addOlderSlice(const QVector<MTPMessage> &slice) {
logged.push_back(QString::number(minAdded));
logged.push_back(QString::number(maxAdded));
SignalHandlers::setCrashAnnotation("old_minmaxwas_minmaxadd", logged.join(";"));
CrashReports::SetAnnotation("old_minmaxwas_minmaxadd", logged.join(";"));
addBlockToSharedMedia(block);
SignalHandlers::setCrashAnnotation("old_minmaxwas_minmaxadd", "");
CrashReports::ClearAnnotation("old_minmaxwas_minmaxadd");
if (isChannel()) {
asChannelHistory()->checkJoinedMessage();
@ -1693,7 +1694,7 @@ void History::addNewerSlice(const QVector<MTPMessage> &slice) {
}
logged.push_back(QString::number(minAdded));
logged.push_back(QString::number(maxAdded));
SignalHandlers::setCrashAnnotation("new_minmaxwas_minmaxadd", logged.join(";"));
CrashReports::SetAnnotation("new_minmaxwas_minmaxadd", logged.join(";"));
if (!atLeastOneAdded) {
newLoaded = true;
@ -1701,7 +1702,7 @@ void History::addNewerSlice(const QVector<MTPMessage> &slice) {
}
addToSharedMedia(medias, wasLoadedAtBottom != loadedAtBottom());
SignalHandlers::setCrashAnnotation("new_minmaxwas_minmaxadd", "");
CrashReports::ClearAnnotation("new_minmaxwas_minmaxadd");
}
if (!wasLoadedAtBottom) {

View File

@ -79,6 +79,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "window/window_peer_menu.h"
#include "inline_bots/inline_results_widget.h"
#include "chat_helpers/emoji_suggestions_widget.h"
#include "core/crash_reports.h"
namespace {
@ -2292,7 +2293,7 @@ void HistoryWidget::messagesReceived(PeerData *peer, const MTPmessages_Messages
if (_preloadRequest == requestId) {
auto to = toMigrated ? _migrated : _history;
if (cBetaVersion()) {
SignalHandlers::setCrashAnnotation("old_debugstr", QString(
CrashReports::SetAnnotation("old_debugstr", QString(
"%1_%2_%3_%4:%5_%6 (%7)"
).arg(PeerString(_debug_preloadDownPeer)
).arg(_debug_preloadOffsetId
@ -2307,7 +2308,7 @@ void HistoryWidget::messagesReceived(PeerData *peer, const MTPmessages_Messages
addMessagesToFront(peer, *histList);
if (cBetaVersion()) {
SignalHandlers::setCrashAnnotation("old_debugstr", QString());
CrashReports::ClearAnnotation("old_debugstr");
}
_preloadRequest = 0;
@ -2319,7 +2320,7 @@ void HistoryWidget::messagesReceived(PeerData *peer, const MTPmessages_Messages
} else if (_preloadDownRequest == requestId) {
auto to = toMigrated ? _migrated : _history;
if (cBetaVersion()) {
SignalHandlers::setCrashAnnotation("new_debugstr", QString(
CrashReports::SetAnnotation("new_debugstr", QString(
"%1_%2_%3_%4:%5_%6 (%7)"
).arg(PeerString(_debug_preloadDownPeer)
).arg(_debug_preloadDownOffsetId
@ -2334,7 +2335,7 @@ void HistoryWidget::messagesReceived(PeerData *peer, const MTPmessages_Messages
addMessagesToBack(peer, *histList);
if (cBetaVersion()) {
SignalHandlers::setCrashAnnotation("new_debugstr", QString());
CrashReports::ClearAnnotation("new_debugstr");
}
_preloadDownRequest = 0;

File diff suppressed because it is too large Load Diff

View File

@ -20,60 +20,61 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
class MTPlong;
namespace Core {
class Launcher;
} // namespace Core
namespace Logs {
void start();
bool started();
void finish();
void start(not_null<Core::Launcher*> launcher);
bool started();
void finish();
bool instanceChecked();
void multipleInstances();
bool instanceChecked();
void multipleInstances();
void closeMain();
void closeMain();
void writeMain(const QString &v);
void writeMain(const QString &v);
void writeDebug(const char *file, int32 line, const QString &v);
void writeTcp(const QString &v);
void writeMtp(int32 dc, const QString &v);
void writeDebug(const char *file, int32 line, const QString &v);
void writeTcp(const QString &v);
void writeMtp(int32 dc, const QString &v);
QString full();
inline const char *b(bool v) {
return v ? "[TRUE]" : "[FALSE]";
}
struct MemoryBuffer {
MemoryBuffer(const void *ptr, uint32 size) : p(ptr), s(size) {
}
QString str() const {
QString result;
const uchar *buf((const uchar*)p);
const char *hex = "0123456789ABCDEF";
result.reserve(s * 3);
for (uint32 i = 0; i < s; ++i) {
result += hex[(buf[i] >> 4)];
result += hex[buf[i] & 0x0F];
result += ' ';
}
result.chop(1);
return result;
}
const void *p;
uint32 s;
};
inline MemoryBuffer mb(const void *ptr, uint32 size) {
return MemoryBuffer(ptr, size);
}
QString vector(const QVector<MTPlong> &ids);
QString vector(const QVector<uint64> &ids);
QString full();
inline const char *b(bool v) {
return v ? "[TRUE]" : "[FALSE]";
}
struct MemoryBuffer {
MemoryBuffer(const void *ptr, uint32 size) : p(ptr), s(size) {
}
QString str() const {
QString result;
const uchar *buf((const uchar*)p);
const char *hex = "0123456789ABCDEF";
result.reserve(s * 3);
for (uint32 i = 0; i < s; ++i) {
result += hex[(buf[i] >> 4)];
result += hex[buf[i] & 0x0F];
result += ' ';
}
result.chop(1);
return result;
}
const void *p;
uint32 s;
};
inline MemoryBuffer mb(const void *ptr, uint32 size) {
return MemoryBuffer(ptr, size);
}
} // namespace Logs
#define LOG(msg) (Logs::writeMain(QString msg))
//usage LOG(("log: %1 %2").arg(1).arg(2))
@ -85,47 +86,3 @@ namespace Logs {
#define MTP_LOG(dc, msg) { if (cDebug() || !Logs::started()) Logs::writeMtp(dc, QString msg); }
//usage MTP_LOG(dc, ("log: %1 %2").arg(1).arg(2))
namespace SignalHandlers {
struct dump {
~dump();
};
const dump &operator<<(const dump &stream, const char *str);
const dump &operator<<(const dump &stream, const wchar_t *str);
const dump &operator<<(const dump &stream, int num);
const dump &operator<<(const dump &stream, unsigned int num);
const dump &operator<<(const dump &stream, unsigned long num);
const dump &operator<<(const dump &stream, unsigned long long num);
const dump &operator<<(const dump &stream, double num);
enum Status {
CantOpen,
LastCrashed,
Started
};
Status start();
Status restart(); // can be only CantOpen or Started
void finish();
void setCrashAnnotation(const std::string &key, const QString &value);
// Remembers value pointer and tries to add the value to the crash report.
// Attention! You should call clearCrashAnnotationRef(key) before destroying value.
void setCrashAnnotationRef(const std::string &key, const QString *valuePtr);
inline void clearCrashAnnotationRef(const std::string &key) {
setCrashAnnotationRef(key, nullptr);
}
}
namespace base {
namespace assertion {
inline void log(const char *message, const char *file, int line) {
auto info = QStringLiteral("%1 %2:%3").arg(message).arg(file).arg(line);
LOG(("Assertion Failed! ") + info);
SignalHandlers::setCrashAnnotation("Assertion", info);
}
} // namespace assertion
} // namespace base

View File

@ -18,49 +18,9 @@ to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "application.h"
#include "platform/platform_specific.h"
#include "storage/localstorage.h"
#include "core/launcher.h"
int main(int argc, char *argv[]) {
#ifndef Q_OS_MAC // Retina display support is working fine, others are not.
QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling, true);
#endif // Q_OS_MAC
QCoreApplication::setApplicationName(qsl("TelegramDesktop"));
InitFromCommandLine(argc, argv);
if (cLaunchMode() == LaunchModeFixPrevious) {
return psFixPrevious();
} else if (cLaunchMode() == LaunchModeCleanup) {
return psCleanup();
}
// both are finished in Application::closeApplication
Logs::start(); // must be started before Platform is started
Platform::start(); // must be started before QApplication is created
int result = 0;
{
Application app(argc, argv);
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 // !TDESKTOP_DISABLE_AUTOUPDATE
if (cRestarting()) {
DEBUG_LOG(("Application Info: executing Telegram, because of restart..."));
psExecTelegram();
}
SignalHandlers::finish();
Platform::finish();
Logs::finish();
return result;
const auto launcher = Core::Launcher::Create(argc, argv);
return launcher ? launcher->exec() : 1;
}

View File

@ -1574,7 +1574,7 @@ void MainWidget::saveRecentHashtags(const QString &text) {
recent = cRecentWriteHashtags();
}
found = true;
incrementRecentHashtag(recent, text.mid(i + 1, next - i - 1));
Stickers::IncrementRecentHashtag(recent, text.mid(i + 1, next - i - 1));
}
if (found) {
cSetRecentWriteHashtags(recent);
@ -4389,7 +4389,7 @@ void MainWidget::incrementSticker(DocumentData *sticker) {
// Remove that sticker from old recent, now it is in cloud recent stickers.
bool writeOldRecent = false;
auto &recent = cGetRecentStickers();
auto &recent = Stickers::GetRecentPack();
for (auto i = recent.begin(), e = recent.end(); i != e; ++i) {
if (i->first == sticker) {
writeOldRecent = true;

File diff suppressed because it is too large Load Diff

View File

@ -224,219 +224,3 @@ private:
Local::ClearManager *_clearManager = nullptr;
};
class PreLaunchWindow : public TWidget {
public:
PreLaunchWindow(QString title = QString());
void activate();
int basicSize() const {
return _size;
}
~PreLaunchWindow();
static PreLaunchWindow *instance();
protected:
int _size;
};
class PreLaunchLabel : public QLabel {
public:
PreLaunchLabel(QWidget *parent);
void setText(const QString &text);
};
class PreLaunchInput : public QLineEdit {
public:
PreLaunchInput(QWidget *parent, bool password = false);
};
class PreLaunchLog : public QTextEdit {
public:
PreLaunchLog(QWidget *parent);
};
class PreLaunchButton : public QPushButton {
public:
PreLaunchButton(QWidget *parent, bool confirm = true);
void setText(const QString &text);
};
class PreLaunchCheckbox : public QCheckBox {
public:
PreLaunchCheckbox(QWidget *parent);
void setText(const QString &text);
};
class NotStartedWindow : public PreLaunchWindow {
public:
NotStartedWindow();
protected:
void closeEvent(QCloseEvent *e);
void resizeEvent(QResizeEvent *e);
private:
void updateControls();
PreLaunchLabel _label;
PreLaunchLog _log;
PreLaunchButton _close;
};
class LastCrashedWindow : public PreLaunchWindow {
Q_OBJECT
public:
LastCrashedWindow();
public slots:
void onViewReport();
void onSaveReport();
void onSendReport();
void onGetApp();
void onNetworkSettings();
void onNetworkSettingsSaved(QString host, quint32 port, QString username, QString password);
void onContinue();
void onCheckingFinished();
void onSendingError(QNetworkReply::NetworkError e);
void onSendingFinished();
void onSendingProgress(qint64 uploaded, qint64 total);
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
void onUpdateRetry();
void onUpdateSkip();
void onUpdateChecking();
void onUpdateLatest();
void onUpdateDownloading(qint64 ready, qint64 total);
void onUpdateReady();
void onUpdateFailed();
#endif // !TDESKTOP_DISABLE_AUTOUPDATE
protected:
void closeEvent(QCloseEvent *e);
void resizeEvent(QResizeEvent *e);
private:
QString minidumpFileName();
void updateControls();
QString _host, _username, _password;
quint32 _port;
PreLaunchLabel _label, _pleaseSendReport, _yourReportName, _minidump;
PreLaunchLog _report;
PreLaunchButton _send, _sendSkip, _networkSettings, _continue, _showReport, _saveReport, _getApp;
PreLaunchCheckbox _includeUsername;
QString _minidumpName, _minidumpFull, _reportText;
QString _reportUsername, _reportTextNoUsername;
QByteArray getCrashReportRaw() const;
bool _reportShown, _reportSaved;
void excludeReportUsername();
enum SendingState {
SendingNoReport,
SendingUpdateCheck,
SendingNone,
SendingTooOld,
SendingTooMany,
SendingUnofficial,
SendingProgress,
SendingUploading,
SendingFail,
SendingDone,
};
SendingState _sendingState;
PreLaunchLabel _updating;
qint64 _sendingProgress, _sendingTotal;
QNetworkAccessManager _sendManager;
QNetworkReply *_checkReply, *_sendReply;
#ifndef TDESKTOP_DISABLE_AUTOUPDATE
PreLaunchButton _updatingCheck, _updatingSkip;
enum UpdatingState {
UpdatingNone,
UpdatingCheck,
UpdatingLatest,
UpdatingDownload,
UpdatingFail,
UpdatingReady
};
UpdatingState _updatingState;
QString _newVersionDownload;
void setUpdatingState(UpdatingState state, bool force = false);
void setDownloadProgress(qint64 ready, qint64 total);
#endif // !TDESKTOP_DISABLE_AUTOUPDATE
QString getReportField(const QLatin1String &name, const QLatin1String &prefix);
void addReportFieldPart(const QLatin1String &name, const QLatin1String &prefix, QHttpMultiPart *multipart);
};
class NetworkSettingsWindow : public PreLaunchWindow {
Q_OBJECT
public:
NetworkSettingsWindow(QWidget *parent, QString host, quint32 port, QString username, QString password);
signals:
void saved(QString host, quint32 port, QString username, QString password);
public slots:
void onSave();
protected:
void closeEvent(QCloseEvent *e);
void resizeEvent(QResizeEvent *e);
private:
void updateControls();
PreLaunchLabel _hostLabel, _portLabel, _usernameLabel, _passwordLabel;
PreLaunchInput _hostInput, _portInput, _usernameInput, _passwordInput;
PreLaunchButton _save, _cancel;
QWidget *_parent;
};
class ShowCrashReportWindow : public PreLaunchWindow {
public:
ShowCrashReportWindow(const QString &text);
protected:
void resizeEvent(QResizeEvent *e);
void closeEvent(QCloseEvent *e);
private:
PreLaunchLog _log;
};

View File

@ -20,6 +20,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "media/media_audio_ffmpeg_loader.h"
#include "core/crash_reports.h"
namespace {
constexpr AVSampleFormat AudioToFormat = AV_SAMPLE_FMT_S16;
@ -423,7 +425,7 @@ AudioPlayerLoader::ReadResult FFMpegLoader::readFromReadyFrame(QByteArray &resul
).arg(ptrdiff_t(frame->extended_data[0])
).arg(ptrdiff_t(frame->data[1])
);
SignalHandlers::setCrashAnnotation(key, value);
CrashReports::SetAnnotation(key, value);
}
}
@ -435,7 +437,7 @@ AudioPlayerLoader::ReadResult FFMpegLoader::readFromReadyFrame(QByteArray &resul
if (frame->extended_data[1] == nullptr) {
const auto key = "ffmpeg_" + std::to_string(ptrdiff_t(this));
SignalHandlers::setCrashAnnotation(key, QString());
CrashReports::ClearAnnotation(key);
}
int32 resultLen = av_samples_get_buffer_size(0, AudioToChannels, res, AudioToFormat, 1);

View File

@ -75,7 +75,9 @@ struct Messenger::Private {
base::Timer quitTimer;
};
Messenger::Messenger() : QObject()
Messenger::Messenger(not_null<Core::Launcher*> launcher)
: QObject()
, _launcher(launcher)
, _private(std::make_unique<Private>())
, _langpack(std::make_unique<Lang::Instance>())
, _audio(std::make_unique<Media::Audio::Instance>())

View File

@ -24,6 +24,17 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "mtproto/auth_key.h"
#include "base/timer.h"
class AuthSession;
class AuthSessionData;
class MainWidget;
class FileUploader;
class Translator;
class MediaView;
namespace Core {
class Launcher;
} // namespace Core
namespace App {
void quit();
} // namespace App
@ -36,13 +47,6 @@ using AuthKeyPtr = std::shared_ptr<AuthKey>;
using AuthKeysList = std::vector<AuthKeyPtr>;
} // namespace MTP
class AuthSession;
class AuthSessionData;
class MainWidget;
class FileUploader;
class Translator;
class MediaView;
namespace Media {
namespace Audio {
class Instance;
@ -59,13 +63,17 @@ class Messenger final : public QObject, public RPCSender, private base::Subscrib
Q_OBJECT
public:
Messenger();
Messenger(not_null<Core::Launcher*> launcher);
Messenger(const Messenger &other) = delete;
Messenger &operator=(const Messenger &other) = delete;
~Messenger();
not_null<Core::Launcher*> launcher() const {
return _launcher;
}
// Windows interface.
MainWindow *getActiveWindow() const;
bool closeActiveWindow();
@ -220,6 +228,8 @@ private:
void loggedOut();
not_null<Core::Launcher*> _launcher;
QMap<FullMsgId, PeerId> photoUpdates;
QMap<MTP::DcId, TimeMs> killDownloadSessionTimes;

View File

@ -45,6 +45,15 @@ constexpr auto kMaxModExpSize = 256;
// Don't try to handle messages larger than this size.
constexpr auto kMaxMessageLength = 16 * 1024 * 1024;
QString LogIdsVector(const QVector<MTPlong> &ids) {
if (!ids.size()) return "[]";
auto idsStr = QString("[%1").arg(ids.cbegin()->v);
for (const auto &id : ids) {
idsStr += QString(", %2").arg(id.v);
}
return idsStr + "]";
}
bool IsGoodModExpFirst(const openssl::BigNum &modexp, const openssl::BigNum &prime) {
auto diff = prime - modexp;
if (modexp.failed() || prime.failed() || diff.failed()) {
@ -1432,7 +1441,7 @@ void ConnectionPrivate::handleReceived() {
// send acks
uint32 toAckSize = ackRequestData.size();
if (toAckSize) {
DEBUG_LOG(("MTP Info: will send %1 acks, ids: %2").arg(toAckSize).arg(Logs::vector(ackRequestData)));
DEBUG_LOG(("MTP Info: will send %1 acks, ids: %2").arg(toAckSize).arg(LogIdsVector(ackRequestData)));
emit sendAnythingAsync(MTPAckSendWaiting);
}
@ -1546,7 +1555,7 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr
auto &ids = msg.c_msgs_ack().vmsg_ids.v;
uint32 idsCount = ids.size();
DEBUG_LOG(("Message Info: acks received, ids: %1").arg(Logs::vector(ids)));
DEBUG_LOG(("Message Info: acks received, ids: %1").arg(LogIdsVector(ids)));
if (!idsCount) return (badTime ? HandleResult::Ignored : HandleResult::Success);
if (badTime) {
@ -1676,7 +1685,7 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr
msg.read(from, end);
auto &ids = msg.c_msgs_state_req().vmsg_ids.v;
auto idsCount = ids.size();
DEBUG_LOG(("Message Info: msgs_state_req received, ids: %1").arg(Logs::vector(ids)));
DEBUG_LOG(("Message Info: msgs_state_req received, ids: %1").arg(LogIdsVector(ids)));
if (!idsCount) return HandleResult::Success;
QByteArray info(idsCount, Qt::Uninitialized);
@ -1787,7 +1796,7 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr
QVector<MTPlong> toAck;
DEBUG_LOG(("Message Info: msgs all info received, msgId %1, reqMsgIds: %2, states %3").arg(msgId).arg(Logs::vector(ids)).arg(Logs::mb(states.data(), states.length()).str()));
DEBUG_LOG(("Message Info: msgs all info received, msgId %1, reqMsgIds: %2, states %3").arg(msgId).arg(LogIdsVector(ids)).arg(Logs::mb(states.data(), states.length()).str()));
handleMsgsStates(ids, states, toAck);
requestsAcked(toAck);
@ -1856,7 +1865,7 @@ ConnectionPrivate::HandleResult ConnectionPrivate::handleOneReceived(const mtpPr
auto &ids = msg.c_msg_resend_req().vmsg_ids.v;
auto idsCount = ids.size();
DEBUG_LOG(("Message Info: resend of msgs requested, ids: %1").arg(Logs::vector(ids)));
DEBUG_LOG(("Message Info: resend of msgs requested, ids: %1").arg(LogIdsVector(ids)));
if (!idsCount) return (badTime ? HandleResult::Ignored : HandleResult::Success);
QVector<quint64> toResend(ids.size());
@ -2087,7 +2096,7 @@ bool ConnectionPrivate::requestsFixTimeSalt(const QVector<MTPlong> &ids, int32 s
void ConnectionPrivate::requestsAcked(const QVector<MTPlong> &ids, bool byResponse) {
uint32 idsCount = ids.size();
DEBUG_LOG(("Message Info: requests acked, ids %1").arg(Logs::vector(ids)));
DEBUG_LOG(("Message Info: requests acked, ids %1").arg(LogIdsVector(ids)));
RPCCallbackClears clearedAcked;
QVector<MTPlong> toAckMore;

View File

@ -246,7 +246,7 @@ mtpRequestId Session::send(const TRequest &request, RPCResponseHandler callbacks
sendPrepared(reqSerialized, msCanWait);
} catch (Exception &e) {
requestId = 0;
rpcErrorOccured(requestId, callbacks.onFail, rpcClientError("NO_REQUEST_ID", QString("send() failed to queue request, exception: %1").arg(e.what())));
requestPrepareFailed(callbacks.onFail, e);
}
if (requestId) registerRequest(requestId, toMainDC ? -getDcWithShift() : getDcWithShift());
return requestId;

View File

@ -23,9 +23,22 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "mtproto/connection.h"
#include "mtproto/dcenter.h"
#include "mtproto/auth_key.h"
#include "core/crash_reports.h"
namespace MTP {
namespace internal {
namespace {
QString LogIds(const QVector<uint64> &ids) {
if (!ids.size()) return "[]";
auto idsStr = QString("[%1").arg(*ids.cbegin());
for (const auto id : ids) {
idsStr += QString(", %2").arg(id);
}
return idsStr + "]";
}
} // namespace
void SessionData::setKey(const AuthKeyPtr &key) {
if (_authKey != key) {
@ -140,6 +153,23 @@ bool Session::rpcErrorOccured(mtpRequestId requestId, const RPCFailHandlerPtr &o
return _instance->rpcErrorOccured(requestId, onFail, err);
}
void Session::requestPrepareFailed(
const RPCFailHandlerPtr &onFail,
Exception &e) {
CrashReports::SetAnnotation("RequestException", QString::fromLatin1(e.what()));
Unexpected("Exception in Session::send()");
const auto requestId = 0;
const auto error = rpcClientError(
"NO_REQUEST_ID",
QString(
"send() failed to queue request, exception: %1"
).arg(
e.what()
));
rpcErrorOccured(requestId, onFail, error);
}
void Session::restart() {
if (_killed) {
DEBUG_LOG(("Session Error: can't restart a killed session"));
@ -271,7 +301,7 @@ void Session::checkRequestsByTimer() {
}
if (stateRequestIds.size()) {
DEBUG_LOG(("MTP Info: requesting state of msgs: %1").arg(Logs::vector(stateRequestIds)));
DEBUG_LOG(("MTP Info: requesting state of msgs: %1").arg(LogIds(stateRequestIds)));
{
QWriteLocker locker(data.stateRequestMutex());
for (uint32 i = 0, l = stateRequestIds.size(); i < l; ++i) {

View File

@ -356,6 +356,7 @@ private:
mtpRequestId storeRequest(mtpRequest &request, const RPCResponseHandler &parser);
mtpRequest getRequest(mtpRequestId requestId);
bool rpcErrorOccured(mtpRequestId requestId, const RPCFailHandlerPtr &onFail, const RPCError &err);
void requestPrepareFailed(const RPCFailHandlerPtr &onFail, Exception &e);
not_null<Instance*> _instance;
std::unique_ptr<Connection> _connection;

View File

@ -0,0 +1,28 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "platform/linux/launcher_linux.h"
namespace Platform {
void Launcher::initHook() {
}
} // namespace

View File

@ -0,0 +1,36 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "core/launcher.h"
namespace Platform {
class Launcher : public Core::Launcher {
public:
using Core::Launcher::Launcher;
private:
void initHook() override;
};
} // namespace Platform

View File

@ -25,6 +25,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "platform/linux/file_utilities_linux.h"
#include "platform/platform_notifications_manager.h"
#include "storage/localstorage.h"
#include "core/crash_reports.h"
#include <sys/stat.h>
#include <sys/types.h>
@ -598,7 +599,7 @@ bool _execUpdater(bool update = true, const QString &crashreport = QString()) {
}
Logs::closeMain();
SignalHandlers::finish();
CrashReports::Finish();
pid_t pid = fork();
switch (pid) {
case -1: return false;

View File

@ -0,0 +1,36 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "core/launcher.h"
namespace Platform {
class Launcher : public Core::Launcher {
public:
using Core::Launcher::Launcher;
private:
void initHook() override;
};
} // namespace Platform

View File

@ -0,0 +1,32 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "platform/mac/launcher_mac.h"
namespace Platform {
void Launcher::initHook() {
#ifndef OS_MAC_OLD
// macOS Retina display support is working fine, others are not.
QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling, false);
#endif // OS_MAC_OLD
}
} // namespace Platform

View File

@ -17,19 +17,18 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "platform/mac/specific_mac.h"
#include <cstdlib>
#include "lang/lang_keys.h"
#include "application.h"
#include "mainwidget.h"
#include "history/history_widget.h"
#include "core/crash_reports.h"
#include "storage/localstorage.h"
#include "passcodewidget.h"
#include "mainwindow.h"
#include "history/history_location_manager.h"
#include "platform/mac/mac_utilities.h"
#include <cstdlib>
#include <execinfo.h>
#include <Cocoa/Cocoa.h>
@ -92,7 +91,7 @@ QAbstractNativeEventFilter *psNativeEventFilter() {
void psWriteDump() {
double v = objc_appkitVersion();
SignalHandlers::dump() << "OS-Version: " << v;
CrashReports::dump() << "OS-Version: " << v;
}
QString demanglestr(const QString &mangled) {

View File

@ -27,6 +27,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "styles/style_window.h"
#include "lang/lang_keys.h"
#include "base/timer.h"
#include "core/crash_reports.h"
#include <Cocoa/Cocoa.h>
#include <CoreFoundation/CFURL.h>
@ -441,7 +442,7 @@ BOOL _execUpdater(BOOL update = YES, const QString &crashreport = QString()) {
DEBUG_LOG(("Application Info: executing %1 %2").arg(NS2QString(path)).arg(NS2QString([args componentsJoinedByString:@" "])));
Logs::closeMain();
SignalHandlers::finish();
CrashReports::Finish();
if (![NSTask launchedTaskWithLaunchPath:path arguments:args]) {
DEBUG_LOG(("Task not launched while executing %1 %2").arg(NS2QString(path)).arg(NS2QString([args componentsJoinedByString:@" "])));
return NO;

View File

@ -0,0 +1,43 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
namespace Platform {
//class Launcher : public Core::Launcher {
//public:
// using Core::Launcher::Launcher;
//
// ...
//
//};
} // namespace Platform
// Platform dependent implementations.
#ifdef Q_OS_MAC
#include "platform/mac/launcher_mac.h"
#elif defined Q_OS_LINUX // Q_OS_MAC
#include "platform/linux/launcher_linux.h"
#elif defined Q_OS_WINRT || defined Q_OS_WIN // Q_OS_MAC || Q_OS_LINUX
#include "platform/win/launcher_win.h"
#endif // Q_OS_MAC || Q_OS_LINUX || Q_OS_WINRT || Q_OS_WIN

View File

@ -0,0 +1,28 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "platform/win/launcher_win.h"
namespace Platform {
void Launcher::initHook() {
}
} // namespace

View File

@ -0,0 +1,36 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "core/launcher.h"
namespace Platform {
class Launcher : public Core::Launcher {
public:
using Core::Launcher::Launcher;
private:
void initHook() override;
};
} // namespace Platform

View File

@ -32,6 +32,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "storage/localstorage.h"
#include "passcodewidget.h"
#include "base/task_queue.h"
#include "core/crash_reports.h"
#include <Shobjidl.h>
#include <shellapi.h>
@ -687,7 +688,7 @@ void psExecTelegram(const QString &crashreport) {
DEBUG_LOG(("Application Info: executing %1 %2").arg(cExeDir() + cExeName()).arg(targs));
Logs::closeMain();
SignalHandlers::finish();
CrashReports::Finish();
HINSTANCE r = ShellExecute(0, 0, telegram.toStdWString().c_str(), targs.toStdWString().c_str(), wdir.isEmpty() ? 0 : wdir.toStdWString().c_str(), SW_SHOWNORMAL);
if (long(r) < 32) {
DEBUG_LOG(("Application Error: failed to execute %1, working directory: '%2', result: %3").arg(telegram).arg(wdir).arg(long(r)));
@ -1291,7 +1292,7 @@ QString psPrepareCrashDump(const QByteArray &crashdump, QString dumpfile) {
void psWriteStackTrace() {
#ifndef TDESKTOP_DISABLE_CRASH_REPORTS
if (!LoadDbgHelp()) {
SignalHandlers::dump() << "ERROR: Could not load dbghelp.dll!\n";
CrashReports::dump() << "ERROR: Could not load dbghelp.dll!\n";
return;
}
@ -1348,17 +1349,17 @@ void psWriteStackTrace() {
// deeper frame could not be found.
// CONTEXT need not to be suplied if imageTyp is IMAGE_FILE_MACHINE_I386!
if (!stackWalk64(imageType, hProcess, hThread, &s, &c, ReadProcessMemoryRoutine64, symFunctionTableAccess64, symGetModuleBase64, NULL)) {
SignalHandlers::dump() << "ERROR: Call to StackWalk64() failed!\n";
CrashReports::dump() << "ERROR: Call to StackWalk64() failed!\n";
return;
}
if (s.AddrPC.Offset == s.AddrReturn.Offset) {
SignalHandlers::dump() << s.AddrPC.Offset << "\n";
SignalHandlers::dump() << "ERROR: StackWalk64() endless callstack!";
CrashReports::dump() << s.AddrPC.Offset << "\n";
CrashReports::dump() << "ERROR: StackWalk64() endless callstack!";
return;
}
if (s.AddrPC.Offset != 0) { // we seem to have a valid PC
SignalHandlers::dump() << s.AddrPC.Offset << "\n";
CrashReports::dump() << s.AddrPC.Offset << "\n";
}
if (s.AddrReturn.Offset == 0) {

View File

@ -20,14 +20,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "settings.h"
#include "platform/platform_specific.h"
#include "data/data_document.h"
bool gRtl = false;
Qt::LayoutDirection gLangDir = gRtl ? Qt::RightToLeft : Qt::LeftToRight;
QString gArguments;
bool gAlphaVersion = AppAlphaVersion;
uint64 gBetaVersion = AppBetaVersion;
uint64 gRealBetaVersion = AppBetaVersion;
@ -168,7 +163,8 @@ void ParseCommandLineArguments(const QStringList &arguments) {
gKeyFile = parseResult.value("-key", QStringList()).join(QString());
gLaunchMode = parseResult.contains("-autostart") ? LaunchModeAutoStart
: parseResult.contains("-fixprevious") ? LaunchModeFixPrevious
: parseResult.contains("-cleanup") ? LaunchModeCleanup : LaunchModeNormal;
: parseResult.contains("-cleanup") ? LaunchModeCleanup
: LaunchModeNormal;
gNoStartUpdate = parseResult.contains("-noupdate");
gStartToSettings = parseResult.contains("-tosettings");
gStartInTray = parseResult.contains("-startintray");
@ -182,13 +178,11 @@ void ParseCommandLineArguments(const QStringList &arguments) {
void InitFromCommandLine(int argc, char *argv[]) {
Expects(argc >= 0);
auto arguments = QStringList();
arguments.reserve(argc);
for (auto i = 0; i != argc; ++i) {
arguments.push_back(fromUtf8Safe(argv[i]));
}
gArguments = arguments.join(' ');
#ifdef Q_OS_MAC
#ifndef OS_MAC_OLD
@ -252,20 +246,3 @@ void InitFromCommandLine(int argc, char *argv[]) {
ParseCommandLineArguments(arguments);
}
RecentStickerPack &cGetRecentStickers() {
if (cRecentStickers().isEmpty() && !cRecentStickersPreload().isEmpty()) {
RecentStickerPreload p(cRecentStickersPreload());
cSetRecentStickersPreload(RecentStickerPreload());
RecentStickerPack &recent(cRefRecentStickers());
recent.reserve(p.size());
for (RecentStickerPreload::const_iterator i = p.cbegin(), e = p.cend(); i != e; ++i) {
DocumentData *doc = App::document(i->first);
if (!doc || !doc->sticker()) continue;
recent.push_back(qMakePair(doc, i->second));
}
}
return cRefRecentStickers();
}

View File

@ -20,8 +20,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
void InitFromCommandLine(int argc, char *argv[]);
extern bool gDebug;
inline bool cDebug() {
#if defined _DEBUG
@ -55,8 +53,6 @@ inline bool rtl() {
return cRtl();
}
DeclareReadSetting(QString, Arguments);
DeclareSetting(bool, AlphaVersion);
DeclareSetting(uint64, BetaVersion);
DeclareSetting(uint64, RealBetaVersion);
@ -169,15 +165,13 @@ DeclareRefSetting(EmojiColorVariants, EmojiVariants);
class DocumentData;
typedef QList<QPair<DocumentData*, int16> > RecentStickerPackOld;
typedef QVector<QPair<uint64, ushort> > RecentStickerPreload;
typedef QVector<QPair<DocumentData*, ushort> > RecentStickerPack;
typedef QList<QPair<DocumentData*, int16>> RecentStickerPackOld;
typedef QVector<QPair<uint64, ushort>> RecentStickerPreload;
typedef QVector<QPair<DocumentData*, ushort>> RecentStickerPack;
DeclareSetting(RecentStickerPreload, RecentStickersPreload);
DeclareRefSetting(RecentStickerPack, RecentStickers);
RecentStickerPack &cGetRecentStickers();
typedef QList<QPair<QString, ushort> > RecentHashtagPack;
typedef QList<QPair<QString, ushort>> RecentHashtagPack;
DeclareRefSetting(RecentHashtagPack, RecentWriteHashtags);
DeclareSetting(RecentHashtagPack, RecentSearchHashtags);
@ -203,41 +197,6 @@ inline bool passcodeCanTry() {
return dt >= 30000;
}
inline void incrementRecentHashtag(RecentHashtagPack &recent, const QString &tag) {
RecentHashtagPack::iterator i = recent.begin(), e = recent.end();
for (; i != e; ++i) {
if (i->first == tag) {
++i->second;
if (qAbs(i->second) > 0x4000) {
for (RecentHashtagPack::iterator j = recent.begin(); j != e; ++j) {
if (j->second > 1) {
j->second /= 2;
} else if (j->second > 0) {
j->second = 1;
}
}
}
for (; i != recent.begin(); --i) {
if (qAbs((i - 1)->second) > qAbs(i->second)) {
break;
}
qSwap(*i, *(i - 1));
}
break;
}
}
if (i == e) {
while (recent.size() >= 64) recent.pop_back();
recent.push_back(qMakePair(tag, 1));
for (i = recent.end() - 1; i != recent.begin(); --i) {
if ((i - 1)->second > i->second) {
break;
}
qSwap(*i, *(i - 1));
}
}
}
DeclareSetting(QStringList, SendPaths);
DeclareSetting(QString, StartUrl);
@ -271,5 +230,3 @@ DeclareSetting(int32, AutoDownloadPhoto);
DeclareSetting(int32, AutoDownloadAudio);
DeclareSetting(int32, AutoDownloadGif);
DeclareSetting(bool, AutoPlayGif);
void settingsParseArgs(int argc, char *argv[]);

View File

@ -27,6 +27,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "storage/localstorage.h"
#include "platform/platform_file_utilities.h"
#include "auth_session.h"
#include "core/crash_reports.h"
namespace Storage {
@ -722,11 +723,11 @@ bool mtpFileLoader::feedPart(int offset, base::const_byte_span bytes) {
// Debugging weird out of memory crashes.
auto info = QString("offset: %1, size: %2, cancelled: %3, finished: %4, filename: '%5', tocache: %6, fromcloud: %7, data: %8, fullsize: %9").arg(offset).arg(bytes.size()).arg(Logs::b(_cancelled)).arg(Logs::b(_finished)).arg(_filename).arg(int(_toCache)).arg(int(_fromCloud)).arg(_data.size()).arg(_size);
info += QString(", locationtype: %1, inqueue: %2, localstatus: %3").arg(int(_locationType)).arg(Logs::b(_inQueue)).arg(int(_localStatus));
SignalHandlers::setCrashAnnotation("DebugInfo", info);
CrashReports::SetAnnotation("DebugInfo", info);
}
_data.reserve(offset + bytes.size());
if (offset > 100 * 1024 * 1024) {
SignalHandlers::setCrashAnnotation("DebugInfo", QString());
CrashReports::ClearAnnotation("DebugInfo");
}
if (offset > _data.size()) {

View File

@ -22,6 +22,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "storage/serialize_document.h"
#include "storage/serialize_common.h"
#include "chat_helpers/stickers.h"
#include "data/data_drafts.h"
#include "window/themes/window_theme.h"
#include "observer_peer.h"
@ -1778,7 +1779,7 @@ void _writeUserSettings() {
}
size += sizeof(quint32) + sizeof(qint32) + cEmojiVariants().size() * (sizeof(uint32) + sizeof(uint64));
size += sizeof(quint32) + sizeof(qint32) + (cRecentStickersPreload().isEmpty() ? cGetRecentStickers().size() : cRecentStickersPreload().size()) * (sizeof(uint64) + sizeof(ushort));
size += sizeof(quint32) + sizeof(qint32) + (Stickers::GetRecentPack().isEmpty() ? Stickers::GetRecentPack().size() : cRecentStickersPreload().size()) * (sizeof(uint64) + sizeof(ushort));
size += sizeof(quint32) + Serialize::stringSize(cDialogLastPath());
size += sizeof(quint32) + 3 * sizeof(qint32);
size += sizeof(quint32) + 2 * sizeof(qint32);
@ -1822,11 +1823,11 @@ void _writeUserSettings() {
}
data.stream << quint32(dbiEmojiVariants) << cEmojiVariants();
{
RecentStickerPreload v(cRecentStickersPreload());
auto v = cRecentStickersPreload();
if (v.isEmpty()) {
v.reserve(cGetRecentStickers().size());
for (RecentStickerPack::const_iterator i = cGetRecentStickers().cbegin(), e = cGetRecentStickers().cend(); i != e; ++i) {
v.push_back(qMakePair(i->first->id, i->second));
v.reserve(Stickers::GetRecentPack().size());
for_const (auto &pair, Stickers::GetRecentPack()) {
v.push_back(qMakePair(pair.first->id, pair.second));
}
}
data.stream << quint32(dbiRecentStickers) << v;

View File

@ -20,6 +20,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "ui/text/text_block.h"
#include "core/crash_reports.h"
// COPIED FROM qtextlayout.cpp AND MODIFIED
namespace {
@ -327,7 +329,7 @@ TextBlock::TextBlock(const style::font &font, const QString &str, QFixed minResi
QString part = str.mid(_from, length);
// Attempt to catch a crash in text processing
SignalHandlers::setCrashAnnotationRef("CrashString", &part);
CrashReports::SetAnnotationRef("CrashString", &part);
QStackTextEngine engine(part, blockFont->f);
QTextLayout layout(&engine);
@ -338,7 +340,7 @@ TextBlock::TextBlock(const style::font &font, const QString &str, QFixed minResi
layout.endLayout();
SignalHandlers::clearCrashAnnotationRef("CrashString");
CrashReports::ClearAnnotationRef("CrashString");
}
}

View File

@ -398,3 +398,8 @@ if [ "$BuildTarget" == "mac" ] || [ "$BuildTarget" == "mac32" ] || [ "$BuildTarg
fi
echo "Version $AppVersionStrFull is ready!";
echo -en "\007";
sleep 1;
echo -en "\007";
sleep 1;
echo -en "\007";

View File

@ -141,8 +141,14 @@
<(src_loc)/core/click_handler.h
<(src_loc)/core/click_handler_types.cpp
<(src_loc)/core/click_handler_types.h
<(src_loc)/core/crash_report_window.cpp
<(src_loc)/core/crash_report_window.h
<(src_loc)/core/crash_reports.cpp
<(src_loc)/core/crash_reports.h
<(src_loc)/core/file_utilities.cpp
<(src_loc)/core/file_utilities.h
<(src_loc)/core/launcher.cpp
<(src_loc)/core/launcher.h
<(src_loc)/core/single_timer.cpp
<(src_loc)/core/single_timer.h
<(src_loc)/core/tl_help.h
@ -398,6 +404,8 @@
<(src_loc)/platform/linux/linux_libs.h
<(src_loc)/platform/linux/file_utilities_linux.cpp
<(src_loc)/platform/linux/file_utilities_linux.h
<(src_loc)/platform/linux/launcher_linux.cpp
<(src_loc)/platform/linux/launcher_linux.h
<(src_loc)/platform/linux/main_window_linux.cpp
<(src_loc)/platform/linux/main_window_linux.h
<(src_loc)/platform/linux/notifications_manager_linux.cpp
@ -406,6 +414,8 @@
<(src_loc)/platform/linux/specific_linux.h
<(src_loc)/platform/mac/file_utilities_mac.mm
<(src_loc)/platform/mac/file_utilities_mac.h
<(src_loc)/platform/mac/launcher_mac.mm
<(src_loc)/platform/mac/launcher_mac.h
<(src_loc)/platform/mac/mac_iconv_helper.c
<(src_loc)/platform/mac/mac_utilities.mm
<(src_loc)/platform/mac/mac_utilities.h
@ -423,6 +433,8 @@
<(src_loc)/platform/win/audio_win.h
<(src_loc)/platform/win/file_utilities_win.cpp
<(src_loc)/platform/win/file_utilities_win.h
<(src_loc)/platform/win/launcher_win.cpp
<(src_loc)/platform/win/launcher_win.h
<(src_loc)/platform/win/main_window_win.cpp
<(src_loc)/platform/win/main_window_win.h
<(src_loc)/platform/win/notifications_manager_win.cpp
@ -440,6 +452,7 @@
<(src_loc)/platform/win/windows_range_v3_helpers.h
<(src_loc)/platform/platform_audio.h
<(src_loc)/platform/platform_file_utilities.h
<(src_loc)/platform/platform_launcher.h
<(src_loc)/platform/platform_main_window.h
<(src_loc)/platform/platform_notifications_manager.h
<(src_loc)/platform/platform_specific.h