New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Xamarin.Android.Build.Tasks] fix potential AsyncTask.Log calls #4187
Conversation
8e24138
to
7ebe6aa
Compare
@@ -34,12 +34,15 @@ public abstract class AndroidAsyncTask : AsyncTask | |||
|
|||
public abstract string TaskPrefix { get; } | |||
|
|||
[Obsolete("You should not use the 'Log' property directly for AsyncTask. Use the 'Log*' methods instead.", error: true)] | |||
public new TaskLoggingHelper Log { get; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realize it has error:true
, but should this also throw an exception for Really Good Measure?
Obsolete (..., error: true)]
public new TaskLoggingHelpe Log {
get => throw new NotSupportedException ("Should not be reached!");
}
Admittedly, if the new Log
property is accessed e.g. via Reflection, it'll "just" return null
(and possibly NRE?), and it really shouldn't happen at all anyway, but... defense in depth? ¯_(ツ)_/¯
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would be careful about throwing an exception. the base class AsyncTask uses Log
allot when on the UI thread. See https://github.com/xamarin/Xamarin.Build.AsyncTask/blob/master/Xamarin.Build.AsyncTask/AsyncTask.cs#L138 note all the #pragma stuff which ignore that Obsolete warning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because I used the new
keyword, the base class shouldn't be able to call the property. I think throwing might be better than the NRE, as I could put a better exception message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or maybe I should just return base.Log
? Might be the absolute safest option.
@jonathanpeppers that is not the hang. That is where its manifesting. The WaitForCompletion is the method which waits on all the events while a task is running. It times out every 10 milliseconds That is by design and is exactly how the ToolTask works in MSbuild itself. So the problem isn't that method exactly, its something it trying to use the UI thread while that Wait is in that 10 millisecond "wait". That then causes the lockup. So the cause will be elsewhere. |
@dellis1972 sorry I didn't explain what the picture was. In a new project, in the 16.5 Preview, I used ReSharper's "new class" dialog. This triggered a design-time build and the UI of VS was completely stuck: only option is to end task. I saved a dump file of Since I was going re-test with a build from master after this is merged, but I can probably try the build from this PR. |
Changes: xamarin/monodroid@78d5658...017b361 Bump to xamarin/monodroid@017b3618 We have had a continuing concern of accidentally calling `AsyncTask.Log` from a background thread. If done so, this can cause a hang inside Visual Studio on Windows. I finally had the idea of creating a build error if we inadvertently do this: [Obsolete("You should not use the 'Log' property directly for AsyncTask. Use the 'Log*' methods instead.", error: true)] public new TaskLoggingHelper Log { get; } This uncovered 26 build errors! Some were actually on the main thread and completely OK, but several were not OK. In most of the places, I could simply change `Log.LogDebugMessage` to `LogDebugMessage`. However a few of the more troublesome places: * `ManifestDocument` required a `TaskLoggingHelper` for its ctor. I moved this to only the methods that need it. * `NdkUtils` and `NdkUtilsOld` I used `Action<string>` and `Action<string, string>` callbacks instead. * The `<Aot/>` task had an empty `ValidateAotConfiguration` method I removed. Going forward, it should be a lot harder for us to introduce a hang by using `AsyncTask.Log`.
7ebe6aa
to
dc93eb8
Compare
I found the hang continued to happen until I changed: -<Target Name="_FindLayoutsForBinding" Condition=" '$(Language)' == 'C#' ">
+<Target Name="_FindLayoutsForBinding" Condition=" '$(AndroidGenerateLayoutBindings)' == 'True' And '$(Language)' == 'C#' "> I'll make that change in a different PR, probably should be doing this anyway? |
@jonathanpeppers what you got was a deadlock, the IDE/UI thread was in |
… unused Context: xamarin#4187 We have been able to repro a hang when using ReSharper + Xamarin.Android with this stack trace: Xamarin.Build.AsyncTask.dll!Xamarin.Build.AsyncTask.WaitForCompletion() Line 285 Xamarin.Build.AsyncTask.dll!Xamarin.Build.AsyncTask.Execute() Line 226 Xamarin.Android.Build.Tasks.dll!Xamarin.Android.Tasks.AndroidAsyncTask.RunTask() Xamarin.Android.Build.Tasks.dll!Xamarin.Android.Tasks.AndroidAsyncTask.Execute() This is happening inside the `<CalculateLayoutCodeBehind/>` MSBuild task. Using ReSharper's special "new class" dialog, a design-time build causes the UI to lock up in VS. PR xamarin#4187 does not fully solve the problem, however the problem *does* go away if I make `_FindLayoutsToBind` conditional. `_FindLayoutsToBind` can be completely skipped if you aren't using the new code-behind features in Xamarin.Android. This is a good fix for now to cover most Xamarin.Android projects, and we can revisit `<CalculateLayoutCodeBehind/>` at a later time.
…rin#4187) We have had a continuing concern of accidentally calling methods on `AsyncTask.Log` from a background thread. If it happens, this can cause a hang inside Visual Studio on Windows. I finally had the idea of creating a build error if we inadvertently do this: [Obsolete("You should not use the 'Log' property directly for AsyncTask. Use the 'Log*' methods instead.", error: true)] public new TaskLoggingHelper Log { get; } This uncovered 26 build errors! Some were actually on the main thread and completely OK, but several were not OK. In most of the places, I could simply change `Log.LogDebugMessage()` to `LogDebugMessage()`. However a few of the more troublesome places: * `ManifestDocument` required a `TaskLoggingHelper` for its ctor. I moved this to only the methods that need it. * `NdkUtils` and `NdkUtilsOld` I used `Action<string>` and `Action<string, string>` callbacks instead. * The `<Aot/>` task had an empty `ValidateAotConfiguration()` method I removed. Going forward, it should be a lot harder for us to introduce a hang by using `AsyncTask.Log`.
… (#4205) We have had a continuing concern of accidentally calling methods on `AsyncTask.Log` from a background thread. If it happens, this can cause a hang inside Visual Studio on Windows. I finally had the idea of creating a build error if we inadvertently do this: [Obsolete("You should not use the 'Log' property directly for AsyncTask. Use the 'Log*' methods instead.", error: true)] public new TaskLoggingHelper Log { get; } This uncovered 26 build errors! Some were actually on the main thread and completely OK, but several were not OK. In most of the places, I could simply change `Log.LogDebugMessage()` to `LogDebugMessage()`. However a few of the more troublesome places: * `ManifestDocument` required a `TaskLoggingHelper` for its ctor. I moved this to only the methods that need it. * `NdkUtils` and `NdkUtilsOld` I used `Action<string>` and `Action<string, string>` callbacks instead. * The `<Aot/>` task had an empty `ValidateAotConfiguration()` method I removed. Going forward, it should be a lot harder for us to introduce a hang by using `AsyncTask.Log`.
… unused (#4199) Context: #4187 (comment) Context: #4187 (comment) We have been able to repro a hang when using ReSharper + Xamarin.Android with this stack trace: Xamarin.Build.AsyncTask.dll!Xamarin.Build.AsyncTask.WaitForCompletion() Line 285 Xamarin.Build.AsyncTask.dll!Xamarin.Build.AsyncTask.Execute() Line 226 Xamarin.Android.Build.Tasks.dll!Xamarin.Android.Tasks.AndroidAsyncTask.RunTask() Xamarin.Android.Build.Tasks.dll!Xamarin.Android.Tasks.AndroidAsyncTask.Execute() This is happening inside the `<CalculateLayoutCodeBehind/>` MSBuild task. Using ReSharper's special "new class" dialog, a design-time build causes the UI to lock up in VS. Commit 9fca138/PR #4187 did not fully solve the problem, however the problem *does* go away if I make `_FindLayoutsToBind` conditional. `_FindLayoutsToBind` can be completely skipped if you aren't using the new code-behind features in Xamarin.Android. This is a good fix for now to cover most Xamarin.Android projects, and we can revisit `<CalculateLayoutCodeBehind/>` at a later time.
… unused (#4199) Context: #4187 (comment) Context: #4187 (comment) We have been able to repro a hang when using ReSharper + Xamarin.Android with this stack trace: Xamarin.Build.AsyncTask.dll!Xamarin.Build.AsyncTask.WaitForCompletion() Line 285 Xamarin.Build.AsyncTask.dll!Xamarin.Build.AsyncTask.Execute() Line 226 Xamarin.Android.Build.Tasks.dll!Xamarin.Android.Tasks.AndroidAsyncTask.RunTask() Xamarin.Android.Build.Tasks.dll!Xamarin.Android.Tasks.AndroidAsyncTask.Execute() This is happening inside the `<CalculateLayoutCodeBehind/>` MSBuild task. Using ReSharper's special "new class" dialog, a design-time build causes the UI to lock up in VS. Commit 9fca138/PR #4187 did not fully solve the problem, however the problem *does* go away if I make `_FindLayoutsToBind` conditional. `_FindLayoutsToBind` can be completely skipped if you aren't using the new code-behind features in Xamarin.Android. This is a good fix for now to cover most Xamarin.Android projects, and we can revisit `<CalculateLayoutCodeBehind/>` at a later time.
Changes: https://github.com/xamarin/monodroid/compare/78d56588...017b3618
Bump to xamarin/monodroid/master@017b3618
We have had a continuing concern of accidentally calling
AsyncTask.Log
from a background thread. If done so, this can cause ahang inside Visual Studio on Windows.
I finally had the idea of creating a build error if we inadvertently
do this:
This uncovered 26 build errors! Some were actually on the main thread
and completely OK, but several were not OK.
In most of the places, I could simply change
Log.LogDebugMessage
toLogDebugMessage
.However a few of the more troublesome places:
ManifestDocument
required aTaskLoggingHelper
for its ctor. Imoved this to only the methods that need it.
NdkUtils
andNdkUtilsOld
I usedAction<string>
andAction<string, string>
callbacks instead.The
<Aot/>
task had an emptyValidateAotConfiguration
method Iremoved.
Going forward, it should be a lot harder for us to introduce a hang by
using
AsyncTask.Log
.