Skip to content

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

Open
@SergeAgeyev

Description

@SergeAgeyev

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<ITestService> TestFactory = new ChannelFactory<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 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

.Net Core client and .Net Framework server operation
core

Metadata

Metadata

Assignees

Labels

bugThis is a product bug.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions