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

NetTcp channel closes while client call in progress in 6.0.0-rc.23205.4 #5134

Closed
cmborg opened this issue Apr 27, 2023 · 1 comment · Fixed by #5138
Closed

NetTcp channel closes while client call in progress in 6.0.0-rc.23205.4 #5134

cmborg opened this issue Apr 27, 2023 · 1 comment · Fixed by #5138
Assignees
Labels

Comments

@cmborg
Copy link

cmborg commented Apr 27, 2023

After the NetTcp channel is opened you start using it. Then it seams like the channel is closed by the client if a call is in progress when the timeout, set in OpenTimeout, expires from the time you CreateChannel. This happens independent of the setting of the RecieveTimeout, SendTimeout and CloseTimeout.

This issue is new since System.ServiceModel.NetTcp Version 4.10.2

When using WireShark I can see that the client sends [RST,ACK] (close).

Reproduction: Below a working sample of console app with both server and client.

Program.cs

using CoreWCF;
using CoreWCF.Configuration;
using Microsoft.AspNetCore.Builder;
using System.Diagnostics;
internal class Program
{
    public static async Task Main()
    {
        int port = 50000;
        string baseAddress = $"net.tcp://localhost:{port}";
        string serviceAddress = $"{baseAddress}/EchoService";
        string testString = new string('a', 3000);

        var builder = WebApplication.CreateBuilder();
        builder.WebHost.UseNetTcp(port);
        builder.Services.AddServiceModelServices();
        var app = builder.Build();
        app.UseServiceModel(serviceBuilder =>
        {
            serviceBuilder.AddService<EchoService>();
            var binding = new NetTcpBinding();
            serviceBuilder.AddServiceEndpoint(typeof(EchoService), typeof(IEchoService), 
                    binding, new Uri(serviceAddress), new Uri(baseAddress));
        });
        await app.StartAsync();

        var binding = new System.ServiceModel.NetTcpBinding
        {
            OpenTimeout = TimeSpan.FromSeconds(10),

            // make sure they dont interfere the test
            ReceiveTimeout = TimeSpan.FromMinutes(15),
            SendTimeout = TimeSpan.FromMinutes(15),
            CloseTimeout = TimeSpan.FromMinutes(15),
        };

        var factory = new System.ServiceModel.ChannelFactory<IEchoService>(binding, 
                new System.ServiceModel.EndpointAddress(new Uri(serviceAddress)));
        var channel = factory.CreateChannel();
        var dt = DateTime.Now;
        System.ServiceModel.Channels.IChannel ichannel = (System.ServiceModel.Channels.IChannel)channel;
        ichannel.Open();
        var result1 = await channel.EchoString(testString); // this works
        var result2 = await channel.EchoString(testString); // this throws System.ServiceModel.CommunicationException
    }
}

[CoreWCF.ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
public class EchoService : IEchoService
{
    public async Task<string> EchoString(string echo)
    {
        await Task.Delay(TimeSpan.FromSeconds(6));
        return echo;
    }
}

[System.ServiceModel.ServiceContract]
public interface IEchoService
{
    [System.ServiceModel.OperationContract]
    Task<string> EchoString(string echo);
}

.csproj file:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0-windows</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>
  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="CoreWCF.ConfigurationManager" Version="1.4.0-preview1" />
    <PackageReference Include="System.ServiceModel.NetTcp" Version="6.0.0-rc.23205.4" />
		
    <!-- Works with this version -->
    <!--<PackageReference Include="System.ServiceModel.NetTcp" Version="4.10.2" />-->
  </ItemGroup>
</Project>
@mconnew
Copy link
Member

mconnew commented May 3, 2023

I found the problem. SocketConnection.OnReceiveTimeout isn't checking _receiveTimerEnabled. Creating and removing timers is expensive, so when we want to cancel the timer, we just set _receiveTimerEnabled to false. Without that check, when the timer fires after being "cancelled" it's closing the connection as though we've actually timed out. There's the same problem on the send timer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants