Skip to content

Fix runtime data races, memory leak, and shutdown safety - #1429

Open
bmehta001 wants to merge 90 commits into
microsoft:mainfrom
bmehta001:bhamehta/runtime-fixes
Open

Fix runtime data races, memory leak, and shutdown safety#1429
bmehta001 wants to merge 90 commits into
microsoft:mainfrom
bmehta001:bhamehta/runtime-fixes

Conversation

@bmehta001

@bmehta001 bmehta001 commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

Fixes runtime thread-safety, shutdown-safety, response-lifetime, and resource-leak issues that affect normal SDK operation. Split out from #1415 per reviewer request so runtime behavior changes stay separate from CI/build/test fixes.

Fix HTTP handle cleanup

HttpClient_WinInet.cpp

  • Close the WinInet session handle under its own null check. Previously m_hWinInetSession was closed only inside the if (m_hWinInetRequest != nullptr) block, so if HttpOpenRequestA failed after InternetConnectA succeeded (session set, request null) the session handle leaked.

Fix HTTP response lifetime on abort/network-failure paths

HttpResponseDecoder.cpp

  • Preserve ctx->httpResponse through requestAborted(ctx) and temporaryNetworkFailure(ctx) so downstream storage/statistics handlers can still read status and headers.
  • Avoid leaking aborted/network-failure responses by keeping ownership with EventsUploadContext, whose clear() path deletes the response.

HttpResponseDecoderTests.cpp

  • Add regression coverage that aborted and network-failure decode routes still receive the response object with result/status intact.

Fix WorkerThread shutdown safety, dropped-task handles, and task leak

TaskDispatcher.hpp

  • Make scheduleTask(...) return a no-op DeferredCallbackHandle when the dispatcher synchronously drops/deletes the task during Queue() (for example on a shutdown-drop path), instead of returning a handle that dangles.
  • Track scheduled task lifetime internally so callers only retain a cancellation pointer if the task survived Queue().

WorkerThread.cpp

  • Add an explicit shutdown gate (m_shuttingDown): late Queue() calls are rejected (and the task deleted) once teardown starts.
  • Enqueue the shutdown sentinel only once under the queue lock.
  • Delete pending queued/timer tasks on shutdown instead of only logging that they exist (previously they leaked). On a normal Join() the owning thread deletes them; on the self-dispose path the worker drains and deletes its own remaining tasks before exiting, so neither path leaks.
  • Make self-dispose safe when the last dispatcher reference is released on the worker thread itself: capture the worker id under lock, detach, defer final delete to the thread after its loop exits, and keep self-dispose detection correct even after a prior detach.
  • Log join/detach failures instead of silently swallowing all exceptions.

TaskDispatcherCAPITests.cpp

  • Add coverage that scheduleTask(...) returns a no-op handle when a dispatcher drops the task synchronously during Queue().

PalTests.cpp

  • Add regression coverage that scheduling after Join() returns a no-op handle, and that releasing the last worker-thread reference from a task on that same worker thread does not use-after-free.

Fix Flush teardown deadlock

OfflineStorageHandler.cpp

  • Flush() could early-return (when StartActivity() fails during teardown) without posting flush completion, so WaitForFlush() blocked forever. Signal completion on the early-return path so teardown cannot deadlock.
  • Flush() also paired StartActivity()/EndActivity() manually (StartActivity() at the top, EndActivity() on the last line) with no exception safety in between. StoreRecords(), the optional checkpoint Flush(), and IOfflineStorageObserver::OnStorageRecordsSaved() are all real throw surfaces (disk I/O, a full/locked DB, or an observer implementation); if any of them threw, EndActivity() was skipped and the pause-activity count was permanently leaked, deadlocking every later FlushAndTeardown()'s PauseActivity()+WaitPause(). This reproduced as a live macOS deadlock on main. Added ActivityGuard, an RAII wrapper matching the existing safe pattern already used by PauseGuard (TransmissionPolicyManager.cpp) and ActiveLoggerCall (Logger.cpp): its destructor calls EndActivity() on every exit path, including exception unwinding.

BasicFuncTests.cpp

  • Add a smoke test that tears down while an upload is in flight (CFG_INT_MAX_TEARDOWN_TIME = 0, large payloads against the slow endpoint) and asserts shutdown completes cleanly; it also asserts the /slow/ endpoint rewrite actually happened so the coverage can’t silently lapse.

