You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
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{returnfalse}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.
Summary
The
writeAllpattern used in bound-stream-pair writers treatsOutputStream.write(_:maxLength:)returning0as a fatal error. Apple's documentation defines a0return as "a fixed-length stream has reached its capacity." It is unclear whether a bound stream pair (fromStream.getBoundStreams(withBufferSize:)) qualifies as a "fixed-length stream," meaningwrite()could return0when the internal buffer is full rather than blocking.If
0is returned as a backpressure signal, the current code silently aborts the write, closes the stream, and leavesURLSessionwaiting forContent-Lengthbytes that never arrive — causing the upload to hang.Locations
RequestBody.makePipedFileSliceStream—ios/Sources/GutenbergKitHTTP/RequestBody.swift(~line 236)DefaultMediaUploader.writeAll—ios/Sources/GutenbergKit/Sources/Media/MediaUploadServer.swift(introduced in fix: improve upload server error handling and memory efficiency #419, same pattern)Both use:
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"Suggested fix
Distinguish
0(retry) from-1(error):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.