From c0e318d8ffc1e61b773fba6eeaa8d1f4c16ce03e Mon Sep 17 00:00:00 2001 From: xgopilot Date: Thu, 6 Nov 2025 06:11:11 +0000 Subject: [PATCH] fix: resolve data race in uptoken.NewSigner Fixed thread-safety issue in storagev2/uptoken package where concurrent calls to GetUpToken() caused data races. The signer.onceGetUpToken() method was checking and writing to signer.upToken without synchronization. Changes: - Added onceUpToken sync.Once field to signer struct - Refactored onceGetUpToken() to use sync.Once.Do() for thread-safe initialization of upToken This ensures token generation happens exactly once even when called concurrently by multiple goroutines during UploadDirectory operations. Fixes #169 Generated with [codeagent](https://github.com/qbox/codeagent) Co-authored-by: zhangzqs <34616640+zhangzqs@users.noreply.github.com> --- storagev2/uptoken/uploadtoken.go | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/storagev2/uptoken/uploadtoken.go b/storagev2/uptoken/uploadtoken.go index b3c32685..423f7aed 100644 --- a/storagev2/uptoken/uploadtoken.go +++ b/storagev2/uptoken/uploadtoken.go @@ -37,6 +37,7 @@ type ( putPolicy PutPolicy credentialsProvider credentials.CredentialsProvider onceCredentials sync.Once + onceUpToken sync.Once upToken string credentials *credentials.Credentials } @@ -86,19 +87,20 @@ func (signer *signer) onceGetCredentials(ctx context.Context) (*credentials.Cred func (signer *signer) onceGetUpToken(ctx context.Context) (string, error) { var err error - if signer.upToken != "" { - return signer.upToken, nil - } - credentials, err := signer.onceGetCredentials(ctx) - if err != nil { - return "", nil - } - putPolicyJson, err := json.Marshal(signer.putPolicy) - if err != nil { - return "", nil - } - signer.upToken = credentials.SignWithData(putPolicyJson) - return signer.upToken, nil + signer.onceUpToken.Do(func() { + var credentials *credentials.Credentials + credentials, err = signer.onceGetCredentials(ctx) + if err != nil { + return + } + var putPolicyJson []byte + putPolicyJson, err = json.Marshal(signer.putPolicy) + if err != nil { + return + } + signer.upToken = credentials.SignWithData(putPolicyJson) + }) + return signer.upToken, err } // NewParser 创建上传凭证签发器