Thespian icon indicating copy to clipboard operation
Thespian copied to clipboard

Invalid Socket Address on Mac with Multiproc bases when disconnected from network.

Open bryang-spindance opened this issue 2 years ago • 1 comments

Similar to #28

I found that on Mac OSX (not tested on Windows), when I disconnect from the network (not internet, but local network) I receive the following error:

Traceback (most recent call last):
  File "start.py", line 23, in <module>
    asys = ActorSystem('multiprocTCPBase')
  File "/Users/username/project/venv/lib/python3.7/site-packages/thespian/actors.py", line 640, in __init__
    systemBase, capabilities, logDefs)
  File "/Users/username/project/venv/lib/python3.7/site-packages/thespian/actors.py", line 678, in _startupActorSys
    systemBase = sbc(self, logDefs=logDefs)
  File "/Users/username/project/venv/lib/python3.7/site-packages/thespian/system/multiprocTCPBase.py", line 28, in __init__
    super(ActorSystemBase, self).__init__(system, logDefs)
  File "/Users/username/project/venv/lib/python3.7/site-packages/thespian/system/multiprocCommon.py", line 82, in __init__
    self.mpcontext)
  File "/Users/username/project/venv/lib/python3.7/site-packages/thespian/system/transport/TCPTransport.py", line 275, in __init__
    templateAddr     = ActorAddress(TCPv4ActorAddress(None, 0, external = externalAddr))
  File "/Users/username/project/venv/lib/python3.7/site-packages/thespian/system/transport/IPBase.py", line 275, in __init__
    external)
  File "/Users/username/project/venv/lib/python3.7/site-packages/thespian/system/transport/IPBase.py", line 171, in __init__
    raise RuntimeError('Unable to determine valid external socket address.')
RuntimeError: Unable to determine valid external socket address.

So I went into IPBase.py and printed out the baseaddr it was receiving on line 110.

class IPActorAddress(object):
    def __init__(self, af, socktype, proto, baseaddr, port, external=False):
        """If external is "truthy", this should be an address that is reachable
           from external nodes.  If external is false, this is usually
           an address that is going to be listened on locally.  For
           example, "0.0.0.0" can be used for a non-external
           listen-any address, but cannot be used for sending messages.

           A "truthy" value of external can be an external address to
           try.  Using the address of the Convention Leader (if any)
           is recommended to ensure that the address chosen is
           appropriate for the network supporting the Convention.  By
           default, the address is Go Daddy's public webserver
           address.
        """
       
        print(baseaddr)

Here is where it differs between Mac and Linux. On my Mac, the baseaddr is None. On Linux, the baseaddr prints None and then this class is instantiated again and it prints 127.0.0.1 as expected and it will cycle between printing None and 127.0.0.1 many times but the actor system appears to be working as expected at this point.

Then I went into TCPTransport.py and printed out the value of externalAddr on line 275. Both Mac and Linux give me the same result of ('', 1900) when disconnected from networks.

class TCPTransport(asyncTransportBase, wakeupTransportBase):
    "A transport using TCP IPv4 sockets for communications."

    def __init__(self, initType, *args):
        super(TCPTransport, self).__init__()

        if isinstance(initType, ExternalInterfaceTransportInit):
            # External process that is going to talk "in".  There is
            # no parent, and the child is the systemAdmin.
            capabilities, logDefs, concurrency_context = args
            adminRouting     = False
            self.txOnly      = False  # communications from outside-in are always local and therefore not restricted.
            convAddr = capabilities.get(CONV_ADDR_IPV4_CAPABILITY, '')
            if isinstance(convAddr, list):
                convAddr = convAddr[0]
            if convAddr and type(convAddr) == type( (1,2) ):
                externalAddr = convAddr
            elif type(convAddr) == type("") and ':' in convAddr:
                externalAddr = convAddr.split(':')
                externalAddr = externalAddr[0], int(externalAddr[1])
            else:
                externalAddr = (convAddr, capabilities.get('Admin Port', DEFAULT_ADMIN_PORT))
            print('externalAddr:', externalAddr) # <================ HERE IS THE PRINT STATEMENT====================
            templateAddr     = ActorAddress(TCPv4ActorAddress(None, 0, external = externalAddr))
            self._adminAddr  = TCPTransport.getAdminAddr(capabilities)
            self._parentAddr = None
            isAdmin = False

This is the extent to which I have debugged this issue due to project deadlines but I figured I'd make you aware of this issue. In the mean time, I am going to switch my development environment to Linux.

Thank you for your time.

bryang-spindance avatar Mar 08 '22 14:03 bryang-spindance