Skip to content

Commit

Permalink
Use class instance to lock signing
Browse files Browse the repository at this point in the history
The `with threading.Lock()` statement does not actually lock
anything because we're creating a new lock each time.  The
fix here is to use an instance level lock.  We need to ensure that
the signer is not called in multiple threads as it is _not_ thread
safe.

This bug surfaces via S3 signature version 4 multithreaded uploads.
If you run "aws s3 cp/sync" in eu-central-1 or cn-north-1, you'll
see signature errors because the timestamp will be off be one or more
seconds.  Given this is a race condition, you'll need a fairly large
file (1GB to be safe) to see this issue.
  • Loading branch information
jamesls committed Feb 13, 2015
1 parent ae1293d commit d8ced45
Showing 1 changed file with 2 additions and 1 deletion.
3 changes: 2 additions & 1 deletion botocore/operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ def __init__(self, service, op_data, model, paginator_cls=None):
if paginator_cls is None:
paginator_cls = self._DEFAULT_PAGINATOR_CLS
self._paginator_cls = paginator_cls
self._lock = threading.Lock()

def __repr__(self):
return 'Operation:%s' % self.name
Expand Down Expand Up @@ -152,7 +153,7 @@ def request_created(request, **kwargs):
# a request has already been signed without needing
# to acquire the lock.
if not getattr(request, '_is_signed', False):
with threading.Lock():
with self._lock:
if not getattr(request, '_is_signed', False):
signer.sign(self.name, request)
request._is_signed = True
Expand Down

0 comments on commit d8ced45

Please sign in to comment.