dotnet / dotnet/wcf

Timeout logic problem on OneWay methods in WCF 4.7.0 on NetCore 3.1 (Win)

Open
#4,302 0 comments 0 reactions 1 assignee Claimed by @mconnew View on GitHub
bug
Dominant language
C#
Stars
1.8k
Forks
576
Avg merge
6d 9h
Merged PRs (30d)
2

Description

**Describe the bug**
In out WCF application we use `void Test(int i)` method with `IsOneWay=True` attribute.
The method is called every second. Server processing is negligible (~1 ms).
If we specify client timeouts ~5..7 sec, it will throw timeout exception on ~5..7th call.
Same code under .Net Framework works fine.

The exception thrown:
```
System.ServiceModel.CommunicationException: The socket was aborted because an asynchronous receive from the socket did not complete within the allotted timeout of 00:00:05.8140000. The time allotted to this operation may have been a portion of a longer timeout.
---> System.IO.IOException: The write operation failed, see inner exception.
---> System.ServiceModel.CommunicationException: The socket was aborted because an asynchronous receive from the socket did not complete within the allotted timeout of 00:00:05.8140000. The time allotted to this operation may have been a portion of a longer timeout.
---> System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Sockets.Socket'.
at System.Net.Sockets.Socket.Send(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, SocketError& errorCode)
at System.ServiceModel.Channels.SocketConnection.Write(Byte[] buffer, Int32 offset, Int32 size, Boolean immediate, TimeSpan timeout)
--- End of inner exception stack trace ---
at System.ServiceModel.Channels.SocketConnection.Write(Byte[] buffer, Int32 offset, Int32 size, Boolean immediate, TimeSpan timeout)
at System.ServiceModel.Channels.BufferedConnection.WriteNow(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout, BufferManager bufferManager)

at System.ServiceModel.Channels.BufferedConnection.WriteNow(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout)
at System.ServiceModel.Channels.BufferedConnection.Write(Byte[] buffer, Int32 offset, Int32 size, Boolean immediate, TimeSpan timeout)
at System.ServiceModel.Channels.ConnectionStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at System.Net.Security.NegotiateStream.StartWriting(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.NegotiateStream.ProcessWrite(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
--- End of inner exception stack trace ---
at System.Net.Security.NegotiateStream.ProcessWrite(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.NegotiateStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at System.ServiceModel.Channels.StreamConnection.Write(Byte[] buffer, Int32 offset, Int32 size, Boolean immediate, TimeSpan timeout)
--- End of inner exception stack trace ---
at System.ServiceModel.Channels.StreamConnection.Write(Byte[] buffer, Int32 offset, Int32 size, Boolean immediate, TimeSpan timeout)
at System.ServiceModel.Channels.StreamConnection.Write(Byte[] buffer, Int32 offset, Int32 size, Boolean immediate, TimeSpan timeout, BufferManager
bufferManager)
at System.ServiceModel.Channels.FramingDuplexSessionChannel.OnSendCore(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.TransportDuplexSessionChannel.OnSend(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.OutputChannel.Send(Message message, TimeSpan timeout)
at System.ServiceModel.Dispatcher.DuplexChannelBinder.Send(Message message, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, Ti
meSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(MethodCall methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(MethodInfo targetMethod, Object[] args)
--- End of stack trace from previous location where exception was thrown ---
at System.Reflection.DispatchProxyGenerator.Invoke(Object[] args)
....

```

**To Reproduce**
Simple app to reproduce issue:

```
using System;

namespace TestInterface
{
using System.ServiceModel;

public static class TestConst
{
public const string DEF_URL = "net.tcp://localhost:8080/ITestService";
}

[ServiceContract]
public interface ITestService
{
[OperationContract( IsOneWay = true )]
void Test( int I );
}
}

namespace TestClient
{
using System.ServiceModel;
using System.Threading;

using TestInterface;

static class Client
{
public static void ClientLoop( string ServerUrl = TestConst.DEF_URL )
{
ChannelFactory TestFactory = new ChannelFactory( new NetTcpBinding
{
OpenTimeout = new TimeSpan( 0, 0, 0, 0, 5000 ),
SendTimeout = new TimeSpan( 0, 0, 0, 0, 6000 ),
ReceiveTimeout = new TimeSpan( 0, 0, 0, 0, 7000 ),
CloseTimeout = new TimeSpan( 0, 0, 0, 0, 8000 ),
}, new EndpointAddress( ServerUrl ) );

var TestChannel = TestFactory.CreateChannel();

int ReqNumber = 0;
int GoodCalls = 0;

Console.WriteLine( "Client Start" );
Console.WriteLine( "Press any key to stop..." );

while( true )
{
if( Console.KeyAvailable )
{
return;
}

try
{
TestChannel.Test( ReqNumber );

ReqNumber++;
GoodCalls++;
Console.WriteLine( $"DONE ReqNum:{ReqNumber} [Good: {GoodCalls}]" );
}
catch( Exception Ex )
{
ReqNumber++;
GoodCalls = 0;
Console.Error.WriteLine( $"FAIL ReqNum:{ReqNumber} ERROR:{GoodCalls} {Ex}");
}
finally
{
Thread.Sleep( 1000 );
}
}
}
}
}

#if NETCOREAPP

namespace TestServer
{
using TestInterface;

static class Server
{
public static void ServerLoop( string ServerUrl = TestConst.DEF_URL )
{
Console.Error.WriteLine( "Server is not available under .net core (user .net framework)" );
}
}
}

#else

namespace TestServer
{
using System.ServiceModel;

using TestInterface;

static class Server
{
public static void ServerLoop( string ServerUrl = TestConst.DEF_URL )
{
try
{
ServiceHost Host = new ServiceHost( typeof( TestService ) );
Host.AddServiceEndpoint( typeof( ITestService ), new NetTcpBinding
{
OpenTimeout = new TimeSpan( 0, 0, 0, 0, 5000 ),
SendTimeout = new TimeSpan( 0, 0, 0, 0, 6000 ),
ReceiveTimeout = new TimeSpan( 0, 0, 0, 0, 7000 ),
CloseTimeout = new TimeSpan( 0, 0, 0, 0, 8000 )

}, new Uri( ServerUrl ) );
Host.Open();

Console.WriteLine( "Server start" );
Console.ReadKey();
}
catch( Exception Ex )
{
Console.Error.WriteLine( Ex );
Console.ReadKey();
}
}
}

public class TestService : ITestService
{
public void Test( int i )
{
Console.WriteLine( $"{i}" );
}
}
}

#endif

namespace TestMain
{
using System.Linq;

static class TestMain
{
static void Main( string[] Args )
{
if( Args.Contains( "-server" ) )
{
TestServer.Server.ServerLoop();
}
else
{
TestClient.Client.ClientLoop();
}
}
}
}

```
Compile provided code under .Net Framework
Check full framework version:
```
start testapp.exe -server
start testapp.exe
```
code runs fine (check for ~40 sec), actually it may run forever

Compile provided code under .NetCore
Check netcore client version:
```
start testapp.exe -server
start testapp.netcore.exe
```
System will throw exception

**Expected behavior**
The system should run without exception, producing new line on console very 1 sec.

**Screenshots**
.Net Framework client and .Net Framework server operation
![framework3](https://user-images.githubusercontent.com/6769160/85307978-4ce13b00-b4b9-11ea-9b99-f4f41bd02c8b.JPG)

.Net Core client and .Net Framework server operation
![core](https://user-images.githubusercontent.com/6769160/85309620-874bd780-b4bb-11ea-91da-7dbc8870331c.JPG)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.