Skip to content

Commit 01e1055

Browse files
authored
Fix sync hang issue after async task method call (#5634)
1 parent 5c73c1a commit 01e1055

File tree

5 files changed

+54
-1
lines changed

5 files changed

+54
-1
lines changed

src/System.Private.ServiceModel/tests/Common/Scenarios/ServiceInterfaces.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ public interface IWcfService
8989

9090
[OperationContract]
9191
Dictionary<string, string> GetRequestHttpHeaders();
92+
93+
[OperationContract]
94+
Task EchoReturnTaskAsync();
9295
}
9396

9497
[ServiceContract]

src/System.Private.ServiceModel/tests/Scenarios/Binding/Tcp/NetTcpBindingTests.4.0.0.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,45 @@ public static async Task SecurityModeNone_Echo_RoundTrips_String_SyncAfterAsync(
8282
}
8383
}
8484

85+
// Test for https://github.com/dotnet/wcf/issues/5626
86+
[WcfFact]
87+
[OuterLoop]
88+
public static async Task SecurityModeNone_Echo_RoundTrips_Task_SyncAfterAsync()
89+
{
90+
string testString = "Hello";
91+
ChannelFactory<IWcfService> factory = null;
92+
IWcfService serviceProxy = null;
93+
94+
try
95+
{
96+
// *** SETUP *** \\
97+
NetTcpBinding binding = new NetTcpBinding(SecurityMode.None);
98+
factory = new ChannelFactory<IWcfService>(binding, new EndpointAddress(Endpoints.Tcp_NoSecurity_Address));
99+
serviceProxy = factory.CreateChannel();
100+
101+
// *** EXECUTE *** \\
102+
string result = serviceProxy.Echo(testString);
103+
Assert.Equal(testString, result);
104+
105+
// Without the ConfigureAwait, the xunit sync context will hop threads from the
106+
// completing thread to their sync context. ConfigureAwait means it continues
107+
// executing on the completing thread and triggers the bug (without the fix).
108+
await serviceProxy.EchoReturnTaskAsync().ConfigureAwait(false);
109+
110+
result = serviceProxy.Echo(testString);
111+
Assert.Equal(testString, result);
112+
113+
// *** CLEANUP *** \\
114+
((ICommunicationObject)serviceProxy).Close();
115+
factory.Close();
116+
}
117+
finally
118+
{
119+
// *** ENSURE CLEANUP *** \\
120+
ScenarioTestHelpers.CloseCommunicationObjects((ICommunicationObject)serviceProxy, factory);
121+
}
122+
}
123+
85124
// Test for https://github.com/dotnet/wcf/issues/5134
86125
[WcfFact]
87126
[OuterLoop]

src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/IWcfService.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,5 +160,8 @@ public interface IWcfService
160160

161161
[OperationContract]
162162
Dictionary<string,string> GetRequestHttpHeaders();
163+
164+
[OperationContract]
165+
System.Threading.Tasks.Task EchoReturnTask();
163166
}
164167
}

src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/WcfService.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,5 +468,13 @@ private static Stream StringToStream(string str)
468468

469469
return ms;
470470
}
471+
472+
public System.Threading.Tasks.Task EchoReturnTask()
473+
{
474+
return System.Threading.Tasks.Task.Run(() =>
475+
{
476+
System.Threading.Tasks.Task.Delay(1).Wait();
477+
});
478+
}
471479
}
472480
}

src/System.ServiceModel.Primitives/src/System/ServiceModel/Channels/ServiceChannelProxy.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ private static Task CreateGenericTask(ServiceChannel channel, ProxyOperationRunt
210210

211211
private static Task CreateTask(ServiceChannel channel, ProxyOperationRuntime operation, object[] inputParameters)
212212
{
213-
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
213+
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
214214
bool completedCallback = false;
215215

216216
Action<IAsyncResult> endCallDelegate = (asyncResult) =>

0 commit comments

Comments
 (0)