xp-sp3: change grammer to support Qt5.6.3 for xp with sp3 system.

This commit is contained in:
2025-06-25 10:54:04 +08:00
parent 1f9275ed72
commit 60f5cb62b1
26 changed files with 250 additions and 246 deletions

View File

@@ -24,15 +24,16 @@
"-Wno-dev"
],
"cmake.environment": {
"QT_LIB_ROOT": "D:/Dev/Qt6/msvc2022_64",
"PATH": "${env:PATH};D:/Dev/Qt6/msvc2022_64/bin"
"QT_LIB_ROOT": "C:/Qt/Qt5.6.3/5.6.3/mingw49_32",
"PATH": "${env:PATH};C:/Qt/Qt5.6.3/5.6.3/mingw49_32/bin"
},
// "cmake.environment": {
// "QT_LIB_ROOT": "C:/Qt/Qt5.14.2/5.14.2/msvc2017_64",
// "PATH": "${env:PATH};C:/Qt/Qt5.14.2/5.14.2/msvc2017_64/bin"
// },
"cmake.configureSettings": {
"CMAKE_PREFIX_PATH": "${env:QT_LIB_ROOT}"
"CMAKE_PREFIX_PATH": "${env:QT_LIB_ROOT}",
"XP_PLATFORM_SUPPORT": "ON"
},
"cmake.options.statusBarVisibility": "visible",
"cmake.generator": "Ninja",

View File

