Skip to content

fix: cache kern log file paths to avoid second auth dialog on refresh - #529

Open
max-lvs wants to merge 1 commit into
linuxdeepin:release/eaglefrom
max-lvs:agent/pms-bug-bot/39e88ce1eee8
Open

max-lvs wants to merge 1 commit into
linuxdeepin:release/eaglefrom
max-lvs:agent/pms-bug-bot/39e88ce1eee8

Conversation

@max-lvs

@max-lvs max-lvs commented Sep 20, 2026 •

Copy link
Copy Markdown

Root Cause Analysis

When a user clears (truncates) kernel logs, the refresh flow calls ParseThreadKern::handleKern() which invokes getFileInfo("kern", false) via DBus. getFileInfo requires com.deepin.pkexec.logViewerAuth polkit authorization, while truncate uses a different action ID (com.deepin.pkexec.logViewerTruncate). Since polkit auth_admin_keep is maintained per action ID, the truncate authorization does not cover the read authorization. When the logViewerAuth keep has expired, a second auth dialog is triggered; the user does not expect it, and the silent parseFinished(CancelAuth) causes the refresh to fail — the log list shows stale data until the user switches modules and returns.

Key evidence: application/parsethread/parsethreadkern.cpp:44 calls getFileInfo on every refresh; logViewerService/logviewerservice.cpp:807 gates getFileInfo behind checkAuth(s_Action_View); the two polkit policy files use distinct action IDs.

Fix Approach

Cache the kernel log file paths obtained from the first getFileInfo call in LogBackend::m_kernFilePaths. On subsequent loads (e.g. refresh after truncate), reuse the cached paths instead of calling getFileInfo again, avoiding the second polkit auth dialog. Truncate only empties file content — the file paths remain valid, so reusing cached paths is safe.

Change Safety Assessment

Code Safety

  • Risk Level: Low
  • The target code was introduced in commit c46e491 (PMS 244067, segment loading optimization) and later refined by 3ef0022 (PMS 292033, skip getFileInfo on first entry). This change builds on that direction — reducing unnecessary getFileInfo calls — and does not revert any historical fix.
  • No function signatures are modified; no public members are removed; only KERN type logic is affected. All four affected callers remain compatible with the added conditional branch.

Business Impact Scope

  • Kernel log viewing: first load, refresh after truncate, pagination, and search remain functional. First load still calls getFileInfo (populating the cache); subsequent loads reuse cached paths.
  • Kernel log clearing (truncate): after clearing, the log list refreshes immediately without a second auth dialog.
  • Non-KERN log types (system, boot, dmesg, etc.) are unaffected.

Verification Suggestion

  • Verify kernel log first load shows normal auth dialog and correct data.
  • Verify truncate followed by immediate refresh — no second auth dialog, list updates correctly.
  • Verify kernel log pagination and module switching still work.

根因分析

用户清除内核日志后,刷新流程中 ParseThreadKern::handleKern() 调用 getFileInfo("kern", false) 走 DBus 到 LogViewerService::getFileInfo,后者要求 com.deepin.pkexec.logViewerAuth 鉴权。而清除日志使用不同的 polkit action ID(com.deepin.pkexec.logViewerTruncate),polkit auth_admin_keep 按动作独立保持,truncate 鉴权不覆盖读取鉴权。当 logViewerAuth 的 keep 已过期时,getFileInfo 触发第二个鉴权对话框,用户不预期该对话框,parseFinished(CancelAuth) 静默发出,刷新失败——日志列表显示旧数据,直到用户切换模块再返回才刷新。

关键证据:application/parsethread/parsethreadkern.cpp:44 每次刷新都调用 getFileInfo;logViewerService/logviewerservice.cpp:807 中 getFileInfo 被 checkAuth(s_Action_View) 门控;两个 polkit policy 文件使用不同的 action ID。

修复方案

在 LogBackend::m_kernFilePaths 中缓存首次 getFileInfo 调用获取的内核日志文件路径。后续刷新(如 truncate 后)复用缓存路径,不再调用 getFileInfo,从而避免触发二次 polkit 鉴权。truncate 仅截断文件内容不改变文件路径,复用缓存路径安全。

改动安全评估

代码安全评估

  • 风险等级: 低风险
  • 目标代码由 c46e491(PMS 244067,分段加载优化)引入,后经 3ef0022(PMS 292033,首次进入跳过 getFileInfo)优化。本次修复延续减少不必要 getFileInfo 调用的方向,不撤销任何历史修复。
  • 不修改函数签名、不删除公开成员,仅影响 KERN 类型逻辑。四个受影响调用者均与新增条件分支兼容。

