Skip to content

Commit

Permalink
Merge branch 'v8/8.7' into v8/8.8
Browse files Browse the repository at this point in the history
  • Loading branch information
nul800sebastiaan committed Dec 15, 2020
2 parents d5d7d31 + 6d4990a commit 02d6011
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 11 deletions.
13 changes: 11 additions & 2 deletions src/Umbraco.Core/Logging/LoggingTaskExtension.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Threading;
using System.Threading.Tasks;

namespace Umbraco.Core.Logging
Expand All @@ -14,7 +15,12 @@ internal static class LoggingTaskExtension
/// </summary>
public static Task LogErrors(this Task task, Action<string, Exception> logMethod)
{
return task.ContinueWith(t => LogErrorsInner(t, logMethod), TaskContinuationOptions.OnlyOnFaulted);
return task.ContinueWith(
t => LogErrorsInner(t, logMethod),
CancellationToken.None,
TaskContinuationOptions.OnlyOnFaulted,
// Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html
TaskScheduler.Default);
}

/// <summary>
Expand All @@ -26,7 +32,10 @@ public static Task LogErrors(this Task task, Action<string, Exception> logMethod
/// </summary>
public static Task LogErrorsWaitable(this Task task, Action<string, Exception> logMethod)
{
return task.ContinueWith(t => LogErrorsInner(t, logMethod));
return task.ContinueWith(
t => LogErrorsInner(t, logMethod),
// Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html
TaskScheduler.Default);
}

private static void LogErrorsInner(Task task, Action<string, Exception> logAction)
Expand Down
12 changes: 11 additions & 1 deletion src/Umbraco.Core/Runtime/MainDom.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Hosting;
using Umbraco.Core;
using Umbraco.Core.Logging;
Expand Down Expand Up @@ -38,6 +39,9 @@ internal class MainDom : IMainDom, IRegisteredObject, IDisposable

private const int LockTimeoutMilliseconds = 40000; // 40 seconds

private Task _listenTask;
private Task _listenCompleteTask;

#endregion

#region Ctor
Expand Down Expand Up @@ -172,7 +176,13 @@ private bool Acquire()
try
{
// Listen for the signal from another AppDomain coming online to release the lock
_mainDomLock.ListenAsync().ContinueWith(_ => OnSignal("signal"));
_listenTask = _mainDomLock.ListenAsync();
_listenCompleteTask = _listenTask.ContinueWith(t =>
{
_logger.Debug<MainDom>("Listening task completed with {TaskStatus}", _listenTask.Status);
OnSignal("signal");
}, TaskScheduler.Default); // Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html
}
catch (OperationCanceledException ex)
{
Expand Down
17 changes: 15 additions & 2 deletions src/Umbraco.Core/Runtime/SqlMainDomLock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,12 @@ public Task ListenAsync()

// Create a long running task (dedicated thread)
// to poll to check if we are still the MainDom registered in the DB
return Task.Factory.StartNew(ListeningLoop, _cancellationTokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
return Task.Factory.StartNew(
ListeningLoop,
_cancellationTokenSource.Token,
TaskCreationOptions.LongRunning,
// Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html
TaskScheduler.Default);

}

Expand Down Expand Up @@ -166,7 +171,11 @@ private void ListeningLoop()
// the other MainDom is taking to startup. In this case the db row will just be deleted and the
// new MainDom will just take over.
if (_cancellationTokenSource.IsCancellationRequested)
{
_logger.Debug<SqlMainDomLock>("Task canceled, exiting loop");
return;
}

IUmbracoDatabase db = null;
try
{
Expand All @@ -190,8 +199,10 @@ private void ListeningLoop()
// We need to keep on listening unless we've been notified by our own AppDomain to shutdown since
// we don't want to shutdown resources controlled by MainDom inadvertently. We'll just keep listening otherwise.
if (_cancellationTokenSource.IsCancellationRequested)
{
_logger.Debug<SqlMainDomLock>("Task canceled, exiting loop");
return;

}
}
finally
{
Expand Down Expand Up @@ -396,6 +407,8 @@ protected virtual void Dispose(bool disposing)
{
lock (_locker)
{
_logger.Debug<SqlMainDomLock>($"{nameof(SqlMainDomLock)} Disposing...");

// immediately cancel all sub-tasks, we don't want them to keep querying
_cancellationTokenSource.Cancel();
_cancellationTokenSource.Dispose();
Expand Down
6 changes: 5 additions & 1 deletion src/Umbraco.Web/PublishedCache/NuCache/ContentStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1380,7 +1380,11 @@ private Task CollectAsyncLocked()
{
_collectTask = null;
}
}, TaskContinuationOptions.ExecuteSynchronously);
},
CancellationToken.None,
TaskContinuationOptions.ExecuteSynchronously,
// Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html
TaskScheduler.Default);
// ReSharper restore InconsistentlySynchronizedField

return task;
Expand Down
6 changes: 5 additions & 1 deletion src/Umbraco.Web/PublishedCache/NuCache/SnapDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,11 @@ private Task CollectAsyncLocked()
{
_collectTask = null;
}
}, TaskContinuationOptions.ExecuteSynchronously);
},
CancellationToken.None,
TaskContinuationOptions.ExecuteSynchronously,
// Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html
TaskScheduler.Default);
// ReSharper restore InconsistentlySynchronizedField