@@ -1,11 +1,11 @@
cmake_minimum_required(VERSION 3.16)
project(frelay VERSION 0.1.3 LANGUAGES CXX)
project(frelay VERSION 0.1.4 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(PROJECT_URL "https://github.com/taynpg/frelay")
set(QT_DEFAULT_MAJOR_VERSION 6)
set(QT_DEFAULT_MAJOR_VERSION 5)
set(QAPPLICATION_CLASS QApplication)
if (MSVC)
@@ -19,15 +19,11 @@ add_definitions(-DCOMPILER_USE_MINGW)
endif()
if(WIN32)
execute_process(COMMAND cmd /c ver
OUTPUT_VARIABLE VER_OUTPUT
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(VER_OUTPUT MATCHES "XP")
message(STATUS "Windows XP platform.")
add_definitions(-D_WIN32_WINNT=0x0501)
if(DEFINED XP_PLATFORM_SUPPORT)
message(STATUS "For Windows XP platform.")
add_definitions(-D_WIN32_WINNT=0x0501)
else()
message(STATUS "Windows NT platform.")
add_definitions(-D_WIN32_WINNT=0x0601)
add_definitions(-D_WIN32_WINNT=0x0601)
endif()
endif()
@@ -39,7 +35,11 @@ include_directories(${PROJECT_BINARY_DIR})
add_definitions(-DFMT_HEADER_ONLY)
include_directories(3rd)
add_subdirectory(3rd/SingleApplication-3.5.2)
if(NOT DEFINED COMPILER_USE_MINGW)
add_subdirectory(crashelper)
endif()
add_subdirectory(Protocol)
add_subdirectory(Server)
add_subdirectory(ClientCore)

View File

@@ -18,6 +18,11 @@ ClientCore::~ClientCore()
{
}
bool ClientCore::SendFrame(QSharedPointer<FrameBuffer> frame)
{
return Send(frame);
}
void ClientCore::DoConnect(const QString& ip, quint16 port)
{
// qDebug() << "doConnect thread:" << QThread::currentThread();
@@ -31,11 +36,6 @@ void ClientCore::DoConnect(const QString& ip, quint16 port)
bool ClientCore::Connect(const QString& ip, quint16 port)
{
QMutexLocker locker(&conMutex_);
if (!locker.isLocked()) {
qWarning() << QString(tr("%1:%2 already connecting...")).arg(ip).arg(port);
return false;
}
socket_->connectToHost(ip, port);
if (!socket_->waitForConnected(3000)) {
qCritical() << QString(tr("%1:%2 connect failed...")).arg(ip).arg(port);

View File

@@ -9,13 +9,14 @@
#include <Protocol.h>
#include <QDataStream>
#include <QFuture>
#include <QFutureWatcher>
#include <QHostAddress>
#include <QMutex>
#include <QMutexLocker>
#include <QPromise>
#include <QQueue>
#include <QTcpSocket>
#include <QThread>
#include <QtConcurrent/QtConcurrentRun>
#include <array>
class ClientCore : public QObject
@@ -26,6 +27,9 @@ public:
ClientCore(QObject* parent = nullptr);
~ClientCore();
public slots:
bool SendFrame(QSharedPointer<FrameBuffer> frame);
public:
void Instance();
bool Connect(const QString& ip, quint16 port);
@@ -46,30 +50,15 @@ public:
f->type = type;
return f;
}
/*
When calling syncInvoke of ClientCore, the ClientCore should not be in the GUI's event loop thread.
In other words, if a ClientCore instance is created in the GUI thread, it should be moved to another thread;
otherwise, it will cause a deadlock and freeze the interface.
*/
template <typename Callable> static bool syncInvoke(QObject* context, Callable&& func)
static bool syncInvoke(ClientCore* context, QSharedPointer<FrameBuffer> frame)
{
auto promise = QSharedPointer<QPromise<bool>>::create();
QFuture<bool> future = promise->future();
QMetaObject::invokeMethod(
context,
[func = std::forward<Callable>(func), promise]() mutable {
try {
promise->addResult(func());
} catch (...) {
promise->addResult(false);
}
promise->finish();
},
Qt::QueuedConnection);
future.waitForFinished();
return future.result();
bool result = false;
bool success = QMetaObject::invokeMethod(context, "SendFrame", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, result),
Q_ARG(QSharedPointer<FrameBuffer>, frame));
if (!success) {
return false;
}
return result;
}
signals:
@@ -114,7 +103,7 @@ public:
QTcpSocket* socket_{};
QByteArray recvBuffer_;
bool connected_{ false };
bool connected_{false};
LocalFile localFile_;
};

View File

@@ -49,7 +49,7 @@ void FileTrans::ReqSendFile(const TransTask& task)
}
auto frame = clientCore_->GetBuffer(info, FBT_CLI_REQ_SEND, task.remoteId);
if (!ClientCore::syncInvoke(clientCore_, [this, frame]() { return clientCore_->Send(frame); })) {
if (!ClientCore::syncInvoke(clientCore_, frame)) {
qCritical() << QString(tr("send req send failed: %1")).arg(info.msg);
sendTask_->state = TaskState::STATE_NONE;
sendTask_->file.close();
@@ -79,7 +79,7 @@ void FileTrans::ReqDownFile(const TransTask& task)
return;
}
auto frame = clientCore_->GetBuffer(info, FBT_CLI_REQ_DOWN, task.remoteId);
if (!ClientCore::syncInvoke(clientCore_, [this, frame]() { return clientCore_->Send(frame); })) {
if (!ClientCore::syncInvoke(clientCore_, frame)) {
qCritical() << QString(tr("send req send failed: %1")).arg(info.msg);
downTask_->state = TaskState::STATE_NONE;
downTask_->file.close();
@@ -154,7 +154,7 @@ void FileTrans::fbtReqSend(QSharedPointer<FrameBuffer> frame)
if (downTask_->state == TaskState::STATE_RUNNING) {
info.msg = QString(tr("busy..."));
auto f = clientCore_->GetBuffer(info, FBT_CLI_CANOT_SEND, frame->fid);
ClientCore::syncInvoke(clientCore_, [this, f]() { return clientCore_->Send(f); });
ClientCore::syncInvoke(clientCore_, f);
return;
}
@@ -165,7 +165,7 @@ void FileTrans::fbtReqSend(QSharedPointer<FrameBuffer> frame)
info.msg = QString(tr("open file failed: %1")).arg(newerPath);
qCritical() << info.msg;
auto f = clientCore_->GetBuffer(info, FBT_CLI_CANOT_SEND, frame->fid);
if (!ClientCore::syncInvoke(clientCore_, [this, f]() { return clientCore_->Send(f); })) {
if (!ClientCore::syncInvoke(clientCore_, f)) {
qCritical() << QString(tr("open recv file:%2 failed, and reply %2 failed.")).arg(info.msg, f->fid);
downTask_->file.close();
return;
@@ -180,7 +180,7 @@ void FileTrans::fbtReqSend(QSharedPointer<FrameBuffer> frame)
info.msg = QString(tr("open recv file success: %1")).arg(newerPath);
qInfo() << info.msg;
auto f = clientCore_->GetBuffer(info, FBT_CLI_CAN_SEND, frame->fid);
if (!ClientCore::syncInvoke(clientCore_, [this, f]() { return clientCore_->Send(f); })) {
if (!ClientCore::syncInvoke(clientCore_, f)) {
qCritical() << QString(tr("open recv file:%2 success, but reply %2 failed.")).arg(info.msg, frame->fid);
downTask_->file.close();
return;
@@ -217,7 +217,7 @@ void FileTrans::fbtReqDown(QSharedPointer<FrameBuffer> frame)
// reply fileinfo
auto f = clientCore_->GetBuffer(info, FBT_CLI_FILE_INFO, frame->fid);
if (!ClientCore::syncInvoke(clientCore_, [this, f]() { return clientCore_->Send(f); })) {
if (!ClientCore::syncInvoke(clientCore_, f)) {
qCritical() << QString(tr("send file %1 info failed.")).arg(info.fromPath);
doTask->file.close();
return;
@@ -237,7 +237,7 @@ void FileTrans::fbtTransDone(QSharedPointer<FrameBuffer> frame)
info.msg = QString(tr("recv file:%1 success.")).arg(downTask_->file.fileName());
qInfo() << info.msg;
auto f = clientCore_->GetBuffer(info, FBT_CLI_CAN_DOWN, frame->fid);
ClientCore::syncInvoke(clientCore_, [this, f]() { return clientCore_->Send(f); });
ClientCore::syncInvoke(clientCore_, f);
return;
}
qCritical() << QString(tr("recv file:%1 done sigal, but file not opened.")).arg(info.msg);
@@ -272,7 +272,7 @@ void FileTrans::fbtFileBuffer(QSharedPointer<FrameBuffer> frame)
InfoMsg info;
info.msg = downTask_->file.errorString();
auto f = clientCore_->GetBuffer(info, FBT_CLI_TRANS_FAILED, frame->fid);
ClientCore::syncInvoke(clientCore_, [this, f]() { return clientCore_->Send(f); });
ClientCore::syncInvoke(clientCore_, f);
downTask_->file.close();
}
downTask_->tranSize += ws;
@@ -351,12 +351,13 @@ void SendThread::run()
// shoule add abort action mark.
}
QMetaObject::invokeMethod(cliCore_, [this, frame] {
frame->sendRet = cliCore_->Send(frame);
if (frame->call) {
frame->call(frame);
}
});
// QMetaObject::invokeMethod(cliCore_, [this, frame] {
// frame->sendRet = cliCore_->Send(frame);
// if (frame->call) {
// frame->call(frame);
// }
// });
++curSendCount_;
if (!isSuccess_) {
@@ -372,7 +373,7 @@ void SendThread::run()
InfoMsg info;
auto f = cliCore_->GetBuffer(info, FBT_CLI_TRANS_DONE, task_->task.remoteId);
ClientCore::syncInvoke(cliCore_, [this, f]() { return cliCore_->Send(f); });
ClientCore::syncInvoke(cliCore_, f);
task_->file.close();
task_->state = TaskState::STATE_FINISH;
}

View File

@@ -2,11 +2,10 @@
#define FILETRANS_H
#include <QFile>
#include <QFuture>
#include <QMap>
#include <QMutex>
#include <QVector>
#include <QFuture>
#include <QPromise>
#include "ClientCore.h"
@@ -50,7 +49,7 @@ public:
void sendCall(QSharedPointer<FrameBuffer> frame);
private:
bool isSuccess_{ false };
bool isSuccess_{false};
ClientCore* cliCore_;
quint32 curSendCount_{0};
QSharedPointer<DoTransTask> task_;

View File

@@ -19,7 +19,7 @@ bool RemoteFile::GetHome()
{
InfoMsg info;
auto frame = cliCore_->GetBuffer(info, FBT_CLI_ASK_HOME, cliCore_->GetRemoteID());
return ClientCore::syncInvoke(cliCore_, [this, frame]() { return cliCore_->Send(frame); });
return ClientCore::syncInvoke(cliCore_, frame);
}
bool RemoteFile::GetDirFile(const QString& dir)
@@ -27,5 +27,5 @@ bool RemoteFile::GetDirFile(const QString& dir)
InfoMsg info;
info.msg = dir;
auto frame = cliCore_->GetBuffer(info, FBT_CLI_ASK_DIRFILE, cliCore_->GetRemoteID());
return ClientCore::syncInvoke(cliCore_, [this, frame]() { return cliCore_->Send(frame); });
return ClientCore::syncInvoke(cliCore_, frame);
}

View File

@@ -1,5 +1,6 @@
#include <QCoreApplication>
#include <Util.h>
#include <iostream>
#include "Console.h"

View File

@@ -110,7 +110,7 @@ void Connecter::RefreshClient()
auto frame = QSharedPointer<FrameBuffer>::create();
frame->data = infoPack(info);
frame->type = FBT_SER_MSG_ASKCLIENTS;
auto sendRet = ClientCore::syncInvoke(clientCore_, [this, frame]() { return clientCore_->Send(frame); });
auto sendRet = ClientCore::syncInvoke(clientCore_, frame);
if (!sendRet) {
qCritical() << QString(tr("send ask client list failed."));
return;

View File

@@ -47,7 +47,6 @@ private:
private:
Ui::Connecter* ui;
bool connceted_{false};
std::thread thContext_;
std::function<void(const QString& id)> remoteCall_;
ClientCore* clientCore_;

View File

@@ -4,10 +4,11 @@
#include <ClientCore.h>
#include <FileTrans.h>
#include <InfoDirFile.h>
#include <QMenu>
#include <QMutex>
#include <QWidget>
#include <Util.h>
#include <QMutex>
#include <QMenu>
#include <memory>
namespace Ui {
class FileManager;

View File

@@ -3,6 +3,8 @@
#include <QDateTime>
#include <QListWidgetItem>
#include <QStandardItem>
#include <chrono>
#include <ctime>
#include <iomanip>
#include <sstream>
@@ -17,9 +19,11 @@ LogPrint::LogPrint(QWidget* parent) : QWidget(parent), ui(new Ui::LogPrint)
void LogPrint::InitControl()
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
isLightMode_ = QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Light;
styleHints_ = QGuiApplication::styleHints();
connect(styleHints_, &QStyleHints::colorSchemeChanged, this, &LogPrint::ColorChange);
#endif
ui->pedText->setReadOnly(true);
}
@@ -29,13 +33,19 @@ std::string LogPrint::now_str()
auto time_t_now = std::chrono::system_clock::to_time_t(now);
auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
// std::ostringstream timestamp;
// timestamp << std::put_time(std::localtime(&time_t_now), "%H:%M:%S") << "." << std::setfill('0') << std::setw(3)
// << milliseconds.count() << " ";
char timeStr[20];
std::strftime(timeStr, sizeof(timeStr), "%H:%M:%S", std::localtime(&time_t_now));
std::ostringstream timestamp;
timestamp << std::put_time(std::localtime(&time_t_now), "%H:%M:%S") << "." << std::setfill('0') << std::setw(3)
<< milliseconds.count() << " ";
timestamp << timeStr << "." << std::setfill('0') << std::setw(3) << milliseconds.count() << " ";
return timestamp.str();
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
void LogPrint::ColorChange(Qt::ColorScheme scheme)
{
if (scheme == Qt::ColorScheme::Dark) {
@@ -45,6 +55,7 @@ void LogPrint::ColorChange(Qt::ColorScheme scheme)
}
RePrintLog();
}
#endif
LogPrint::~LogPrint()
{

View File

@@ -36,7 +36,10 @@ public:
public:
std::string now_str();
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
void ColorChange(Qt::ColorScheme scheme);
#endif
private:
void InitControl();
@@ -51,7 +54,11 @@ private:
QMap<PrintType, QBrush> lightMap_;
QMap<PrintType, QBrush> darkMap_;
QVector<LogEntry> logEntries_;
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
QStyleHints* styleHints_{};
#endif
QStandardItemModel* model_;
};

View File

@@ -5,6 +5,7 @@
#include <QMimeData>
#include <QPainter>
#include <Util.h>
#include <functional>
#include "GuiUtil/Public.h"

View File

@@ -92,25 +92,20 @@ void frelayGUI::ControlLayout()
void frelayGUI::ControlMsgHander(QtMsgType type, const QMessageLogContext& context, const QString& msg)
{
QMetaObject::invokeMethod(
qApp,
[type, msg]() {
switch (type) {
case QtDebugMsg:
logPrint->Debug(msg);
break;
case QtInfoMsg:
logPrint->Info(msg);
break;
case QtWarningMsg:
logPrint->Warn(msg);
break;
default:
logPrint->Error(msg);
break;
}
},
Qt::QueuedConnection);
switch (type) {
case QtDebugMsg:
logPrint->Debug(msg);
break;
case QtInfoMsg:
logPrint->Info(msg);
break;
case QtWarningMsg:
logPrint->Warn(msg);
break;
default:
logPrint->Error(msg);
break;
}
}
void frelayGUI::HandleTask(const QVector<TransTask>& tasks)

View File

@@ -20,9 +20,9 @@ int main(int argc, char* argv[])
#else
backward::SetDumpLogSavePath(configDir + QDir::separator() + "dumplog");
#endif
CRASHELPER_MARK_ENTRY();
#endif
CRASHELPER_MARK_ENTRY();
SingleApplication a(argc, argv);
#ifdef _WIN32

View File

@@ -1,5 +1,6 @@
#include "Protocol.h"
#include <QDataStream>
#include <QIODevice>
#include <cstdint>
@@ -14,12 +15,12 @@ QSharedPointer<FrameBuffer> Protocol::ParseBuffer(QByteArray& buffer)
int headerPos = buffer.indexOf(protocolHeader);
if (headerPos == -1) {
return nullptr;
return QSharedPointer<FrameBuffer>();
}
const int minFrameSize = protocolHeader.size() + sizeof(uint16_t) + 32 + 32 + sizeof(uint32_t) + protocolTail.size();
if (buffer.size() - headerPos < minFrameSize) {
return nullptr;
return QSharedPointer<FrameBuffer>();
}
QDataStream stream(buffer.mid(headerPos));
@@ -29,7 +30,7 @@ QSharedPointer<FrameBuffer> Protocol::ParseBuffer(QByteArray& buffer)
header.resize(protocolHeader.size());
stream.readRawData(header.data(), protocolHeader.size());
if (header != protocolHeader) {
return nullptr;
return QSharedPointer<FrameBuffer>();
}
FrameBufferType type;
@@ -51,7 +52,7 @@ QSharedPointer<FrameBuffer> Protocol::ParseBuffer(QByteArray& buffer)
int totalFrameSize = minFrameSize - protocolTail.size() + dataLen;
if (buffer.size() - headerPos < totalFrameSize) {
return nullptr;
return QSharedPointer<FrameBuffer>();
}
QByteArray data;
if (dataLen > 0) {
@@ -62,7 +63,7 @@ QSharedPointer<FrameBuffer> Protocol::ParseBuffer(QByteArray& buffer)
tail.resize(protocolTail.size());
stream.readRawData(tail.data(), protocolTail.size());
if (tail != protocolTail) {
return nullptr;
return QSharedPointer<FrameBuffer>();
}
auto frame = QSharedPointer<FrameBuffer>::create();
frame->type = type;

View File

@@ -2,9 +2,10 @@
#define PROTOCOL_H
#include <QByteArray>
#include <QMetaType>
#include <QSharedPointer>
#include <QString>
#include <QMetaType>
#include <functional>
constexpr quint32 CHUNK_BUF_SIZE = 1 * 1024 * 1024;
@@ -54,5 +55,4 @@ public:
static QByteArray PackBuffer(const QSharedPointer<FrameBuffer>& frame);
};
#endif // PROTOCOL_H

View File

@@ -63,7 +63,8 @@ void Server::onNewConnection()
client->socket = clientSocket;
client->socket->setProperty("clientId", clientId);
client->id = clientId;
client->connectTime = QDateTime::currentSecsSinceEpoch();
// client->connectTime = QDateTime::currentSecsSinceEpoch();
client->connectTime = QDateTime::currentDateTime().toMSecsSinceEpoch() / 1000;
connect(clientSocket, &QTcpSocket::readyRead, this, &Server::onReadyRead);
connect(clientSocket, &QTcpSocket::disconnected, this, &Server::onClientDisconnected);
@@ -198,7 +199,8 @@ bool Server::sendData(QTcpSocket* socket, QSharedPointer<FrameBuffer> frame)
void Server::monitorClients()
{
qint64 now = QDateTime::currentSecsSinceEpoch();
// qint64 now = QDateTime::currentSecsSinceEpoch();
qint64 now = QDateTime::currentDateTime().toMSecsSinceEpoch() / 1000;
QWriteLocker locker(&rwLock_);
for (auto it = clients_.begin(); it != clients_.end();) {

View File

@@ -30,14 +30,15 @@ struct InfoClientVec {
void serialize(QDataStream& data) const
{
data << vec.size();
uint32_t size = static_cast<uint32_t>(vec.size());
data << size;
for (const auto& info : vec) {
data << info;
}
}
void deserialize(QDataStream& data)
{
qsizetype size;
uint32_t size = 0;
data >> size;
vec.resize(size);
for (quint32 i = 0; i < size; ++i) {

View File

@@ -19,12 +19,15 @@ struct DirFileInfo {
void serialize(QDataStream& data) const
{
data << name << size << type << fullPath << permission << lastModified;
uint32_t t = static_cast<FileType>(type);
data << name << size << t << fullPath << permission << lastModified;
}
void deserialize(QDataStream& data)
{
data >> name >> size >> type >> fullPath >> permission >> lastModified;
uint32_t t = 0;
data >> name >> size >> t >> fullPath >> permission >> lastModified;
type = static_cast<FileType>(t);
}
};
@@ -37,7 +40,8 @@ struct DirFileInfoVec {
void serialize(QDataStream& data) const
{
data << vec.size();
uint32_t size = static_cast<uint32_t>(vec.size());
data << size;
for (const auto& info : vec) {
data << info;
}
@@ -45,7 +49,7 @@ struct DirFileInfoVec {
}
void deserialize(QDataStream& data)
{
qsizetype size;
uint32_t size = 0;
data >> size;
vec.resize(size);
for (quint32 i = 0; i < size; ++i) {

18
Test/BaseTest.cpp Normal file
View File

@@ -0,0 +1,18 @@
#include <QCoreApplication>
#include <QDateTime>
#include <QDebug>
void DateTimeTest()
{
qDebug() << QDateTime::currentDateTime().toMSecsSinceEpoch();
}
int main(int argc, char** argv)
{
QCoreApplication app(argc, argv);
qDebug() << "Running...";
DateTimeTest();
return app.exec();
}

View File

@@ -1,13 +1,24 @@
cmake_minimum_required(VERSION 3.16)
project(frelayTest LANGUAGES CXX)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core)
set(MSOURCES
msgTest.h msgTest.cpp
protocolTest.cpp infoTest.h infoTest.cpp
)
add_executable(frelayTest ${MSOURCES})
target_link_libraries(frelayTest PRIVATE Protocol Util)
target_link_libraries(frelayTest PRIVATE Protocol Util)
add_executable(frelayBaseTest BaseTest.cpp)
target_link_libraries(frelayBaseTest Qt${QT_VERSION_MAJOR}::Core)

View File

@@ -3,6 +3,7 @@
#include <QDateTime>
#include <QDebug>
#include <QDir>
#include <QFileInfo>
#include <QMutex>
#include <QStandardPaths>
#include <iostream>
@@ -77,9 +78,6 @@ void Util::InitLogger(const QString& logPath, const QString& mark)
spdlog::register_logger(logger);
}
#include <QDir>
#include <QFileInfo>
// do not check exit
QString Util::Get2FilePath(const QString& file, const QString& directory)
{

View File

@@ -335,21 +335,19 @@
#if defined(BACKWARD_SYSTEM_WINDOWS)
#include <basetsd.h>
#include <condition_variable>
#include <mutex>
#include <thread>
#include <basetsd.h>
typedef SSIZE_T ssize_t;
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#include <winnt.h>
#include <psapi.h>
#include <signal.h>
#include <windows.h>
#include <winnt.h>
#ifndef __clang__
#undef NOINLINE
@@ -1293,8 +1291,7 @@ public:
for (;;) {
// NOTE: this only works if PDBs are already loaded!
SetLastError(0);
if (!StackWalk64(machine_type_, process, thd_, &s, ctx_, NULL, SymFunctionTableAccess64, SymGetModuleBase64,
NULL))
if (!StackWalk64(machine_type_, process, thd_, &s, ctx_, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))
break;
if (s.AddrReturn.Offset == 0)
@@ -1797,13 +1794,11 @@ private:
static void find_in_section_trampoline(bfd*, asection* section, void* data)
{
find_sym_context* context = static_cast<find_sym_context*>(data);
context->self->find_in_section(reinterpret_cast<bfd_vma>(context->addr),
reinterpret_cast<bfd_vma>(context->base_addr), context->fobj, section,
context->result);
context->self->find_in_section(reinterpret_cast<bfd_vma>(context->addr), reinterpret_cast<bfd_vma>(context->base_addr),
context->fobj, section, context->result);
}
void find_in_section(bfd_vma addr, bfd_vma base_addr, bfd_fileobject* fobj, asection* section,
find_sym_result& result)
void find_in_section(bfd_vma addr, bfd_vma base_addr, bfd_fileobject* fobj, asection* section, find_sym_result& result)
{
if (result.found)
return;
@@ -1844,8 +1839,8 @@ private:
}
if (!result.found && fobj->dynamic_symtab) {
result.found = bfd_find_nearest_line(fobj->handle.get(), section, fobj->dynamic_symtab.get(),
addr - sec_addr, &result.filename, &result.funcname, &result.line);
result.found = bfd_find_nearest_line(fobj->handle.get(), section, fobj->dynamic_symtab.get(), addr - sec_addr,
&result.filename, &result.funcname, &result.line);
}
#if defined(__clang__)
#pragma clang diagnostic pop
@@ -2490,62 +2485,61 @@ private:
// We go the preprocessor way to avoid having to create templated
// classes or using gelf (which might throw a compiler error if 64 bit
// is not supported
#define ELF_GET_DATA(ARCH) \
Elf_Scn* elf_section = 0; \
Elf_Data* elf_data = 0; \
Elf##ARCH##_Shdr* section_header = 0; \
Elf_Scn* symbol_section = 0; \
size_t symbol_count = 0; \
size_t symbol_strings = 0; \
Elf##ARCH##_Sym* symbol = 0; \
const char* section_name = 0; \
\
while ((elf_section = elf_nextscn(elf_handle.get(), elf_section)) != NULL) { \
section_header = elf##ARCH##_getshdr(elf_section); \
if (section_header == NULL) { \
return r; \
} \
\
if ((section_name = elf_strptr(elf_handle.get(), shdrstrndx, section_header->sh_name)) == NULL) { \
return r; \
} \
\
if (cstrings_eq(section_name, ".gnu_debuglink")) { \
elf_data = elf_getdata(elf_section, NULL); \
if (elf_data && elf_data->d_size > 0) { \
debuglink = std::string(reinterpret_cast<const char*>(elf_data->d_buf)); \
} \
} \
\
switch (section_header->sh_type) { \
case SHT_SYMTAB: \
symbol_section = elf_section; \
symbol_count = section_header->sh_size / section_header->sh_entsize; \
symbol_strings = section_header->sh_link; \
break; \
\
/* We use .dynsyms as a last resort, we prefer .symtab */ \
case SHT_DYNSYM: \
if (!symbol_section) { \
symbol_section = elf_section; \
symbol_count = section_header->sh_size / section_header->sh_entsize; \
symbol_strings = section_header->sh_link; \
} \
break; \
} \
} \
\
if (symbol_section && symbol_count && symbol_strings) { \
elf_data = elf_getdata(symbol_section, NULL); \
symbol = reinterpret_cast<Elf##ARCH##_Sym*>(elf_data->d_buf); \
for (size_t i = 0; i < symbol_count; ++i) { \
int type = ELF##ARCH##_ST_TYPE(symbol->st_info); \
if (type == STT_FUNC && symbol->st_value > 0) { \
r.symbol_cache[symbol->st_value] = \
std::string(elf_strptr(elf_handle.get(), symbol_strings, symbol->st_name)); \
} \
++symbol; \
} \
#define ELF_GET_DATA(ARCH) \
Elf_Scn* elf_section = 0; \
Elf_Data* elf_data = 0; \
Elf##ARCH##_Shdr* section_header = 0; \
Elf_Scn* symbol_section = 0; \
size_t symbol_count = 0; \
size_t symbol_strings = 0; \
Elf##ARCH##_Sym* symbol = 0; \
const char* section_name = 0; \
\
while ((elf_section = elf_nextscn(elf_handle.get(), elf_section)) != NULL) { \
section_header = elf##ARCH##_getshdr(elf_section); \
if (section_header == NULL) { \
return r; \
} \
\
if ((section_name = elf_strptr(elf_handle.get(), shdrstrndx, section_header->sh_name)) == NULL) { \
return r; \
} \
\
if (cstrings_eq(section_name, ".gnu_debuglink")) { \
elf_data = elf_getdata(elf_section, NULL); \
if (elf_data && elf_data->d_size > 0) { \
debuglink = std::string(reinterpret_cast<const char*>(elf_data->d_buf)); \
} \
} \
\
switch (section_header->sh_type) { \
case SHT_SYMTAB: \
symbol_section = elf_section; \
symbol_count = section_header->sh_size / section_header->sh_entsize; \
symbol_strings = section_header->sh_link; \
break; \
\
/* We use .dynsyms as a last resort, we prefer .symtab */ \
case SHT_DYNSYM: \
if (!symbol_section) { \
symbol_section = elf_section; \
symbol_count = section_header->sh_size / section_header->sh_entsize; \
symbol_strings = section_header->sh_link; \
} \
break; \
} \
} \
\
if (symbol_section && symbol_count && symbol_strings) { \
elf_data = elf_getdata(symbol_section, NULL); \
symbol = reinterpret_cast<Elf##ARCH##_Sym*>(elf_data->d_buf); \
for (size_t i = 0; i < symbol_count; ++i) { \
int type = ELF##ARCH##_ST_TYPE(symbol->st_info); \
if (type == STT_FUNC && symbol->st_value > 0) { \
r.symbol_cache[symbol->st_value] = std::string(elf_strptr(elf_handle.get(), symbol_strings, symbol->st_name)); \
} \
++symbol; \
} \
}
if (e_ident[EI_CLASS] == ELFCLASS32) {
@@ -2639,8 +2633,7 @@ private:
if (dwarf_srclines_b(die, 0, &table_count, &de.line_context, &error) == DW_DLV_OK) {
// Get the source lines for this line context, to be deallocated
// later
if (dwarf_srclines_from_linecontext(de.line_context, &de.line_buffer, &de.line_count, &error) ==
DW_DLV_OK) {
if (dwarf_srclines_from_linecontext(de.line_context, &de.line_buffer, &de.line_count, &error) == DW_DLV_OK) {
// Add all the addresses to our map
for (int i = 0; i < de.line_count; i++) {
@@ -2832,8 +2825,7 @@ private:
if (dwarf_get_ranges_a(dwarf, offset, die, &ranges, &ranges_count, &byte_count, &error) == DW_DLV_OK) {
has_ranges = ranges_count != 0;
for (int i = 0; i < ranges_count; i++) {
if (ranges[i].dwr_addr1 != 0 && pc >= ranges[i].dwr_addr1 + low_pc &&
pc < ranges[i].dwr_addr2 + low_pc) {
if (ranges[i].dwr_addr1 != 0 && pc >= ranges[i].dwr_addr1 + low_pc && pc < ranges[i].dwr_addr2 + low_pc) {
result = true;
break;
}
@@ -2908,8 +2900,7 @@ private:
std::string result;
bool found = false;
while (dwarf_next_cu_header_d(dwarf, 0, 0, 0, 0, 0, 0, 0, &tu_signature, 0, &next_cu_header, 0, &error) ==
DW_DLV_OK) {
while (dwarf_next_cu_header_d(dwarf, 0, 0, 0, 0, 0, 0, 0, &tu_signature, 0, &next_cu_header, 0, &error) == DW_DLV_OK) {
if (strncmp(signature.signature, tu_signature.signature, 8) == 0) {
Dwarf_Die type_cu_die = 0;
@@ -3072,8 +3063,8 @@ private:
}
// Resolve the function return type and parameters
static void set_function_parameters(std::string& function_name, std::vector<std::string>& ns,
dwarf_fileobject& fobj, Dwarf_Die die)
static void set_function_parameters(std::string& function_name, std::vector<std::string>& ns, dwarf_fileobject& fobj,
Dwarf_Die die)
{
Dwarf_Debug dwarf = fobj.dwarf_handle.get();
Dwarf_Error error = DW_DLE_NE;
@@ -3335,8 +3326,8 @@ private:
}
template <typename CB>
static bool deep_first_search_by_pc(dwarf_fileobject& fobj, Dwarf_Die parent_die, Dwarf_Addr pc,
std::vector<std::string>& ns, CB cb)
static bool deep_first_search_by_pc(dwarf_fileobject& fobj, Dwarf_Die parent_die, Dwarf_Addr pc, std::vector<std::string>& ns,
CB cb)
{
Dwarf_Die current_die = 0;
Dwarf_Debug dwarf = fobj.dwarf_handle.get();
@@ -3371,8 +3362,7 @@ private:
bool declaration = false;
Dwarf_Attribute attr_mem;
if (tag != DW_TAG_class_type &&
dwarf_attr(current_die, DW_AT_declaration, &attr_mem, &error) == DW_DLV_OK) {
if (tag != DW_TAG_class_type && dwarf_attr(current_die, DW_AT_declaration, &attr_mem, &error) == DW_DLV_OK) {
Dwarf_Bool flag = 0;
if (dwarf_formflag(attr_mem, &flag, &error) == DW_DLV_OK) {
declaration = flag != 0;
@@ -3501,8 +3491,7 @@ private:
Dwarf_Half tag = 0;
returnDie = 0;
while (!found &&
dwarf_next_cu_header_d(dwarf, 1, 0, 0, 0, 0, 0, 0, 0, 0, &next_cu_header, 0, &error) == DW_DLV_OK) {
while (!found && dwarf_next_cu_header_d(dwarf, 1, 0, 0, 0, 0, 0, 0, 0, 0, &next_cu_header, 0, &error) == DW_DLV_OK) {
if (returnDie)
dwarf_dealloc(dwarf, returnDie, DW_DLA_DIE);
@@ -3643,8 +3632,7 @@ private:
details::handle<char**> _symbols;
};
template <>
class TraceResolverImpl<system_tag::darwin_tag> : public TraceResolverDarwinImpl<trace_resolver_tag::current>
template <> class TraceResolverImpl<system_tag::darwin_tag> : public TraceResolverDarwinImpl<trace_resolver_tag::current>
{
};
@@ -3712,8 +3700,7 @@ public:
EnumProcessModules(process, &module_handles[0], module_handles.size() * sizeof(HMODULE), &cbNeeded);
module_handles.resize(cbNeeded / sizeof(HMODULE));
EnumProcessModules(process, &module_handles[0], module_handles.size() * sizeof(HMODULE), &cbNeeded);
std::transform(module_handles.begin(), module_handles.end(), std::back_inserter(modules),
get_mod_info(process));
std::transform(module_handles.begin(), module_handles.end(), std::back_inserter(modules), get_mod_info(process));
void* base = modules[0].base_address;
IMAGE_NT_HEADERS* h = ImageNtHeader(base);
image_type = h->FileHeader.Machine;
@@ -3742,9 +3729,8 @@ public:
char* lpMsgBuf;
DWORD dw = GetLastError();
if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&lpMsgBuf, 0, NULL)) {
if (FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&lpMsgBuf, 0, NULL)) {
std::fprintf(stderr, "%s\n", lpMsgBuf);
LocalFree(lpMsgBuf);
}
@@ -3959,8 +3945,8 @@ public:
return src_file.get_lines(start, context_size);
}
lines_t get_combined_snippet(const std::string& filename_a, unsigned line_a, const std::string& filename_b,
unsigned line_b, unsigned context_size)
lines_t get_combined_snippet(const std::string& filename_a, unsigned line_a, const std::string& filename_b, unsigned line_b,
unsigned context_size)
{
SourceFile& src_file_a = get_src_file(filename_a);
SourceFile& src_file_b = get_src_file(filename_b);
@@ -4007,11 +3993,7 @@ private:
/*************** PRINTER ***************/
namespace ColorMode {
enum type {
automatic,
never,
always
};
enum type { automatic, never, always };
} // namespace ColorMode
class cfile_streambuf : public std::streambuf
@@ -4055,11 +4037,7 @@ private:
#ifdef BACKWARD_SYSTEM_LINUX
namespace Color {
enum type {
yellow = 33,
purple = 35,
reset = 39
};
enum type { yellow = 33, purple = 35, reset = 39 };
} // namespace Color
class Colorize
@@ -4111,11 +4089,7 @@ private:
#else // ndef BACKWARD_SYSTEM_LINUX
namespace Color {
enum type {
yellow = 0,
purple = 0,
reset = 0
};
enum type { yellow = 0, purple = 0, reset = 0 };
} // namespace Color
class Colorize
@@ -4148,11 +4122,7 @@ public:
int trace_context_size;
Printer()
: snippet(true),
color_mode(ColorMode::automatic),
address(false),
object(false),
inliner_context_size(5),
: snippet(true), color_mode(ColorMode::automatic), address(false), object(false), inliner_context_size(5),
trace_context_size(7)
{
}
@@ -4211,8 +4181,7 @@ private:
}
}
template <typename IT>
void print_stacktrace(IT begin, IT end, std::ostream& os, size_t thread_id, Colorize& colorize)
template <typename IT> void print_stacktrace(IT begin, IT end, std::ostream& os, size_t thread_id, Colorize& colorize)
{
print_header(os, thread_id);
for (; begin != end; ++begin) {
@@ -4235,8 +4204,7 @@ private:
bool already_indented = true;
if (!trace.source.filename.size() || object) {
os << " Object \"" << trace.object_filename << "\", at " << trace.addr << ", in " << trace.object_function
<< "\n";
os << " Object \"" << trace.object_filename << "\", at " << trace.addr << ", in " << trace.object_function << "\n";
already_indented = false;
}
@@ -4263,14 +4231,13 @@ private:
}
}
void print_snippet(std::ostream& os, const char* indent, const ResolvedTrace::SourceLoc& source_loc,
Colorize& colorize, Color::type color_code, int context_size)
void print_snippet(std::ostream& os, const char* indent, const ResolvedTrace::SourceLoc& source_loc, Colorize& colorize,
Color::type color_code, int context_size)
{
using namespace std;
typedef SnippetFactory::lines_t lines_t;
lines_t lines =
_snippets.get_snippet(source_loc.filename, source_loc.line, static_cast<unsigned>(context_size));
lines_t lines = _snippets.get_snippet(source_loc.filename, source_loc.line, static_cast<unsigned>(context_size));
for (lines_t::const_iterator it = lines.begin(); it != lines.end(); ++it) {
if (it->first == source_loc.line) {
@@ -4286,11 +4253,9 @@ private:
}
}
void print_source_loc(std::ostream& os, const char* indent, const ResolvedTrace::SourceLoc& source_loc,
void* addr = nullptr)
void print_source_loc(std::ostream& os, const char* indent, const ResolvedTrace::SourceLoc& source_loc, void* addr = nullptr)
{
os << indent << "Source \"" << source_loc.filename << "\", line " << source_loc.line << ", in "
<< source_loc.function;
os << indent << "Source \"" << source_loc.filename << "\", line " << source_loc.line << ", in " << source_loc.function;
if (address && addr != nullptr) {
os << " [" << addr << "]";
@@ -4484,9 +4449,9 @@ private:
class SignalHandling
{
private:
static inline std::function<std::string()> crash_path_getter_ = nullptr;
static inline std::function<void(EXCEPTION_POINTERS* info)> crash_use_handler_ = nullptr;
static inline std::function<void(int sig)> user_sig_handler_ = nullptr;
static std::function<std::string()> crash_path_getter_;
static std::function<void(EXCEPTION_POINTERS* info)> crash_use_handler_;
static std::function<void(int sig)> user_sig_handler_;
public:
static void register_crash_path(std::function<std::string()>&& crash_path_getter)
@@ -4562,12 +4527,7 @@ private:
return &data;
}
enum class crash_status {
running,
crashed,
normal_exit,
ending
};
enum class crash_status { running, crashed, normal_exit, ending };
static crash_status& crashed()
{
@@ -4637,8 +4597,7 @@ private:
}
}
static inline void __cdecl invalid_parameter_handler(const wchar_t*, const wchar_t*, const wchar_t*, unsigned int,
uintptr_t)
static inline void __cdecl invalid_parameter_handler(const wchar_t*, const wchar_t*, const wchar_t*, unsigned int, uintptr_t)
{
crash_handler(signal_skip_recs);
abort();

View File

@@ -8,6 +8,12 @@
#include <QFileInfo>
#include <QStandardPaths>
#include "backward.hpp"
std::function<std::string()> backward::SignalHandling::crash_path_getter_ = nullptr;
std::function<void(EXCEPTION_POINTERS* info)> backward::SignalHandling::crash_use_handler_ = nullptr;
std::function<void(int sig)> backward::SignalHandling::user_sig_handler_ = nullptr;
namespace backward {
class crashHelper
@@ -126,8 +132,7 @@ void UseExceptionHandler(EXCEPTION_POINTERS* exception)
QString fullPath = QDir(h.dumpSavePath_).absoluteFilePath(dumpName);
QString fullFailedPath = QDir(h.dumpSavePath_).absoluteFilePath(dumpFailedLog);
HANDLE hFile =
CreateFile(fullPath.toStdWString().c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE hFile = CreateFile(fullPath.toStdString().c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
QFile file(fullFailedPath);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {