Skip to content
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

Fix 10 minutes time out of TransactionScope #21102

Merged
merged 1 commit into from
Sep 20, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 46 additions & 10 deletions src/Cli/dotnet/TransactionalAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,19 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Reflection;
using System.Transactions;
using Microsoft.DotNet.Cli.Utils;

namespace Microsoft.DotNet.Cli
{
public sealed class TransactionalAction
{
static TransactionalAction()
{
DisableTransactionTimeoutUpperLimit();
}

private class EnlistmentNotification : IEnlistmentNotification
{
private Action _commit;
Expand Down Expand Up @@ -65,19 +72,44 @@ public static T Run<T>(
// This automatically inherits any ambient transaction
// If a transaction is inherited, completing this scope will be a no-op
T result = default(T);
using (var scope = new TransactionScope(
TransactionScopeOption.Required,
TimeSpan.Zero))
try
{
Transaction.Current.EnlistVolatile(
new EnlistmentNotification(commit, rollback),
EnlistmentOptions.None);
using (var scope = new TransactionScope(
TransactionScopeOption.Required,
TimeSpan.Zero))
Copy link
Member

Choose a reason for hiding this comment

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

Are you sure you want an infinite timeout? A really high timeout will still eventually timeout whereas something going wrong with an infinite timeout can cause things to block indefinitely.

Copy link
Member

Choose a reason for hiding this comment

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

I think that the other operations happening within the transaction have their own timeouts, so it wouldn't end up being effectively infinite.

{
Transaction.Current.EnlistVolatile(
new EnlistmentNotification(commit, rollback),
EnlistmentOptions.None);

result = action();
result = action();

scope.Complete();
scope.Complete();
}

return result;
}
catch (TransactionAbortedException ex)
{
Reporter.Verbose.WriteLine(string.Format("TransactionAbortedException Message: {0}", ex.Message));
Reporter.Verbose.WriteLine(
$"Inner Exception Message: {ex?.InnerException?.Message + "---" + ex?.InnerException}");
throw;
}
return result;
}

private static void SetTransactionManagerField(string fieldName, object value)
{
typeof(TransactionManager).GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Static)
.SetValue(null, value);
}

// https://github.com/dotnet/sdk/issues/21101
// we should use the proper API once it is available
public static void DisableTransactionTimeoutUpperLimit()
{
SetTransactionManagerField("s_cachedMaxTimeout", true);
SetTransactionManagerField("s_maximumTimeout", TimeSpan.Zero);
}

public static void Run(
Expand All @@ -86,7 +118,11 @@ public static void Run(
Action rollback = null)
{
Run<object>(
action: () => { action(); return null; },
action: () =>
{
action();
return null;
},
commit: commit,
rollback: rollback);
}
Expand Down