return task;
Expand Down
10 changes: 9 additions & 1 deletion src/Umbraco.Web/Scheduling/BackgroundTaskRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -756,9 +756,17 @@ private void StopInitial()
lock (_locker)
{
if (_runningTask != null)
_runningTask.ContinueWith(_ => StopImmediate());
{
_runningTask.ContinueWith(
_ => StopImmediate(),
// Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html
TaskScheduler.Default);
}
else
{
StopImmediate();
}

}
}

Expand Down
22 changes: 20 additions & 2 deletions src/Umbraco.Web/Scheduling/TaskAndFactoryExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ internal static class TaskAndFactoryExtensions
{
#region Task Extensions

// TODO: Not used, is this used in Deploy or something?
static void SetCompletionSource<TResult>(TaskCompletionSource<TResult> completionSource, Task task)
{
if (task.IsFaulted)
Expand All @@ -16,6 +17,7 @@ static void SetCompletionSource<TResult>(TaskCompletionSource<TResult> completio
completionSource.SetResult(default(TResult));
}

// TODO: Not used, is this used in Deploy or something?
static void SetCompletionSource<TResult>(TaskCompletionSource<TResult> completionSource, Task<TResult> task)
{
if (task.IsFaulted)
Expand All @@ -24,17 +26,33 @@ static void SetCompletionSource<TResult>(TaskCompletionSource<TResult> completio
completionSource.SetResult(task.Result);
}

// TODO: Not used, is this used in Deploy or something?
public static Task ContinueWithTask(this Task task, Func<Task, Task> continuation)
{
var completionSource = new TaskCompletionSource<object>();
task.ContinueWith(atask => continuation(atask).ContinueWith(atask2 => SetCompletionSource(completionSource, atask2)));
task.ContinueWith(atask => continuation(atask).ContinueWith(
atask2 => SetCompletionSource(completionSource, atask2),
// Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html
TaskScheduler.Default),
// Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html
TaskScheduler.Default);
return completionSource.Task;
}

// TODO: Not used, is this used in Deploy or something?
public static Task ContinueWithTask(this Task task, Func<Task, Task> continuation, CancellationToken token)
{
var completionSource = new TaskCompletionSource<object>();
task.ContinueWith(atask => continuation(atask).ContinueWith(atask2 => SetCompletionSource(completionSource, atask2), token), token);
task.ContinueWith(atask => continuation(atask).ContinueWith(
atask2 => SetCompletionSource(completionSource, atask2),
token,
TaskContinuationOptions.None,
// Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html
TaskScheduler.Default),
token,
TaskContinuationOptions.None,
// Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html
TaskScheduler.Default);
return completionSource.Task;
}

Expand Down
4 changes: 3 additions & 1 deletion src/Umbraco.Web/WebApi/HttpActionContextExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ public static MultipartFormDataStreamProvider ReadAsMultipart(this HttpActionCon
throw x.Exception;
}
result = x.ConfigureAwait(false).GetAwaiter().GetResult();
});
},
// Must explicitly specify this, see https://blog.stephencleary.com/2013/10/continuewith-is-dangerous-too.html
TaskScheduler.Default);
task.Wait();

if (result == null)
Expand Down

0 comments on commit 02d6011

Please sign in to comment.