iOS: OutputStream.write return value 0 treated as fatal in bound stream writers

未关闭
#437 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

还没有人认领这个 Issue。

评估

难度
3/5
预计耗时
1-2 天
新手友好度
68/100
Issue 类型
缺陷
描述清晰度
基本清楚
活跃度
冷清
技术栈
swift
领域
mobile

调研方向

从 ios/Sources/GutenbergKitHTTP/RequestBody.swift 中的 RequestBody.makePipedFileSliceStream 和 ios/Sources/GutenbergKit/Sources/Media/MediaUploadServer.swift 中的 DefaultMediaUploader.writeAll 开始。阅读两者如何处理 OutputStream.write(_:maxLength:) 的结果,然后验证返回值为 0 时不会中止上传,而返回值为负数时仍会中止上传。完成标准是,两个绑定流 writer 都能一致地处理文档中说明的返回情况,并且不会让 URLSession 一直等待字节。

由索引模型根据 Issue 内容生成。

描述

Bug iOS

Summary

The writeAll pattern used in bound-stream-pair writers treats OutputStream.write(_:maxLength:) returning 0 as a fatal error. Apple's documentation defines a 0 return as "a fixed-length stream has reached its capacity." It is unclear whether a bound stream pair (from Stream.getBoundStreams(withBufferSize:)) qualifies as a "fixed-length stream," meaning write() could return 0 when the internal buffer is full rather than blocking.

If 0 is returned as a backpressure signal, the current code silently aborts the write, closes the stream, and leaves URLSession waiting for Content-Length bytes that never arrive — causing the upload to hang.

Locations

  1. RequestBody.makePipedFileSliceStream — ios/Sources/GutenbergKitHTTP/RequestBody.swift (~line 236)
  2. DefaultMediaUploader.writeAll — ios/Sources/GutenbergKit/Sources/Media/MediaUploadServer.swift (introduced in #419, same pattern)

Both use:

let result = output.write(base.advanced(by: written), maxLength: ...)
if result <= 0 { return }

Apple documentation

  • OutputStream.write(_:maxLength:): returns 0 for "a fixed-length stream that has reached its capacity"
  • CFWriteStreamWrite: "If the stream is not full, this call blocks until at least one byte is written"
  • Neither document explicitly states whether bound stream pairs block or return 0 when the buffer is full

Suggested fix

Distinguish 0 (retry) from -1 (error):

if result == -1 { return false }
if result == 0 {
    Thread.sleep(forTimeInterval: 0.001)
    continue
}

Risk

Low probability in practice — uploads would need to outpace URLSession's read rate long enough to fill the 65KB buffer. More likely with large files on slow connections.

主要语言
JavaScript
星标
29
派生
7
平均合并
2 天 10 小时
30 天内合并 PR
83

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

wordpress-mobile/GutenbergKit 的其他 Issue

查看 wordpress-mobile/GutenbergKit 的全部 Issue

相似的 Issue

更多 JavaScript Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。