Skip to content

fix: deduplicate low-battery notifications during upgrade retries#320

Merged
zhaohuiw42 merged 1 commit intolinuxdeepin:masterfrom
zhaohuiw42:master
Mar 4, 2026
Merged

fix: deduplicate low-battery notifications during upgrade retries#320
zhaohuiw42 merged 1 commit intolinuxdeepin:masterfrom
zhaohuiw42:master

Conversation

@zhaohuiw42
Copy link
Copy Markdown
Contributor

Do not remove power properties handler at job end, otherwise the single watcher can be detached and later flows may miss notifications.

Bug: https://pms.uniontech.com/bug-view-316659.html

Do not remove power properties handler at job end, otherwise the
single watcher can be detached and later flows may miss notifications.

Bug: https://pms.uniontech.com/bug-view-316659.html
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 4, 2026

CLA Assistant Lite bot:
提交邮箱中包含我们的合作伙伴,但您似乎并非合作伙伴的成员或对接人,请联系相关对接人将您添加至组织之中,或由其重新发起 Pull Request。
The commit email domain belongs to one of our partners, but it seems you are not yet a member of the current organization, please contact the contact person to add you to the organization or let them submit the Pull Request.

You can retrigger this bot by commenting recheck in this Pull Request

@deepin-ci-robot
Copy link
Copy Markdown

deepin pr auto review

这段代码的改动主要是为了优化电源状态监听逻辑,防止重复注册监听器。以下是对这段代码的详细审查和改进建议:

1. 代码逻辑审查

优点:

  • 使用 sync.Once (sysPowerWatchOnce) 确保电源监听器只被注册一次,这是一个很好的改进,避免了多次调用 handleSysPowerChanged 时重复注册监听器导致的资源浪费和潜在问题。
  • 使用卫语句 (if err != nil || !isLaptop { return }) 提前返回,减少了代码嵌套层级,提高了可读性。
  • 移除了未使用的导入 github.com/linuxdeepin/go-lib/dbusutil/proxy,保持了代码整洁。

潜在问题:

  • 变量作用域问题:在 sync.Once 的闭包中定义的 lowPowerNotifyIDonBatteryGlobalbatteryPercentage 等变量,其作用域仅限于该闭包。这意味着如果 handleSysPowerChanged 被多次调用(尽管 sync.Once 保证了闭包只执行一次),这些变量在闭包外部是不可见的。这可能是预期的行为,但需要确认。
  • 错误处理:在获取 onBatteryGlobalbatteryPercentage 时忽略了错误 (_, _ := ...)。如果这些获取失败,可能会导致后续逻辑基于错误的数据执行。

2. 代码质量审查

命名规范:

  • lowPowerNotifyId 改为 lowPowerNotifyID,符合 Go 的命名规范(缩略词应大写),这是一个好的改进。

代码结构:

  • handleSysPowerBatteryEvent 函数较长,可以考虑将其拆分为更小的函数,例如:
    • shouldShowLowPowerNotification():判断是否应该显示低电量通知。
    • showLowPowerNotification():显示低电量通知。
    • closeLowPowerNotification():关闭低电量通知。

3. 代码性能审查

  • 使用 sync.Once 避免了重复注册监听器,这是一个显著的性能优化。
  • handleSysPowerBatteryEvent 中,每次电池状态变化时都会启动一个新的 goroutine (go handleSysPowerBatteryEvent())。如果电池状态变化非常频繁,可能会导致 goroutine 数量过多。可以考虑使用一个单一的 goroutine 和 channel 来处理电池事件。

4. 代码安全审查

  • 并发安全handleSysPowerBatteryEvent 使用了互斥锁 (handleSysPowerBatteryEventMu) 来保护共享变量 (lowPowerNotifyIDonBatteryGlobalbatteryPercentage),这是正确的做法。
  • 资源泄漏:在 distUpgrade 函数中,移除了 m.sysPower.RemoveHandler(proxy.RemovePropertiesChangedHandler),这意味着监听器可能不会被显式移除。虽然这不是一个严重的问题(因为 sync.Once 保证了只注册一次),但最好在 Manager 销毁时清理所有监听器。

5. 改进建议

5.1 错误处理改进

onBatteryGlobal, err := m.sysPower.OnBattery().Get(0)
if err != nil {
    logger.Warning("failed to get OnBattery status:", err)
    onBatteryGlobal = false // 使用默认值
}

batteryPercentage, err := m.sysPower.BatteryPercentage().Get(0)
if err != nil {
    logger.Warning("failed to get BatteryPercentage:", err)
    batteryPercentage = 100.0 // 使用默认值
}

5.2 函数拆分

func (m *Manager) handleSysPowerBatteryEvent(lowPowerNotifyID *uint32, onBatteryGlobal *bool, batteryPercentage *float64, handleSysPowerBatteryEventMu *sync.Mutex) {
    handleSysPowerBatteryEventMu.Lock()
    defer handleSysPowerBatteryEventMu.Unlock()

    if m.shouldShowLowPowerNotification(*onBatteryGlobal, *batteryPercentage) {
        m.showLowPowerNotification(lowPowerNotifyID)
    }

    if !*onBatteryGlobal && *lowPowerNotifyID != 0 {
        m.closeLowPowerNotification(lowPowerNotifyID)
    }
}

func (m *Manager) shouldShowLowPowerNotification(onBatteryGlobal bool, batteryPercentage float64) bool {
    return onBatteryGlobal && batteryPercentage < 60.0 && m.statusManager.isUpgrading()
}

func (m *Manager) showLowPowerNotification(lowPowerNotifyID *uint32) {
    if *lowPowerNotifyID != 0 {
        return
    }
    msg := gettext.Tr("The battery capacity is lower than 60%. To get successful updates, please plug in.")
    *lowPowerNotifyID = m.sendNotify(updateNotifyShow, 0, "notification-battery_low", "", msg, nil, nil, system.NotifyExpireTimeoutNoHide)
}

func (m *Manager) closeLowPowerNotification(lowPowerNotifyID *uint32) {
    closeErr := m.closeNotify(*lowPowerNotifyID)
    if closeErr != nil {
        logger.Warning(closeErr)
    } else {
        *lowPowerNotifyID = 0
    }
}

5.3 资源清理

Manager 的清理方法中(如果有),添加对电源监听器的清理:

func (m *Manager) cleanup() {
    if m.sysPower != nil {
        // 移除所有监听器
        // 注意:需要确保 sysPower 提供了相应的方法
    }
    // 其他清理逻辑...
}

总结

这段代码的改动总体上是积极的,主要改进了电源监听器的注册逻辑,避免了重复注册。建议进一步改进错误处理和函数结构,以提高代码的健壮性和可维护性。

@deepin-ci-robot
Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: qiuzhiqian, zhaohuiw42

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@zhaohuiw42 zhaohuiw42 merged commit 1ba86bc into linuxdeepin:master Mar 4, 2026
15 of 17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants