Skip to content

fix: prevent NullReferenceException in Histories async operations#2289

Closed
gadfly3173 wants to merge 1 commit intosourcegit-scm:developfrom
gadfly3173:fix/null-reference-in-histories-async-calls
Closed

fix: prevent NullReferenceException in Histories async operations#2289
gadfly3173 wants to merge 1 commit intosourcegit-scm:developfrom
gadfly3173:fix/null-reference-in-histories-async-calls

Conversation

@gadfly3173
Copy link
Copy Markdown
Contributor

Add null checks for _repo in Histories methods to prevent crashes when Repository is closed while async operations are still pending.

Bug Cause:
When Repository.Close() is called, Histories.Dispose() sets _repo to null. If an async operation (e.g., CheckoutBranchByDecoratorAsync triggered by double-clicking a branch icon) is executing concurrently, it may access the now-null _repo reference, causing NullReferenceException.

Stack Trace:

System.NullReferenceException: Object reference not set to an instance of an object.
   at SourceGit.ViewModels.Repository.<CheckoutBranchAsync>d__192.MoveNext() + 0x169
--- End of stack trace from previous location ---
   at SourceGit.ViewModels.Histories.<CheckoutBranchByDecoratorAsync>d__48.MoveNext() + 0x57
--- End of stack trace from previous location ---
   at SourceGit.Views.Histories.<OnCommitListDoubleTapped>d__34.MoveNext() + 0x5a
--- End of stack trace from previous location ---
   at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__124_0(Object state) + 0x1a
   at Avalonia.Threading.SendOrPostCallbackDispatcherOperation.InvokeCore() + 0x19a
   at Avalonia.Threading.DispatcherOperation.Execute() + 0x4a
   at Avalonia.Threading.Dispatcher.ExecuteJob(DispatcherOperation) + 0x78
   at Avalonia.Threading.Dispatcher.ExecuteJobsCore(Boolean) + 0x387
   at Avalonia.Win32.Win32Platform.WndProc(IntPtr hWnd, UInt32 msg, IntPtr wParam, IntPtr lParam) + 0x58
   at SourceGit!<BaseAddress>+0x1166c9a

Add null checks for _repo in Histories methods to prevent crashes when
Repository is closed while async operations are still pending.

Bug Cause:
When Repository.Close() is called, Histories.Dispose() sets _repo to null.
If an async operation (e.g., CheckoutBranchByDecoratorAsync triggered by
double-clicking a branch icon) is executing concurrently, it may access
the now-null _repo reference, causing NullReferenceException.

Stack Trace:

```log
System.NullReferenceException: Object reference not set to an instance of an object.
   at SourceGit.ViewModels.Repository.<CheckoutBranchAsync>d__192.MoveNext() + 0x169
--- End of stack trace from previous location ---
   at SourceGit.ViewModels.Histories.<CheckoutBranchByDecoratorAsync>d__48.MoveNext() + 0x57
--- End of stack trace from previous location ---
   at SourceGit.Views.Histories.<OnCommitListDoubleTapped>d__34.MoveNext() + 0x5a
--- End of stack trace from previous location ---
   at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__124_0(Object state) + 0x1a
   at Avalonia.Threading.SendOrPostCallbackDispatcherOperation.InvokeCore() + 0x19a
   at Avalonia.Threading.DispatcherOperation.Execute() + 0x4a
   at Avalonia.Threading.Dispatcher.ExecuteJob(DispatcherOperation) + 0x78
   at Avalonia.Threading.Dispatcher.ExecuteJobsCore(Boolean) + 0x387
   at Avalonia.Win32.Win32Platform.WndProc(IntPtr hWnd, UInt32 msg, IntPtr wParam, IntPtr lParam) + 0x58
   at SourceGit!<BaseAddress>+0x1166c9a

```
@love-linger
Copy link
Copy Markdown
Collaborator

It's not just about Histories. You will get this exception when you are trying to close repository while it has an async operation running.

I believe the only solution to such problems is that when there is a action still running, the Close will not clear properties (since we do not have unmanaged resources), and let it recycled by system GC

love-linger added a commit that referenced this pull request Apr 21, 2026
…still running (#2289)

Signed-off-by: leo <longshuang@msn.cn>
@love-linger
Copy link
Copy Markdown
Collaborator

I've pushed my fix for this bug

love-linger added a commit that referenced this pull request Apr 21, 2026
…still running (#2289)

- It's not necessary to implement `IDisposable` interface for class that only contains managed resources
- Do not clear fields of `Repository` and let system GC handle it

Signed-off-by: leo <longshuang@msn.cn>
@gadfly3173 gadfly3173 closed this Apr 21, 2026
@gadfly3173 gadfly3173 deleted the fix/null-reference-in-histories-async-calls branch April 21, 2026 03:57
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.

2 participants