vapor/vapor

Large, streamed request body may result in noSignalReceived preconditionFailure crash

daveanderson opened this issue · 6 comments

Describe the bug

When streaming a large (20+ MB) request body to a controller that writes it to a file on disk the Request.Body.AsyncSequenceDelegate method produceMore0() encounters a noSignalReceived case and the server exits with a preconditionFailure().

Having the server spontaneously exit in production is highly undesirable.

It's not completely clear why noSignalReceived is occurring, but experimentally replacing the preconditionFailure() with break appears to allow the server to wait for additional data to arrive from the client, allowing the remainder of the body to be received and stored.

Please consider adjusting the implementation of the Request.Body.AsyncSequenceDelegate method produceMore0() such that the server will not spontaneously terminate when streaming a large request body.

To Reproduce

Steps to reproduce the behavior:

  1. A route with configured with body: .stream
  2. A controller method that handles the 20+ MB streamed body using the for try await byteBuffer in body {} pattern.
  3. As the streamed bytes are received at some point the Request.Body.AsyncSequenceDelegate method produceMore0() encounters a noSignalReceived case and the server exits with a preconditionFailure().

Environment

  • Vapor Framework version: 4.92.2

Hmm if it's hitting https://github.com/vapor/vapor/blob/main/Sources/Vapor/Concurrency/RequestBody%2BConcurrency.swift#L34 then I don't think the latest release will help. It could be the same bug as #2985

(Wrong button!)

@0xTim This PR mentions it fixes this issue in the description: #2998

Vapor v4.92.3 does not resolve the produceMore0() preconditionFailure().

Also, this does appear to be a the same issue as #2985