SDWebImageSwiftUI icon indicating copy to clipboard operation
SDWebImageSwiftUI copied to clipboard

Fix Race conditions

Open biovolt opened this issue 4 months ago • 1 comments

I believe this fixes https://github.com/SDWebImage/SDWebImageSwiftUI/issues/358

Summary by CodeRabbit

  • Bug Fixes
    • Improves stability of image loading by ensuring progress and completion callbacks are invoked consistently under concurrent scenarios.
    • Delivers progress updates reliably on the main thread, reducing missed or duplicated notifications.
    • Reduces rare race-related crashes or hangs during rapid callback changes.
  • Refactor
    • Internally synchronizes callback handling for more predictable behavior, with no changes to how you set or use callbacks.

biovolt avatar Sep 02 '25 11:09 biovolt

Walkthrough

Introduces thread-safe storage and invocation for image loading callbacks in ImageManager by adding a private callback queue and backing closures. Public callback properties become computed with synchronized get/set. Progress and completion now capture local callback references and dispatch to the main thread, minimizing race conditions. No functional flow changes.

Changes

Cohort / File(s) Summary of Changes
Thread-safe callback handling
SDWebImageSwiftUI/Classes/ImageManager.swift
- Added callbackQueue and private _successBlock, _failureBlock, _progressBlock.
- Converted successBlock, failureBlock, progressBlock to computed properties synchronized via callbackQueue.
- Captured local callback copies for progress/completion before invoking on main thread.
- Maintains existing loading flow and API surface behavior.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant View
  participant ImageManager
  participant SDWebImage
  participant CallbackQueue as Callback Queue
  participant MainThread

  View->>ImageManager: set success/failure/progress blocks
  ImageManager->>CallbackQueue: sync set _success/_failure/_progress

  View->>ImageManager: load(url)
  ImageManager->>SDWebImage: start request

  SDWebImage-->>ImageManager: progress(received,total)
  ImageManager->>CallbackQueue: sync get _progress
  CallbackQueue-->>ImageManager: progressCallback
  alt progressCallback exists
    ImageManager->>MainThread: invoke progressCallback(received,total)
  end

  SDWebImage-->>ImageManager: completion(image,data,cacheType or error)
  ImageManager->>CallbackQueue: sync get _success/_failure
  CallbackQueue-->>ImageManager: successCallback/failureCallback
  alt success
    ImageManager->>MainThread: invoke successCallback(image,data,cacheType)
  else failure
    ImageManager->>MainThread: invoke failureCallback(error)
  end

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

In burrows of bytes, I twitch with delight,
Queued little callbacks, kept snug and tight.
No races to chase, no hare-brained despair—
Progress hops softly, completion with care.
On the main meadow, we nuzzle the view,
Thread-safe thumps: thump-thump—swift and true.

✨ Finishing Touches
  • [ ] 📝 Generate Docstrings
🧪 Generate unit tests
  • [ ] Create PR with unit tests
  • [ ] Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

coderabbitai[bot] avatar Sep 02 '25 11:09 coderabbitai[bot]