Repository navigation
Replies: 1 comment 1 reply
|
机制、边界常量、终止条件我都核过了,你说的都对。但有一条施工信息你没有、而且会直接决定 PR 能不能过,另有一处论证需要收窄。 1. ⭐「走到根」不是疏漏,是被测试逐目录断言的有意设计这是最要紧的一条。 it.skipIf(process.platform === 'win32')('syncs every object ancestor up to the durable boundary before returning', async () => {
// Each process first proves DSH_HOME durable all the way to the filesystem root;
// existence alone cannot vouch for a concurrent creator's fsync.
expect(fsControl.syncedDirectories).toEqual([ ...parentChainToRoot(base), ... ])
⇒ 任何「不要走到根」的改动必须同步改这条期望数组,否则 CI 立即红。 而且注释里写了理由(「existence alone cannot vouch for a concurrent creator's fsync」),所以你的修复说明必须回应这个跨进程并发契约,否则会被当成削弱语义驳回。 2. 只有一条调用点会越过 DSH_HOME(所以你的"窄改法"确实更安全)
3. 你的修复论证需要收窄一处你写的是:
后半句不成立。 Android 的 另外一并吞 4. 两处小澄清
5. 会话侧为什么不受影响 —— 你的不对称解释成立
建议采纳你的
如果你倾向更保守的窄方案(让 |
Uh oh!
There was an error while loading. Please reload this page.
What happens
With dsh running inside an Android app sandbox (
DSH_HOMEunder/data/user/0/<package>/), attaching an image always fails. The prompt is rejected and the reason is:Sending text is never affected. Only attachments fail, and they fail every time, on every device.
Why
packages/attachment/attachment-local/src/store.ts:ensureDurableDirectorywalks fromhomeup to that boundary callingsyncDirectory(parent)at every level, andsyncDirectoryopens the directory withO_RDONLYin order to fsync it.With
DSH_HOME = /data/user/0/<pkg>/dsh-homethe walk is:On Android
/data/user/0isdrwxrwx--x system system. An ordinary app lands in the "other" bits: execute, so it can traverse, but no read. Opening a directory read-only requires read permission, so this is an unconditional failure rather than a misconfiguration — no ROM or Android version makes it work.Session persistence is unaffected because it only fsyncs explicit single-level paths that top out at
DSH_HOMEand never walks upward. That asymmetry is why "send a message" works while "send an image" has never worked.Reproduced
Redmi 23113RKC6C, Android 16, arm64, published dsh tree run by an Android app that bundles Node 24. Reproduced on
0.1.5-rc.2and0.2.0-rc.2; the code is identical in both, and still the same onmasteratdsh-v0.2.1-alpha.1.Both attachment entry points reach it — the composer's file input and a paste into the composer.
Not Android-specific in principle
Any environment where some ancestor of
DSH_HOMEis not readable by the process hits the same wall: a restrictive container mount, a hardened multi-user setup, aDSH_HOMEunder a directory owned by someone else. Android only makes it unconditional.Suggested fix
Treat "this process cannot open the ancestor" as "this ancestor is not ours to sync":
This keeps the contract the comment on
ensureDurableDirectorydescribes. Creating an entry in a directory requires write+execute on it, so a directory the process cannot even open read-only is one it cannot have written to; there is no unsynced entry of ours to lose. Every directory the process did create stays inside the sandbox and is still fsynced exactly as before.If you would rather not loosen
syncDirectoryfor all four of its call sites, the narrower alternative is to stop theensureDurableHomewalk at the first ancestor that cannot be opened instead of atparse(home).root.Verified
Applied as a build-time patch over the published tree and run on the device above: attachment ingest returns its sha256 reference, the object lands in
DSH_HOME/attachments/v1/objects/<xx>/<hash>, the image reaches the provider, and the turn completes. The same build with the stock code reproduces the EACCES every time.All reactions