Fix static-destruction-order crashes in the two process-wide singletons

LogManagerFactory.hpp / PAL.cpp

  • LogManagerFactory::instance() and PAL::GetPAL() were ordinary function-local statics. Their destruction order relative to LogManagerProvider::Release() and PAL::shutdown() (both invoked during process teardown) is unspecified — PAL in particular is constructed lazily on first use rather than at a fixed point, so whether it outlives the teardown call that needs it depends on runtime timing, not source order.
  • A downstream consumer (onnxruntime-genai, see microsoft/onnxruntime-genai#2363) hit this in production as intermittent EXC_BAD_ACCESS crashes on macOS-arm64 at process exit — LogManagerFactory's registries and PAL's ISystemInformation member were sometimes already destroyed by the time teardown code tried to use them — and worked around it in their vendored copy of this SDK by leaking both singletons.
  • Applied the same fix upstream: static T& x = *new T(); deliberately never destroys the object, so it stays valid for the rest of the process regardless of teardown timing. Both objects are small and process-lifetime singletons (one instance ever), and PAL::shutdown() / Release() already perform the real resource teardown explicitly, so this only removes the destructor-ordering hazard, not a resource leak in the ordinary sense.

Make TransmissionPolicyManager scheduling consistently mutex-guarded

TransmissionPolicyManager.cpp / .hpp

  • Guard m_isUploadScheduled, m_runningLatency, and m_scheduledUploadTime consistently with m_scheduledUploadMutex.
  • Avoid holding m_scheduledUploadMutex across potentially blocking cancellation during stop/shutdown.
  • Keep force/zero-delay no-wait cancellation under the scheduler mutex so a competing delayed schedule cannot suppress an immediate upload, and propagate the requested latency to the already-running task when a no-wait cancel fails because that task is already executing.
  • Use an explicit std::chrono::milliseconds value in the bandwidth-controller reschedule path, and cast std::chrono counts to long long in the %lld LOG_TRACE calls (the rep is long on LP64, a -Wformat mismatch in logging-enabled builds).

TransmissionPolicyManagerTests.cpp

  • Add regression coverage for the force/zero-delay scheduling race, including the running-cancel/latency-propagation case.

Fix Logger static-destruction-order crash

Logger.cpp

  • Remove destructor logging from Logger::~Logger() because it can run after logging infrastructure has already been destroyed, causing crashes during static teardown.

Known parity gap (separate repo, follow-up): AIHttpResponseDecoder::handleDecode in the lib/modules submodule (lib/modules/azmon/AIHttpResponseDecoder.cpp:105,118) still sets ctx->httpResponse = nullptr; on the aborted/failure paths — the same response-lifetime leak fixed here in lib/http/HttpResponseDecoder.cpp. It lives in a different repository (the lib/modules submodule), so it must be fixed there and pulled in via a submodule bump; it is out of scope for this PR.

Add batched offline persistence and recovery hardening

OfflineStorage_SQLite.cpp / OfflineStorageHandler.cpp

  • Persist flush batches in one SQLite transaction, filter invalid records before persistence, verify commit success, and roll back both database writes and the in-memory size estimate on failure.
  • Requeue drained records only when the batch is not durably stored, avoiding both event loss and duplicate requeueing.
  • Keep flush completion signaling and record recovery correct on rejected, failed, and exceptional flush paths.

OfflineStorageTests_SQLite.cpp

  • Exercise the batched persistence path in the release performance test and cover rollback/recovery behavior.

Harden Apple cancellation and callback lifetime handling

HttpClient_Apple.mm / HttpClientManager.cpp

  • Handle NSURLSession cancellation callbacks that have no HTTP response without dereferencing a null response.
  • Keep Apple request tracking consistent through asynchronous cancellation callbacks so teardown can drain callback state safely.

Follow-up review fix

WorkerThread.cpp

  • Use the captured worker thread identity for self-cancellation checks, which remains valid after the std::thread object is detached.

bmehta001 and others added 4 commits April 29, 2026 14:41
- HttpClient_Apple: scope Cancel() to m_dataTask only instead of
  blanket-cancelling every task on the shared session. Fix torn read
  on m_requests.empty() in CancelAllRequests spin loop.
- HttpClientManager: fix torn read on m_httpCallbacks.empty() in
  cancelAllRequests spin loop — read under lock.
- HttpResponseDecoder: add missing delete ctx->httpResponse before
  nullptr in Abort and RetryNetwork paths (memory leak).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Only delete queued tasks after successful join (not after detach,
  where the thread may still access them — undefined behavior)
- Replace catch(...) with std::system_error and std::exception handlers
  that log error code and message
- Log pending queue sizes in both join and detach paths

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Both variables are read and written from different threads during
normal upload scheduling. Declare as std::atomic to eliminate data
races per the C++ memory model. Add .load() for variadic LOG_TRACE
calls. Add comment explaining why unlocked stores in uploadAsync
are safe.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove LOG_TRACE from Logger destructor — it triggers a crash on iOS
simulator when the recursive_mutex used by logging has already been
destroyed during static destruction.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bmehta001
bmehta001 force-pushed the bhamehta/runtime-fixes branch from 3f0289c to de46cb2 Compare April 29, 2026 21:42
Reject new worker-thread tasks once shutdown starts so queue cleanup
cannot race with late producers, and move the TPM scheduled-upload
state back under a single mutex so latency/next-upload decisions stay
consistent without mixed atomic and mutex access.

Files changed:
- lib/pal/WorkerThread.cpp
- lib/tpm/TransmissionPolicyManager.cpp
- lib/tpm/TransmissionPolicyManager.hpp

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR targets runtime correctness in the SDK by addressing thread-safety issues, shutdown safety, and a per-request memory leak in HTTP response handling.

Changes:

  • Tighten HTTP request cancellation scoping and fix torn reads in request/callback tracking loops.
  • Fix a SimpleHttpResponse leak on aborted/network-failure decode paths.
  • Rework worker-thread shutdown behavior to avoid unsafe queue cleanup after detach() and improve error logging.
  • Refactor TransmissionPolicyManager scheduling state synchronization (mutex + new cancelUploadTaskLocked() helper).

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
lib/tpm/TransmissionPolicyManager.hpp Changes upload-scheduling state fields and adds a locked cancellation helper declaration.
lib/tpm/TransmissionPolicyManager.cpp Moves upload-scheduling state access under a mutex and adjusts cancellation/scheduling flow.
lib/pal/WorkerThread.cpp Makes shutdown/join behavior safer and improves exception handling/logging during join/detach.
lib/http/HttpResponseDecoder.cpp Deletes ctx->httpResponse on Abort/RetryNetwork paths to prevent leaks.
lib/http/HttpClient_Apple.mm Limits cancellation to the instance’s task and fixes a torn read in the shutdown wait loop.
lib/http/HttpClientManager.cpp Fixes a torn read in the shutdown wait loop by locking around empty-check.
lib/api/Logger.cpp Removes destructor logging to avoid iOS static-destruction-order crash.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/tpm/TransmissionPolicyManager.cpp Outdated
Comment thread lib/tpm/TransmissionPolicyManager.hpp
Comment thread lib/tpm/TransmissionPolicyManager.cpp Outdated
Keep the scheduled-upload state mutex-based, but stop holding
m_scheduledUploadMutex across DeferredCallbackHandle::Cancel so
shutdown and pause paths do not block uploadAsync behind the same
lock. While touching the path, use std::chrono::milliseconds for the
bandwidth-controller reschedule call so ENABLE_BW_CONTROLLER builds
cleanly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
bmehta001 added a commit to bmehta001/cpp_client_telemetry that referenced this pull request May 1, 2026
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bmehta001 bmehta001 self-assigned this May 3, 2026
@bmehta001
bmehta001 requested a review from Copilot May 3, 2026 05:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/http/HttpClientManager.cpp Outdated
Comment thread lib/pal/WorkerThread.cpp
Comment thread lib/pal/WorkerThread.cpp Outdated
Comment thread lib/tpm/TransmissionPolicyManager.cpp Outdated
Comment thread lib/tpm/TransmissionPolicyManager.cpp Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/tpm/TransmissionPolicyManager.cpp Outdated
Comment thread lib/http/HttpResponseDecoder.cpp Outdated
Comment thread lib/http/HttpResponseDecoder.cpp Outdated
bmehta001 and others added 6 commits May 4, 2026 07:26
Keep forced upload scheduling atomic around no-wait cancellation and preserve HTTP responses until downstream abort/network-failure handlers finish.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When scheduleUpload is called with force=true (or zero delay) and the
previously scheduled upload task is currently executing on the worker,
the no-wait cancel returns false and m_isUploadScheduled stays set. The
existing m_isUploadScheduled check then skipped scheduling a new task,
silently dropping the requested latency for force-scheduled profile
changes.

Propagate the requested latency to m_runningLatency under the same
mutex when this race occurs. uploadAsync re-reads m_runningLatency
inside its own LOCKGUARD, so a task that hasn't yet entered that
critical section will pick up the new latency. If uploadAsync has
already cleared m_isUploadScheduled (past its LOCKGUARD), the existing
fallthrough at line 184 schedules a fresh task with the new latency.

Add a regression test using a fake dispatcher whose Cancel always
returns false, asserting that a force-scheduled call updates
m_runningLatency without enqueueing a duplicate task.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use the existing LOCKGUARD helper because scheduled upload cancellation does not need movable lock ownership.

Consolidate the duplicated Issue 388 cancellation note so the PR keeps the remaining limitation documented without repeating the same TODO.

Files changed:

- lib/tpm/TransmissionPolicyManager.cpp

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace tight current-time assertions with a direct comparison against the original delayed schedule time.

This keeps coverage for the forced immediate upload race while reducing timing sensitivity in CI.

Files changed:

- tests/unittests/TransmissionPolicyManagerTests.cpp

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Restore the existing Issue 388 wording in the remaining cancellation comment while keeping the duplicated helper comment removed.

Files changed:

- lib/tpm/TransmissionPolicyManager.cpp

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bmehta001
bmehta001 requested a review from Copilot May 11, 2026 16:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Comment thread lib/tpm/TransmissionPolicyManager.cpp Outdated
Comment thread lib/pal/WorkerThread.cpp Outdated
Comment thread tests/unittests/TransmissionPolicyManagerTests.cpp
Fix printf-style logging arguments for scheduled upload delays and queued worker task pointers.

Ensure the blocking cancel test releases the dispatcher before failing so async futures cannot hang the test runner.

Files changed:

- lib/pal/WorkerThread.cpp

- lib/tpm/TransmissionPolicyManager.cpp

- tests/unittests/TransmissionPolicyManagerTests.cpp

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bmehta001
bmehta001 force-pushed the bhamehta/runtime-fixes branch from 4178021 to d357260 Compare May 12, 2026 23:33
bmehta001 and others added 8 commits August 5, 2026 17:23
Ensure vcpkg-built Apple libraries match the consumer deployment target and avoid linker warnings.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 5f341bc5-f8ae-4259-b03b-8eeb87c06837
Propagate the resolved iOS sysroot to embedding builds and keep Apple vendored targets compatible with strict warning settings.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 5f341bc5-f8ae-4257-b03b-8eeb87c06837
Remove legacy Apple architecture, platform, and deployment-target inputs so standalone scripts and embedding consumers share CMAKE_OSX_* configuration.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 5f341bc5-f8ae-4257-b03b-8eeb87c06837
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 2bfc77f4-1a25-439f-8552-16750895413b
Ensure flush completion is signaled when record recovery throws, prevent activity cleanup exceptions from terminating teardown, and make worker task state race-free.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 2bfc77f4-1a25-439f-8552-16750895413b
Integrate the batched SQLite transaction path and preserve exception-safe flush recovery for PR microsoft#1429.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 2bfc77f4-1a25-439f-8552-16750895413b
Prevent PauseGuard and other teardown destructors from terminating the process when activity cleanup encounters a mutex or system error.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 2bfc77f4-1a25-439f-8552-16750895413b

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 42 out of 42 changed files in this pull request and generated 1 comment.

Suppressed comments (1)

tests/unittests/OfflineStorageTests.cpp:13

  • This test file now uses std::find and std::vector (NoopTaskDispatcher) but does not include or . Relying on transitive includes is brittle and can break builds when headers change; add the direct includes here.

Comment thread lib/pal/WorkerThread.cpp
Ensure the offline storage unit tests do not rely on transitive includes.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 2bfc77f4-1a25-439f-8552-16750895413b

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 42 out of 42 changed files in this pull request and generated no new comments.

Suppressed comments (2)

lib/offline/OfflineStorageHandler.cpp:380

  • LOG_INFO uses printf-style varargs; for a "%p" format the argument must be a void*. Passing a MAT::Task* here is undefined behavior. Cast the pointer to void* so the format/type match.
                        LOG_INFO("Requested Flush (%p)", m_flushHandle.GetTask());

lib/offline/OfflineStorageHandler.cpp:121

  • LOG_INFO uses printf-style varargs; for a "%p" format the argument must be a void*. Passing a MAT::Task* here is undefined behavior. Cast the pointer to void* so the format/type match consistently (similar to the WorkerThread logging fixes).

This issue also appears on line 380 of the same file.

        LOG_INFO("Waiting for pending Flush (%p) to complete...", m_flushHandle.GetTask());

Prevent the transaction destructor from committing a partial batch after an exception, so Flush can safely recover the entire drained batch without duplicate persisted records.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 2bfc77f4-1a25-439f-8552-16750895413b
Adopt main's CMake preset and dependency architecture while preserving the runtime, storage, and teardown fixes on this branch. Resolve the iOS deployment and bundled dependency conflicts in favor of the current main build approach.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 2bfc77f4-1a25-439f-8552-16750895413b
NSURLSession cancellation callbacks may provide no HTTP response. Avoid dereferencing the null response while preserving the aborted result so teardown can complete safely.\n\nCo-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>\nCopilot-Session: 2bfc77f4-1a25-439f-8552-16750895413b
Preserve request lifetime until the asynchronous NSURLSession completion callback has finished, preventing teardown use-after-free and callback drain deadlocks. Also pass task pointers safely to variadic logging.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 2bfc77f4-1a25-439f-8552-16750895413b

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 35 out of 35 changed files in this pull request and generated no new comments.

Suppressed comments (1)

lib/offline/OfflineStorage_SQLite.cpp:371

  • In the batched StoreRecords() path, insertRecordUnsafe() increments m_DbSizeEstimate before the transaction is committed. If an exception occurs during the loop, the transaction is marked for rollback and rethrown, but m_DbSizeEstimate is not reverted, leaving the size estimate permanently inflated (which can trigger incorrect storage-full notifications/resizes).
            catch (...)
            {
#ifdef ENABLE_LOCKING
                // DbTransaction commits on destruction by default for legacy
                // callers. An exception during a batch must explicitly roll

bmehta001 and others added 5 commits August 8, 2026 23:20
Restore the size estimate when a batched insert transaction rolls back, and make the release performance test measure the batched StoreRecords path instead of timing 1,000 individual transactions.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 2bfc77f4-1a25-439f-8552-16750895413b
BasicFuncTests.teardownDuringInFlightUpload_ShutsDownCleanly intermittently
killed the whole test runner on macOS/iOS CI: the process exited with signal
SIGPIPE (exit 141) and no crash backtrace, which XCTest reports as an
unexpected exit/restart and a ~24s timeout rather than a test failure.

Cause: the test HTTP server writes responses from the reactor thread via
::send() with no SIGPIPE protection. That test deliberately cancels an upload
that is still in flight against the /slow/ endpoint, so NSURLSession resets the
connection while the server is mid-response. ::send() then fails with EPIPE and
raises SIGPIPE; the test process installs no handler, so the default
disposition terminates it. The race is timing-dependent, which is why it looks
flaky and only shows up on the slower Apple CI runners.

Fix (test infrastructure only, no SDK behavior change):
- Add Socket::setNoSigPipe() and apply SO_NOSIGPIPE to every accepted
  connection (Apple/BSD, where the option is per-socket).
- Pass MSG_NOSIGNAL from Socket::send() on Linux, which has no SO_NOSIGPIPE.
Both make a write to a reset peer return EPIPE, which the reactor already
handles by closing the connection.

Files changed: tests/common/SocketTools.hpp

Validated locally on macOS (arm64, Debug): the test reproduced at ~30% (5/15
runs exited 141) before the fix and passed 30/30 after; the full FuncTests
suite passes 40/40.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
A failed database recreate clears m_isOpened while retaining the SqliteDB wrapper. The fixture then removes the database path while the wrapper still owns SQLite state, which triggers Apple's vnode-unlinked warning and poisons the next test. Always shut down and reset the wrapper regardless of the open flag so failed recreates cannot leak storage state across tests.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Keep self-thread detection correct after the worker std::thread object is detached, avoiding a potential recursive wait on the execution mutex.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 2bfc77f4-1a25-439f-8552-16750895413b
Keep SQLite transactions bounded and requeue only a failed batch so earlier commits remain durable.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 2bfc77f4-1a25-439f-8552-16750895413b
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

100% CPU spin on CancelAllRequests

4 participants