Skip to content

BindableObject System.NullReferenceException when bindings queue gets messed up#21523

Merged
StephaneDelcroix merged 3 commits into
dotnet:mainfrom
taublast:taublast-patch-1
Apr 6, 2024
Merged

BindableObject System.NullReferenceException when bindings queue gets messed up#21523
StephaneDelcroix merged 3 commits into
dotnet:mainfrom
taublast:taublast-patch-1

Conversation

@taublast
Copy link
Copy Markdown
Contributor

Description of Change

Added a check for null.

Issues Fixed

What I am meeting often in a multi-threaded situation:

System.NullReferenceException: Object reference not set to an instance of an object.

03-29 10:10:25.660 I/DOTNET  ( 4189): System.NullReferenceException: Object reference not set to an instance of an object.
03-29 10:10:25.661 I/DOTNET  ( 4189):    at Microsoft.Maui.Controls.BindableObject.SetValueCore(BindableProperty property, Object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes, SetterSpecificity specificity) in D:\a\_work\1\s\src\Controls\src\Core\BindableObject.cs:line 577
03-29 10:10:25.661 I/DOTNET  ( 4189):    at Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value) in D:\a\_work\1\s\src\Controls\src\Core\BindableObject.cs:line 474

This leads to bindings to stop working forever for this specific BindableObject.

Proposing that the backend should never crash whatever the client is doing.

taublast and others added 2 commits March 29, 2024 10:18
…nstance of an object.

03-29 10:10:25.660 I/DOTNET  ( 4189): System.NullReferenceException: Object reference not set to an instance of an object.
03-29 10:10:25.661 I/DOTNET  ( 4189):    at Microsoft.Maui.Controls.BindableObject.SetValueCore(BindableProperty property, Object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes, SetterSpecificity specificity) in D:\a\_work\1\s\src\Controls\src\Core\BindableObject.cs:line 577
03-29 10:10:25.661 I/DOTNET  ( 4189):    at Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value) in D:\a\_work\1\s\src\Controls\src\Core\BindableObject.cs:line 474
@taublast taublast requested a review from a team as a code owner March 29, 2024 07:39
@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Hey there @taublast! Thank you so much for your PR! Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

@dotnet-policy-service dotnet-policy-service Bot added the community ✨ Community Contribution label Mar 29, 2024
@PureWeen PureWeen requested review from StephaneDelcroix and removed request for jfversluis March 29, 2024 13:27
@rmarinho
Copy link
Copy Markdown
Member

rmarinho commented Apr 1, 2024

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

Copy link
Copy Markdown
Member

@rmarinho rmarinho left a comment

Choose a reason for hiding this comment

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

Hey @taublast do you think you can add a unit test? thanks

@taublast
Copy link
Copy Markdown
Contributor Author

taublast commented Apr 2, 2024

Hey @taublast do you think you can add a unit test? thanks

@rmarinho sure, will do.

@taublast
Copy link
Copy Markdown
Contributor Author

taublast commented Apr 2, 2024

Still on it, very hard to catch and reproduce, can't get a 100% repro yet.

image

Debugging that test catched another 100%-related problem, I was getting it since MAUI came out, but it was very hard to reproduce. Should we fix it too?

image

My guess the solution is to lock execution of GetOrCreateContext since its parallel execution can access the non-concurrent Dictionary inside. Another solution could be to use "ConcurrentDictionary".

@taublast
Copy link
Copy Markdown
Contributor Author

taublast commented Apr 2, 2024

For me this one catches either crash A or crash B from the above post:

[Fact]
	public async Task GetSetValueMultithreaded()
	{
		var value = "text";
		int numberOfThreads = 100;
		var random = new Random();
		var exceptions = new ConcurrentBag<Exception>();
		bool get = false;

		for (int i = 0; i < numberOfThreads; i++)
		{
			var newMock = new MockBindable();
			Parallel.For(0, numberOfThreads, async (i) =>
			{
				try
				{
					if (random.Next(0, 1) == 1)
					{
						var read = newMock.GetValue(MockBindable.TextProperty);
					}
					else
					{
						newMock.SetValue(MockBindable.TextProperty, value);
					}
				}
				catch (Exception ex)
				{
					exceptions.Add(ex);
				}
			});
		}

		if (exceptions.Count > 0)
		{
			throw new AggregateException(exceptions);
		}
	}

@StephaneDelcroix StephaneDelcroix enabled auto-merge (squash) April 2, 2024 08:39
@rmarinho
Copy link
Copy Markdown
Member

rmarinho commented Apr 2, 2024

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

@jsuarezruiz jsuarezruiz added the area-xaml XAML, CSS, Triggers, Behaviors label Apr 3, 2024
@StephaneDelcroix StephaneDelcroix merged commit d743f9f into dotnet:main Apr 6, 2024
@github-actions github-actions Bot locked and limited conversation to collaborators May 9, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-xaml XAML, CSS, Triggers, Behaviors community ✨ Community Contribution fixed-in-8.0.40 fixed-in-9.0.0-preview.4.10690

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants