fix: add per-device internet connectivity check for network switching#557
Conversation
5c93bb9 to
e494d11
Compare
|
@deepin-ci-robot |
262463c to
381038c
Compare
Add InternetChecker module to detect and switch the primary network interface when the current one cannot access the internet. - Add InternetChecker class with switchInternetAccess() logic: traverse activated devices, check which ones can access internet, compare with current primary connection, and switch via never-default (updateUnsaved + reapplyConnection, not persisted to disk) - Subscribe to NetworkManager::primaryConnectionChanged signal, retry connectivity checks after switch to wait for DHCP/route settling - Reset all connections' never-default=false after successful switch or when all devices exhausted (via NetworkManager::Settings::listConnections + device active connections) - Add needCheckNetwork config option to enable/disable the feature - Integrate InternetChecker into LocalConnectionvityChecker, trigger on Limited/Noconnectivity/Unknownconnectivity states 增加检测单独网卡是否可以上网并自动切换网络的功能。 - 新增InternetChecker类,实现switchInternetAccess()逻辑:遍历所有已激活的网卡, 检测哪些网卡可以上网,与当前主连接网卡对比,若当前网卡不可上网则通过 never-default属性切换默认路由(使用updateUnsaved+reapplyConnection, 不持久化到磁盘) - 监听NetworkManager::primaryConnectionChanged信号,切换后重试检测网络连通性, 等待DHCP/路由生效 - 切换成功后或所有设备都尝试过以后,重置所有连接的never-default为false (通过NetworkManager::Settings::listConnections遍历所有已保存连接, 并补充设备当前激活的连接,确保不遗漏) - 新增needCheckNetwork配置项控制是否启用该功能 - 在LocalConnectionvityChecker中集成InternetChecker,在网络状态变为 Limited/Noconnectivity/Unknownconnectivity时触发检测和切换 PMS: BUG-351163
deepin pr auto review这份代码实现了一个网络自动切换功能:当检测到当前网络受限或无连接时,自动遍历其他可用的网络设备,修改其路由优先级( 整体逻辑清晰,但在线程安全、资源泄漏、阻塞调用以及平台兼容性等方面存在一些较严重的问题。以下是详细的审查意见: 1. 语法与逻辑问题1.1 if (m_tryIndex < m_tryDevices.size()) {
// ...
NetworkManager::Device::Ptr nextDevice = m_tryDevices.at(m_tryIndex);
// ...
m_tryIndex++;
}当 1.2 } else if (ret == EAI_AGAIN || ...) {
// ...
return reply; // 提前返回
} else {
// ...
return reply; // 提前返回
}
CURL *curl = curl_easy_init();如果 DNS 解析失败,函数会提前返回 2. 代码质量2.1 析构函数中的 m_statusChecker->deleteLater();
m_thread->deleteLater();
2.2 拼写错误 2.3 日志级别使用不当 qWarning() << "get primary device: " << primaryDevice->interfaceName();获取主设备是正常的业务逻辑,不应使用 3. 代码性能3.1 在工作线程中使用 for (int i = 0; i < maxRetry; ++i) {
QThread::sleep(1); // 阻塞线程1秒
// ...
}
3.2 同步 HTTP 请求阻塞 NetworkManager 线程 4. 代码安全4.1 严重: if (joinRet == ETIMEDOUT) {
pthread_detach(thread); // 脱离管理
return ETIMEDOUT;
}如果 DNS 请求卡死(例如路由器无响应,glibc 的
4.2 严重: 4.3 CURLcode curlRes = curl_easy_perform(curl);
// ... 处理结果 ...
if (resolveList)
curl_slist_free_all(resolveList);
curl_easy_cleanup(curl);
return reply;如果在 auto slist_deleter = [](curl_slist *s) { curl_slist_free_all(s); };
std::unique_ptr<curl_slist, decltype(slist_deleter)> resolveGuard(resolveList, slist_deleter);
auto curl_deleter = [](CURL *c) { curl_easy_cleanup(c); };
std::unique_ptr<CURL, decltype(curl_deleter)> curlGuard(curl, curl_deleter);4.4 IPv6 地址格式未做合规处理 if (result->ai_family == AF_INET6) {
// ...
resolvedIp = QString::fromLatin1(ipStr);
}
// ...
std::string resolveStr = host.toStdString() + ":" + std::to_string(port) + ":" + resolvedIp.toStdString();当解析到 IPv6 地址时, 总结与修改建议代码片段1. 修复析构函数内存泄漏: LocalConnectionvityChecker::~LocalConnectionvityChecker()
{
m_thread->quit();
m_thread->wait();
delete m_statusChecker; // 修改: deleteLater -> delete
delete m_thread; // 修改: deleteLater -> delete
if (m_internetCheckerThread) {
m_internetCheckerThread->quit();
m_internetCheckerThread->wait();
delete m_internetCheckerThread; // 修改: deleteLater -> delete
// m_internetChecker 已通过 finished 信号关联 deleteLater,
// 但由于线程已停止,事件循环不再运行,deleteLater 不会生效!
// 必须显式 delete
delete m_internetChecker;
}
}2. 优化 HTTP 请求的 RAII 管理: HttpReply *HttpManager::get(const QString &url, int timeoutSec)
{
HttpReply *reply = new HttpReply(this);
// ... DNS 解析部分 ...
CURL *curl = curl_easy_init();
if (!curl) {
// ...
return reply;
}
// 使用 RAII 确保 curl 资源释放
auto curl_deleter = [](CURL *c) { curl_easy_cleanup(c); };
std::unique_ptr<CURL, decltype(curl_deleter)> curlGuard(curl, curl_deleter);
curl_slist *resolveList = nullptr;
if (!resolvedIp.isEmpty()) {
std::string resolveStr = host.toStdString() + ":" + std::to_string(port) + ":" + resolvedIp.toStdString();
resolveList = curl_slist_append(nullptr, resolveStr.c_str());
curl_easy_setopt(curl, CURLOPT_RESOLVE, resolveList);
}
// 使用 RAII 确保 slist 资源释放
auto slist_deleter = [](curl_slist *s) { curl_slist_free_all(s); };
std::unique_ptr<curl_slist, decltype(slist_deleter)> resolveGuard(resolveList, slist_deleter);
// ... 设置 curl 参数并执行 ...
return reply; // 离开作用域自动清理 curl 和 resolveList
} |
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: mhduiy, ut003640 The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
|
/force |
|
/merge |
|
This pr cannot be merged! (status: unstable) |
|
/forcemerge |
|
This pr force merged! (status: unstable) |
Add InternetChecker module to detect and switch the primary network interface when the current one cannot access the internet.
增加检测单独网卡是否可以上网并自动切换网络的功能。
PMS: BUG-351163