zeromq / netmq

A 100% native C# implementation of ZeroMQ for .NET
Other
2.95k stars 744 forks source link

create socket ,init Signaler blocked #857

Closed GuojieLin closed 2 years ago

GuojieLin commented 4 years ago

invoke NetMQ.Core.Ctx.CreateSocket create new NetMQSocket, sometimes it be blocked.

i create a dump ,and output the thread stack

Child-SP         RetAddr          Call Site
000000001eaedca0 00007ffa13942c01 DomainBoundILStubClass.IL_STUB(IntPtr, Byte[], Int32 ByRef)
000000001eaedd80 00007ffa13942913 System.Net.SafeCloseSocket+InnerSafeCloseSocket.Accept(System.Net.SafeCloseSocket, Byte[], Int32 ByRef)
000000001eaeddb0 00007ff9b9748fb8 System.Net.Sockets.Socket.Accept()
000000001eaede10 00007ff9b9748be4 NetMQ.Core.Utils.Signaler..ctor()
000000001eaede80 00007ff9b974b958 NetMQ.Core.Mailbox..ctor(System.String)
000000001eaedef0 00007ff9b974b5d2 NetMQ.Core.SocketBase..ctor(NetMQ.Core.Ctx, Int32, Int32)
000000001eaedf50 00007ff9b974b243 NetMQ.Core.Patterns.Stream..ctor(NetMQ.Core.Ctx, Int32, Int32)
000000001eaedf90 00007ff9b97497f1 NetMQ.Core.SocketBase.Create(NetMQ.ZmqSocketType, NetMQ.Core.Ctx, Int32, Int32)
000000001eaedff0 00007ff9b97484b2 NetMQ.Core.Ctx.CreateSocket(NetMQ.ZmqSocketType)
000000001eaee080 00007ff9b9947af0 NetMQ.NetMQSocket..ctor(NetMQ.ZmqSocketType, System.String, DefaultAction)

And I reviewed the code.

public Signaler()
        {
            m_dummy = new byte[] { 0 };
            m_receiveDummy = new byte[1];

            // Create the socketpair for signaling.
            using (var listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Unspecified))
            {
                listener.NoDelay = true;
                listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);

                // using ephemeral port
                listener.Bind(new IPEndPoint(IPAddress.Loopback, 0));
                listener.Listen(1);

                m_writeSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Unspecified) { NoDelay = true };

                m_writeSocket.Connect(listener.LocalEndPoint);
                m_readSocket = listener.Accept();<- the blocked position
            }

            m_writeSocket.Blocking = false;
            m_readSocket.Blocking = false;
        }

I can't understand why the position is blocked.

Environment

NetMQ Version:    4.0.0.1
Operating System:  Windows Server 2008 R2
.NET Version:     .NET Framework 3.5.1

Expected behaviour

invoke NetMQ.Core.Ctx.CreateSocket create new NetMQSocket

Actual behaviour

CreateSocket Blocked,another thread create socket whill bei block ,due to a create socket lock.

public SocketBase CreateSocket(ZmqSocketType type)
{
    lock (m_slotSync)
    {
...

                // Create the socket and register its mailbox.
                SocketBase s = SocketBase.Create(type, this, slot, socketId);
...
    }
}

Steps to reproduce the behaviour

i don't know,There's a chance it's going to happen, i can't reproduce the behaviour.and I can't understand why this happened.

GuojieLin commented 4 years ago

m_writeSocket is a block socket

m_writeSocket.Connect(listener.LocalEndPoint); should be connect completed.

accept was blocked, because listen never accept new connection.

Is it possible to cause SO_REUSEADDR parameters?

stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had activity for 365 days. It will be closed if no further activity occurs within 56 days. Thank you for your contributions.