业务影响范围

  • 内核日志查看:首次加载、truncate 后刷新、分段翻页、搜索均正常。首次加载仍调用 getFileInfo(填充缓存),后续加载复用缓存路径。
  • 内核日志清除(truncate):清除后日志列表立即刷新,不弹出二次鉴权框。
  • 非 KERN 类型日志(系统、启动、dmesg 等)不受影响。

验证建议

  • 验证内核日志首次加载正常弹出鉴权框且数据正确。
  • 验证 truncate 后立即刷新——无二次鉴权框,列表正确更新。
  • 验证内核日志分段翻页和模块切换仍正常。

Log: avoid second auth dialog when refreshing kern log after truncate
Bug: https://pms.uniontech.com/bug-view-254665.html

Summary by Sourcery

Avoid repeated kernel-log authorization prompts by coordinating truncation refreshes with cache invalidation and cached path reuse.

Bug Fixes:

  • Prevent repeated authorization prompts and stale kernel log data when refreshing after truncation.
  • Refresh kernel logs with invalidated caches after truncation so updated line counts and file paths are used.

Enhancements:

  • Cache kernel log file paths and total line counts for reuse during pagination, refresh, and search while preserving normal initial authorization behavior.

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: max-lvs

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

@sourcery-ai

sourcery-ai Bot commented Sep 20, 2026

Copy link
Copy Markdown

Reviewer's Guide

This change prevents a second polkit authorization dialog after kernel-log truncation by caching file paths from the first authorized lookup and reusing them across KERN refresh, pagination, and parsing flows; non-KERN log handling is unchanged.

Sequence diagram for cached kernel log refresh after truncation

sequenceDiagram
    actor User
    participant Backend as LogBackend
    participant DBus as DLDBusHandler
    participant Service as LogViewerService
    participant Parser as ParseThreadKern

    User->>Backend: truncate and refresh KERN logs
    Backend->>Backend: loadSegementPage()
    alt cached kernel paths available
        Backend->>Parser: parse(LOG_FILTER_BASE with cachedFilePaths)
        Parser->>Parser: handleKern()
        Parser->>Parser: reuse cachedFilePaths
    else first KERN load
        Backend->>DBus: getFileInfo(kern, false)
        DBus->>Service: getFileInfo()
        Service-->>DBus: authorized file paths
        DBus-->>Backend: file paths
        Backend->>Parser: parse(LOG_FILTER_BASE with cachedFilePaths)
        Parser->>Parser: handleKern()
    end
    Parser->>DBus: getLineCount(file)
    DBus-->>Parser: line counts
    Parser-->>User: refreshed kernel log list
Loading

File-Level Changes

Change Details Files
Cache kernel log paths and propagate them through segment loading so refreshes reuse the original paths instead of reauthorizing via DBus.
  • Add backend storage for cached KERN file paths.
  • Populate cached paths on the initial file-info lookup and reuse them when calculating segment counts.
  • Attach cached paths to KERN filters during segment-page loads.
  • Make the KERN parser prefer cached paths while preserving authorization-error handling for initial lookups.
application/logbackend.cpp
application/logbackend.h
application/parsethread/parsethreadkern.cpp
application/structdef.h

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="application/logbackend.cpp" line_range="1997-1999" />
<code_context>
     }

     m_type2Filter[m_flag].segementIndex = nSegementIndex;
+    if (m_flag == KERN && !m_kernFilePaths.isEmpty()) {
+        m_type2Filter[m_flag].cachedFilePaths = m_kernFilePaths;
+    }
     parse(m_type2Filter[m_flag]);

</code_context>
<issue_to_address>
**issue (bug_risk):** The cache is never invalidated or refreshed after it becomes non-empty, while `getFileInfo("kern", false)` dynamically scans `/var/log` and returns the current rotated kernel-log files. After log rotation removes or replaces a cached file, pagination or refresh uses the stale paths; `ParseThreadKern::handleKern()` then finds a missing path and finishes without producing data, leaving the kernel list empty or stale.

**Triggers:** When kernel log rotation or another filesystem change occurs after the cache is populated.

**Suggested fix:** Invalidate or refresh `m_kernFilePaths` when kernel log files rotate or disappear, and fall back to `getFileInfo` when a cached path no longer exists.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment on lines +1997 to +1999
if (m_flag == KERN && !m_kernFilePaths.isEmpty()) {
m_type2Filter[m_flag].cachedFilePaths = m_kernFilePaths;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): The cache is never invalidated or refreshed after it becomes non-empty, while getFileInfo("kern", false) dynamically scans /var/log and returns the current rotated kernel-log files. After log rotation removes or replaces a cached file, pagination or refresh uses the stale paths; ParseThreadKern::handleKern() then finds a missing path and finishes without producing data, leaving the kernel list empty or stale.

Triggers: When kernel log rotation or another filesystem change occurs after the cache is populated.

