diff --git a/.changes/next-release/bugfix-s3-3139.json b/.changes/next-release/bugfix-s3-3139.json new file mode 100644 index 000000000000..b9fb26324e7e --- /dev/null +++ b/.changes/next-release/bugfix-s3-3139.json @@ -0,0 +1,5 @@ +{ + "type": "bugfix", + "category": "``s3``", + "description": "Fixes a race condition where CreateSession is called multiple times across different threads during an S3-Express recursive upload/download." +} diff --git a/awscli/botocore/utils.py b/awscli/botocore/utils.py index a3ac03e745e8..8915354cc3b8 100644 --- a/awscli/botocore/utils.py +++ b/awscli/botocore/utils.py @@ -25,6 +25,7 @@ import secrets import socket import string +import threading import time import uuid import warnings @@ -1483,11 +1484,16 @@ class S3ExpressIdentityCache(IdentityCache): def __init__(self, client, credential_cls): self._client = client self._credential_cls = credential_cls + self._lock = threading.Lock() @functools.lru_cache(maxsize=100) - def get_credentials(self, bucket): + def _get_credentials_cached(self, bucket): return super().get_credentials(bucket=bucket) + def get_credentials(self, bucket): + with self._lock: + return self._get_credentials_cached(bucket) + def build_refresh_callback(self, bucket): def refresher(): response = self._client.create_session(Bucket=bucket)