VPAAMP-558: restore per-host curl share locks; fix non-store USERDATA=NULL#1606
Open
pstroffolino wants to merge 2 commits into
Open
VPAAMP-558: restore per-host curl share locks; fix non-store USERDATA=NULL#1606pstroffolino wants to merge 2 commits into
pstroffolino wants to merge 2 commits into
Conversation
…=NULL
Issue 1 (medium risk -- per-host DNS/SSL lock granularity):
Embed CurlDataShareLock mShareLock directly in curlstorestruct as a
value member. CURLSHOPT_USERDATA is now set to &CurlSock->mShareLock
so each CDN hostname gets its own three-way mutex (DNS / SSL / general),
restoring the parallelism lost by the VPAAMP-139 single-static-lock fix.
Safety: every cleanup path (RemoveCurlSock, ~CurlStore,
FlushCurlSockForHost) follows the order:
1. curl_easy_cleanup all queued handles (no further easy-hdl callbacks)
2. curl_share_cleanup(mCurlShared) (share teardown; lock may fire)
3. SAFE_DELETE(CurlSock) (destroys embedded mShareLock)
The embedded lock is therefore always alive when curl_share_cleanup
calls it, eliminating the original use-after-free without leaking memory.
Removes: CurlStore::mSharedCurlLock (static class member, no longer
needed) and the old large IMPORTANT comment block.
Issue 2 (low risk -- non-store path USERDATA=NULL inconsistency):
Replace static std::mutex gCurlShMutex with static CurlDataShareLock
gCurlShLock. CurlInit (non-store path) now passes &gCurlShLock as
CURLSHOPT_USERDATA instead of NULL, giving DNS/SSL/general lock
granularity parity with the store path. The defensive else branches
in curl_lock/unlock_callback are updated accordingly.
Test updates (CurlStoreTests.cpp):
T1 CreateCurlStore_UserDataDiffersAcrossHosts
Flipped from SAME to DIFFERENT: two hostname entries must now
receive distinct CURLSHOPT_USERDATA pointers (per-host lock).
T2 LockCallback_WorksWhileEntryIsAlive
Replaced: captures callbacks while entry is alive (count > 0) and
invokes them; verifies the embedded lock is functional.
T3 ShareCleanup_CalledOnEviction
Replaced: verifies that curl_share_cleanup is called with the
correct CURLSH handle when RemoveCurlSock evicts an entry, testing
the cleanup-order invariant that guarantees lock safety.
T4 LockCallback_HandlesAllLockDataTypes
Unchanged (still exercises DNS/SSL/generic branches).
Contributor
There was a problem hiding this comment.
Pull request overview
Restores per-host libcurl share locking in CurlStore to regain DNS/SSL cache parallelism (lost in the prior single-static-lock fix), and fixes the non-store path to pass a valid CURLSHOPT_USERDATA pointer instead of NULL.
Changes:
- Embed
CurlDataShareLockas a value member incurlstorestructand pass&CurlSock->mShareLockasCURLSHOPT_USERDATAfor per-host lock granularity. - Replace the non-store global
std::mutexfallback with a process-lifetimeCurlDataShareLockand pass it viaCURLSHOPT_USERDATAinCurlInit. - Update L1 tests to validate per-host distinct
USERDATApointers and the expectedcurl_share_cleanupeviction behavior.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
downloader/AampCurlStore.h |
Adds per-host embedded share lock to the curl store entry struct; removes the static shared lock. |
downloader/AampCurlStore.cpp |
Switches share USERDATA to per-entry lock; introduces process-lifetime lock for non-store path; adjusts callback fallback locking. |
test/utests/tests/AampCurlStore/CurlStoreTests.cpp |
Updates regression tests to assert distinct per-host USERDATA and validate eviction cleanup ordering. |
… in tests AampCurlStore.h: Reorder curlstorestruct constructor initializer list to match the member declaration order (mFreeQ, mCurlShared, mShareLock, mCurlStoreUserCount, timestamp). The previous order triggered -Wreorder which is fatal in -Werror builds. CurlStoreTests.cpp: CurlStore is a Meyer singleton that persists across all tests in the process. Every GetHandleForHost call increments mCurlStoreUserCount; leaving it > 0 prevents RemoveCurlSock from evicting the entry, causing later tests to accumulate stale entries and making eviction- dependent behaviour order-sensitive. Fix: capture the CURL* returned by every GetHandleForHost call and add a matching ReturnHandleForHost at the end of each test body (T1, T2, T3, T4) so mCurlStoreUserCount returns to 0 before the test exits. KeepInCurlStore does not trigger RemoveCurlSock, so there are no additional mock side-effects from the return calls.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue 1 (medium risk -- per-host DNS/SSL lock granularity):
Embed CurlDataShareLock mShareLock directly in curlstorestruct as a
value member. CURLSHOPT_USERDATA is now set to &CurlSock->mShareLock
so each CDN hostname gets its own three-way mutex (DNS / SSL / general),
restoring the parallelism lost by the VPAAMP-139 single-static-lock fix.
Safety: every cleanup path (RemoveCurlSock, ~CurlStore,
FlushCurlSockForHost) follows the order:
1. curl_easy_cleanup all queued handles (no further easy-hdl callbacks)
2. curl_share_cleanup(mCurlShared) (share teardown; lock may fire)
3. SAFE_DELETE(CurlSock) (destroys embedded mShareLock)
The embedded lock is therefore always alive when curl_share_cleanup
calls it, eliminating the original use-after-free without leaking memory.
Removes: CurlStore::mSharedCurlLock (static class member, no longer
needed) and the old large IMPORTANT comment block.
Issue 2 (low risk -- non-store path USERDATA=NULL inconsistency):
Replace static std::mutex gCurlShMutex with static CurlDataShareLock
gCurlShLock. CurlInit (non-store path) now passes &gCurlShLock as
CURLSHOPT_USERDATA instead of NULL, giving DNS/SSL/general lock
granularity parity with the store path. The defensive else branches
in curl_lock/unlock_callback are updated accordingly.
Test updates (CurlStoreTests.cpp):
T1 CreateCurlStore_UserDataDiffersAcrossHosts
Flipped from SAME to DIFFERENT: two hostname entries must now
receive distinct CURLSHOPT_USERDATA pointers (per-host lock).
T2 LockCallback_WorksWhileEntryIsAlive
Replaced: captures callbacks while entry is alive (count > 0) and
invokes them; verifies the embedded lock is functional.
T3 ShareCleanup_CalledOnEviction
Replaced: verifies that curl_share_cleanup is called with the
correct CURLSH handle when RemoveCurlSock evicts an entry, testing
the cleanup-order invariant that guarantees lock safety.
T4 LockCallback_HandlesAllLockDataTypes
Unchanged (still exercises DNS/SSL/generic branches).