Skip to content

S3 GetObjectCommand leaks sockets if the body is never read / add doc links for streaming responses re: socket exhaustion #6691

Open
@modelbitjason

Description

@modelbitjason

Checkboxes for prior research

Describe the bug

If you send a GetObjectCommand but only read the returned metadata and never read the body , the S3Client eventually runs out of sockets and gets stuck forever.

I realize the solution is to use HeadObjectCommand here, but it'd be nice to call this out in the docs someplace. The example for GetObjectCommand doesn't read the body and thus will lead to leaking connections.

Once the 50 sockets have been used, the S3Client object is dead and will never work again, even after the OS cleans up the stale sockets (By looking at netstat output).

Regression Issue

  • Select this option if this issue appears to be a regression.

SDK version number

3.637.0

Which JavaScript Runtime is this issue in?

Node.js

Details of the browser/Node.js/ReactNative version

v20.14.0

Reproduction Steps

const client = new S3Client({
      region: getEnv("DATA_REGION"),
      requestHandler: new NodeHttpHandler({ socketTimeout: 25000, connectionTimeout: 5000 }),
      maxAttempts: 3,
    })

for(let i=0;i<=50;i++){
  const s3objCmd = new GetObjectCommand({
    Bucket: awsBucket,
    Key: s3Key,
  })
  const s3resp = await client.send(s3objCmd)
  doSomethingWithMetadata(s3resp.Metadata)
}

Observed Behavior

Without a timeout the 51st GetObjectCommand hangs forever. With a timeout, you get an error after the socketTimeout triggers.

Expected Behavior

I expected to continue getting S3 objects or there to be a note in the documentation that I should always calls .Body() on the response to drain the socket.

I would expect the client itself to garbage collect sockets after the timeout or after the OS closes them.

I would also expect the client to throw an OutOfSockets error instead of hanging forever or hitting a connection timeout (When it won't ever connect because it is out of sockets)

Possible Solution

The easiest fix is a note in the documentation but I'd appreciate also a different error when out of sockets in the client.

I'm not sure about the expected behavior with regards to draining the socket -- It's nice that I found this typo because of the errors -- I don't want the body here and downloading in the background would be a waste of bytes.

But, it took a long time to figure out what was wrong because the inner workings of the SDK are not really clear. I don't see any examples re-using a client and wasn't sure if that was even allowed. It was only when I found the default maxSockets parameter on the client that everything fell into place.

Additional Information/Context

No response

Metadata

Metadata

Labels

documentationThis is a problem with documentation.p2This is a standard priority issuequeuedThis issues is on the AWS team's backlog

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions