Skip to content

fix(dfm-mount): stop GMountOperation signal emission to prevent premature UNHANDLED reply - #389

Merged
deepin-bot[bot] merged 1 commit into
linuxdeepin:develop/meagle-20260526from
pppanghu77:fix/sftp-mount-password-dialog-cancelled
Sep 8, 2026
Merged

deepin-bot[bot] merged 1 commit into
linuxdeepin:develop/meagle-20260526from
pppanghu77:fix/sftp-mount-password-dialog-cancelled

Conversation

@pppanghu77

@pppanghu77 pppanghu77 commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

问题现象

首次登录挂载 SFTP 时,在主机密钥确认框点击「仍然登录」后,挂载失败并弹窗提示:挂载失败,密码对话框被取消(gvfs: "Password dialog cancelled"),用户实际从未取消任何对话框。低性能/界面繁忙环境(如 FT-D2000)上稳定复现。

根因

gio 的 GMountOperation 默认类处理器(G_SIGNAL_RUN_LAST)会在实例处理器返回后,通过 idle(G_PRIORITY_DEFAULT_IDLE)异步回复 G_MOUNT_OPERATION_UNHANDLED(glib/gio/gmountoperation.c reply_non_handled_in_idle)。

首次登录 SFTP 的完整触发链:

  1. gvfs sftp 后端先发 ask-question(主机密钥确认)。dfm-mount 应答 HANDLED 后,gio 默认处理器仍会调度上述 UNHANDLED 残留 idle;
  2. gvfs 接着发 AskPassword DBus 调用。若客户端主循环繁忙(idle 被饿死),该 DBus 派发(G_PRIORITY_DEFAULT)会先于残留 idle 执行,弹出密码对话框(嵌套事件循环);
  3. 残留 idle 在对话框的嵌套循环中触发 → g_mount_operation_reply(op, UNHANDLED) 命中此刻已连接的临时 reply 处理器(gmountoperationdbus.c)→ 挂载操作以 handled=FALSE 被提前作答;
  4. gvfs 侧 aborted=TRUEG_IO_ERROR_FAILED_HANDLED + "Password dialog cancelled"。

只有首次登录才有主机密钥询问(残留 idle 的唯一来源),与缺陷「前置条件:未登录过 sftp」完全吻合。

修复

mountByGvfsAskQuestion / mountByGvfsAskPasswd 入口调用 g_signal_stop_emission_by_name(),与 gvfs 官方客户端实现(gmountsource.c op_ask_password/op_ask_question)做法一致。两个处理器的所有返回路径均已显式调用 g_mount_operation_reply(HANDLED/ABORTED),停止默认处理器不会留下未应答的 DBus 调用;对 SMB/FTP 非首次登录流程无行为影响。

验证

最小 gio 复现程序(本机 UOS 20 + gvfs 1.38 + glib 2.58.3,paramiko 模拟 SFTP 服务器)三组对照:

模式 条件 结果
plain 立即应答(对照) 挂载成功
busy 模拟界面繁忙 + 密码对话框嵌套事件循环 失败,报「密码对话框被取消」(G_IO_ERROR_FAILED_HANDLED=30),与缺陷一致
fixed 同 busy + stop_emission 挂载成功

Log: 修复首次登录挂载sftp点击仍然登录后提示挂载失败密码对话框被取消
Influence: sftp/ftp/smb 挂载过程中密码与主机密钥确认对话框交互不再被 gio 默认处理器竞态打断

Summary by Sourcery

Prevent GIO mount-operation signal races from prematurely aborting interactive SFTP mounts.

Bug Fixes:

  • Prevent premature GMountOperation replies from causing first-time SFTP mounts to fail with a misleading “Password dialog cancelled” error.
  • Ensure host-key and password prompts are not interrupted by stale GIO default signal handling during nested event-loop activity.

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

@sourcery-ai

sourcery-ai Bot commented Sep 8, 2026

Copy link
Copy Markdown
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

The PR fixes a GLib signal-handler race in GVFS mounting by stopping the default ask-question and ask-password emissions, ensuring custom handlers explicitly reply and preventing stale UNHANDLED responses from prematurely aborting first-time SFTP mounts.

File-Level Changes

Change Details Files
Stop GLib’s default GMountOperation handlers from scheduling stale UNHANDLED replies during question and password prompts.
  • Stop emission of the ask-question signal before custom handling.
  • Stop emission of the ask-password signal before custom handling.
  • Retain explicit HANDLED/ABORTED replies on all custom-handler paths to ensure each DBus request is answered.
src/dfm-mount/private/dnetworkmounter.cpp
Prevent a first-time SFTP host-key prompt race from being misreported as password-dialog cancellation.
  • Avoid residual idle callbacks completing the mount operation inside the password dialog’s nested event loop.
  • Preserve expected behavior for SFTP, FTP, and SMB authentication and confirmation flows.
src/dfm-mount/private/dnetworkmounter.cpp

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 reviewed your changes and they look great!


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

…ture UNHANDLED reply

Root cause: gio's GMountOperation default class handlers (G_SIGNAL_RUN_LAST)
schedule an idle reply of G_MOUNT_OPERATION_UNHANDLED after instance handlers
return. On first-time SFTP login, gvfs sends ask-question (host key) followed
by ask-password. The stale UNHANDLED idle queued by the question stage may
still be pending when the AskPassword DBus call is dispatched (priority race:
G_PRIORITY_DEFAULT dispatch vs G_PRIORITY_DEFAULT_IDLE idle); it then fires
inside the modal password dialog's nested event loop, completes the pending
AskPassword invocation as handled=FALSE, and gvfs fails the mount with
"Password dialog cancelled" (密码对话框被取消) — reproducible when the UI is
busy/event-starved on the password dialog, exactly matching the reported
first-login SFTP mount failure.

Fix: call g_signal_stop_emission_by_name() in both mountByGvfsAskQuestion and
mountByGvfsAskPasswd, same as gvfs' own client implementation (gmountsource.c
op_ask_password/op_ask_question). All reply paths already call
g_mount_operation_reply explicitly, so stopping the default handler is safe.

Verified with a minimal gio reproducer against a local SFTP server:
- busy mode (stale idle + nested dialog loop): mount fails with
  "密码对话框被取消" (G_IO_ERROR_FAILED_HANDLED) before the fix
- with stop_emission: mount succeeds under identical conditions

Log: 修复首次登录挂载sftp点击仍然登录后提示挂载失败密码对话框被取消
Influence: sftp/ftp/smb 挂载过程中密码与主机密钥确认对话框交互不再被 gio 默认处理器竞态打断
Bug: https://pms.uniontech.com/bug-view-376305.html
Change-Id: I1f9e2d6c4b7a48e3952f0a1d8e6c5b3a7f2d4e8c
@pppanghu77
pppanghu77 force-pushed the fix/sftp-mount-password-dialog-cancelled branch from 12c96dd to a7e3350 Compare September 8, 2026 05:57
@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: Johnson-zs, pppanghu77

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

@pppanghu77

Copy link
Copy Markdown
Contributor Author

/merge

@deepin-bot
deepin-bot Bot merged commit 8081779 into linuxdeepin:develop/meagle-20260526 Sep 8, 2026
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