Suggested fix: Invalidate or refresh m_kernFilePaths when kernel log files rotate or disappear, and fall back to getFileInfo when a cached path no longer exists.

…ation

Cache the kernel log file paths and total line count from the first
getFileInfo call in LogBackend. On subsequent loads (e.g. refresh after
truncate), reuse the cached values instead of calling getFileInfo again,
which triggers a second polkit auth dialog with a different action ID.

However, the cached m_kernTotalLineCount and m_kernFilePaths were never
invalidated after truncation. When the kernel log is truncated and
refreshed, m_kernTotalLineCount retains the pre-truncation line count,
causing m_segementCount to be too high. Pagination then reuses the stale
count to decide there are more pages, triggering empty-page cascade
loading (each involving pkexec logViewerAuth process spawn and DBus
calls), causing noticeable lag and incorrect page indicators.

Fix: add LogBackend::invalidateKernCache() that resets
m_kernTotalLineCount to -1 and clears m_kernFilePaths. Call it in the
truncate-refresh flow via a new sigTruncateRefresh signal / slot_truncateRefresh
slot, NOT in clearAllFilter() (normal refresh depends on m_kernFilePaths
to skip getFileInfo auth).

Changes:
- Add cachedFilePaths field to LOG_FILTER_BASE struct (structdef.h)
- Add m_kernFilePaths and m_kernTotalLineCount cache members to LogBackend
  (logbackend.h)
- Add LogBackend::invalidateKernCache() to reset kern cache (logbackend.h/.cpp)
- LogBackend::getNextSegementIndex: populate cache on first call, reuse
  on subsequent calls; fix const ref iteration (logbackend.cpp)
- LogBackend::loadSegementPage: inject cached paths into filter for
  KERN type before parse() (logbackend.cpp)
- ParseThreadKern::handleKern: use cachedFilePaths from filter when
  available, skip getFileInfo call (parsethreadkern.cpp)
- Add sigTruncateRefresh signal to LogListView, emit after truncateFile
  (loglistview.h/.cpp)
- Add slot_truncateRefresh to DisplayContent: invalidateKernCache then
  slot_refreshClicked (displaycontent.h/.cpp)
- Connect sigTruncateRefresh in LogCollectorMain (logcollectormain.cpp)

Log: avoid second auth dialog when refreshing kern log after truncate
Bug: https://pms.uniontech.com/bug-view-254665.html
@max-lvs
max-lvs force-pushed the agent/pms-bug-bot/39e88ce1eee8 branch from 28c4d6d to d8ad122 Compare October 5, 2026 15:31
@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

🤖 AI 代码审查报告

总体评分: 100 分 (通过阈值: 70分)

Pass


📊 总体评价

项目 结果
审查结论 代码审查通过
评分详情 总体评分 100 分,大于 70 分通过阈值。本次提交修复了内核日志刷新时的二次鉴权弹窗和截断后分页失效问题,缓存机制设计合理,代码质量优秀,无安全漏洞。

🔍 详细分析

1. 语法逻辑 ✅

评价: 优秀 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: 语法正确,逻辑清晰,边界处理完善。缓存机制设计合理,哨兵值-1正确标识未初始化状态;txtFilePaths为空时缓存保持未初始化,三元运算符正确返回0;信号槽连接匹配正确。


2. 代码质量 ✅

评价: 优秀 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: 代码结构清晰,注释完整。invalidateKernCache()方法有详细的Doxygen文档说明设计约束(不可在clearAllFilter中调用的原因);成员变量m_kernFilePaths和m_kernTotalLineCount有清晰的内联注释;const引用迭代改进(for (const auto &file : txtFilePaths))避免了不必要的QString拷贝。


3. 代码性能 ✅

评价: 优秀 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: 性能良好,资源使用合理。缓存机制显著减少了DBus调用(getFileInfo/getLineCount)和polkit鉴权进程开销;修复了空页级联加载导致的性能问题(每个空页都触发pkexec进程和DBus调用)。哨兵模式(-1)避免不必要的重复计算。


4. 代码安全 🔒

评价: 优秀 ✅ 通过

🔐 发现 0 个安全漏洞

安全漏洞详情:
✅ 未发现安全漏洞

建议: 无安全风险,安全合规。缓存仅存储文件路径和行数,不涉及敏感数据;DBus调用沿用既有安全模式;无用户输入处理变更,无注入风险。


💡 改进建议代码示例

// 本次提交为高质量的Bug修复,代码设计合理,无需改进
// 缓存机制:首次调用populate,后续复用,截断时invalidate
void LogBackend::invalidateKernCache()
{
    m_kernTotalLineCount = -1;
    m_kernFilePaths.clear();
}

本报告由 AI 代码审查工具自动生成

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.

2 participants