We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[BUG]: Multi-rank on same device
### 🐛 Describe the bug

When I use colossalai CLI with 2 node, I got an error "rank 8 and rank 0 both on CUDA device d000"
I have examined my scripts and command. And torchrun works well.

The error msg is:
```
Error: failed to run torchrun --nproc_per_node=8 --nnodes=2 --node_rank=0 --master_addr=192.168.0.64 --master_port=29500 benchmark.py -c 7b --plugin zero --zero 1 -l 2048 -g -b 10 on 192.168.0.64, is localhost: True, exception: I/O operation on closed file
Error: failed to run torchrun --nproc_per_node=8 --nnodes=2 --node_rank=1 --master_addr=192.168.0.64 --master_port=29500 benchmark.py -c 7b --plugin zero --zero 1 -l 2048 -g -b 10 on 192.168.0.189, is localhost: True, exception: I/O operation on closed file
```


### Environment

_No response_
[tensor] fix some unittests

[tensor] fix some unittests


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `colossalai/cli/launcher/hostinfo.py`
Content:
```
1 import socket
2 from typing import List
3 
4 
5 class HostInfo:
6     """
7     A data class to store host connection-related data.
8 
9     Args:
10         hostname (str): name or IP address of the host
11         port (str): the port for ssh connection
12     """
13 
14     def __init__(
15         self,
16         hostname: str,
17         port: str = None,
18     ):
19         self.hostname = hostname
20         self.port = port
21         self.is_local_host = HostInfo.is_host_localhost(hostname, port)
22 
23     @staticmethod
24     def is_host_localhost(hostname: str, port: str = None) -> None:
25         """
26         Check if the host refers to the local machine.
27 
28         Args:
29             hostname (str): name or IP address of the host
30             port (str): the port for ssh connection
31 
32         Returns:
33             bool: True if it is local, False otherwise
34         """
35 
36         if port is None:
37             port = 22    # no port specified, lets just use the ssh port
38 
39         # socket.getfqdn("127.0.0.1") does not return localhost
40         # on some users' machines
41         # thus, we directly return True if hostname is localhost, 127.0.0.1 or 0.0.0.0
42         if hostname in ("localhost", "127.0.0.1", "0.0.0.0"):
43             return True
44 
45         hostname = socket.getfqdn(hostname)
46         localhost = socket.gethostname()
47         localaddrs = socket.getaddrinfo(localhost, port)
48         targetaddrs = socket.getaddrinfo(hostname, port)
49         for (family, socktype, proto, canonname, sockaddr) in localaddrs:
50             for (rfamily, rsocktype, rproto, rcanonname, rsockaddr) in targetaddrs:
51                 if rsockaddr[0] == sockaddr[0]:
52                     return True
53         return False
54 
55     def __str__(self):
56         return f'hostname: {self.hostname}, port: {self.port}'
57 
58     def __repr__(self):
59         return self.__str__()
60 
61 
62 class HostInfoList:
63     """
64     A data class to store a list of HostInfo objects.
65     """
66 
67     def __init__(self):
68         self.hostinfo_list = []
69 
70     def append(self, hostinfo: HostInfo) -> None:
71         """
72         Add an HostInfo object to the list.
73 
74         Args:
75             hostinfo (HostInfo): host information
76         """
77 
78         self.hostinfo_list.append(hostinfo)
79 
80     def remove(self, hostname: str) -> None:
81         """
82         Add an HostInfo object to the list.
83 
84         Args:
85             hostname (str): the name of the host
86         """
87 
88         hostinfo = self.get_hostinfo(hostname)
89         self.hostinfo_list.remove(hostinfo)
90 
91     def get_hostinfo(self, hostname: str) -> HostInfo:
92         """
93         Return the HostInfo object which matches with the hostname.
94 
95         Args:
96             hostname (str): the name of the host
97 
98         Returns:
99             hostinfo (HostInfo): the HostInfo object which matches with the hostname
100         """
101 
102         for hostinfo in self.hostinfo_list:
103             if hostinfo.hostname == hostname:
104                 return hostinfo
105 
106         raise Exception(f"Hostname {hostname} is not found")
107 
108     def has(self, hostname: str) -> bool:
109         """
110         Check if the hostname has been added.
111 
112         Args:
113             hostname (str): the name of the host
114 
115         Returns:
116             bool: True if added, False otherwise
117         """
118         for hostinfo in self.hostinfo_list:
119             if hostinfo.hostname == hostname:
120                 return True
121         return False
122 
123     def __iter__(self):
124         return iter(self.hostinfo_list)
125 
126     def __len__(self):
127         return len(self.hostinfo_list)
128
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/colossalai/cli/launcher/hostinfo.py b/colossalai/cli/launcher/hostinfo.py
--- a/colossalai/cli/launcher/hostinfo.py
+++ b/colossalai/cli/launcher/hostinfo.py
@@ -46,11 +46,8 @@
         localhost = socket.gethostname()
         localaddrs = socket.getaddrinfo(localhost, port)
         targetaddrs = socket.getaddrinfo(hostname, port)
-        for (family, socktype, proto, canonname, sockaddr) in localaddrs:
-            for (rfamily, rsocktype, rproto, rcanonname, rsockaddr) in targetaddrs:
-                if rsockaddr[0] == sockaddr[0]:
-                    return True
-        return False
+
+        return localaddrs == targetaddrs
 
     def __str__(self):
         return f'hostname: {self.hostname}, port: {self.port}'

{"golden_diff": "diff --git a/colossalai/cli/launcher/hostinfo.py b/colossalai/cli/launcher/hostinfo.py\n--- a/colossalai/cli/launcher/hostinfo.py\n+++ b/colossalai/cli/launcher/hostinfo.py\n@@ -46,11 +46,8 @@\n         localhost = socket.gethostname()\n         localaddrs = socket.getaddrinfo(localhost, port)\n         targetaddrs = socket.getaddrinfo(hostname, port)\n-        for (family, socktype, proto, canonname, sockaddr) in localaddrs:\n-            for (rfamily, rsocktype, rproto, rcanonname, rsockaddr) in targetaddrs:\n-                if rsockaddr[0] == sockaddr[0]:\n-                    return True\n-        return False\n+\n+        return localaddrs == targetaddrs\n \n     def __str__(self):\n         return f'hostname: {self.hostname}, port: {self.port}'\n", "issue": "[BUG]: Multi-rank on same device\n### \ud83d\udc1b Describe the bug\n\nWhen I use colossalai CLI with 2 node, I got an error \"rank 8 and rank 0 both on CUDA device d000\"\r\nI have examined my scripts and command. And torchrun works well.\r\n\r\nThe error msg is:\r\n```\r\nError: failed to run torchrun --nproc_per_node=8 --nnodes=2 --node_rank=0 --master_addr=192.168.0.64 --master_port=29500 benchmark.py -c 7b --plugin zero --zero 1 -l 2048 -g -b 10 on 192.168.0.64, is localhost: True, exception: I/O operation on closed file\r\nError: failed to run torchrun --nproc_per_node=8 --nnodes=2 --node_rank=1 --master_addr=192.168.0.64 --master_port=29500 benchmark.py -c 7b --plugin zero --zero 1 -l 2048 -g -b 10 on 192.168.0.189, is localhost: True, exception: I/O operation on closed file\r\n```\r\n\n\n### Environment\n\n_No response_\n[tensor] fix some unittests\n\n[tensor] fix some unittests\n\n", "before_files": [{"content": "import socket\nfrom typing import List\n\n\nclass HostInfo:\n    \"\"\"\n    A data class to store host connection-related data.\n\n    Args:\n        hostname (str): name or IP address of the host\n        port (str): the port for ssh connection\n    \"\"\"\n\n    def __init__(\n        self,\n        hostname: str,\n        port: str = None,\n    ):\n        self.hostname = hostname\n        self.port = port\n        self.is_local_host = HostInfo.is_host_localhost(hostname, port)\n\n    @staticmethod\n    def is_host_localhost(hostname: str, port: str = None) -> None:\n        \"\"\"\n        Check if the host refers to the local machine.\n\n        Args:\n            hostname (str): name or IP address of the host\n            port (str): the port for ssh connection\n\n        Returns:\n            bool: True if it is local, False otherwise\n        \"\"\"\n\n        if port is None:\n            port = 22    # no port specified, lets just use the ssh port\n\n        # socket.getfqdn(\"127.0.0.1\") does not return localhost\n        # on some users' machines\n        # thus, we directly return True if hostname is localhost, 127.0.0.1 or 0.0.0.0\n        if hostname in (\"localhost\", \"127.0.0.1\", \"0.0.0.0\"):\n            return True\n\n        hostname = socket.getfqdn(hostname)\n        localhost = socket.gethostname()\n        localaddrs = socket.getaddrinfo(localhost, port)\n        targetaddrs = socket.getaddrinfo(hostname, port)\n        for (family, socktype, proto, canonname, sockaddr) in localaddrs:\n            for (rfamily, rsocktype, rproto, rcanonname, rsockaddr) in targetaddrs:\n                if rsockaddr[0] == sockaddr[0]:\n                    return True\n        return False\n\n    def __str__(self):\n        return f'hostname: {self.hostname}, port: {self.port}'\n\n    def __repr__(self):\n        return self.__str__()\n\n\nclass HostInfoList:\n    \"\"\"\n    A data class to store a list of HostInfo objects.\n    \"\"\"\n\n    def __init__(self):\n        self.hostinfo_list = []\n\n    def append(self, hostinfo: HostInfo) -> None:\n        \"\"\"\n        Add an HostInfo object to the list.\n\n        Args:\n            hostinfo (HostInfo): host information\n        \"\"\"\n\n        self.hostinfo_list.append(hostinfo)\n\n    def remove(self, hostname: str) -> None:\n        \"\"\"\n        Add an HostInfo object to the list.\n\n        Args:\n            hostname (str): the name of the host\n        \"\"\"\n\n        hostinfo = self.get_hostinfo(hostname)\n        self.hostinfo_list.remove(hostinfo)\n\n    def get_hostinfo(self, hostname: str) -> HostInfo:\n        \"\"\"\n        Return the HostInfo object which matches with the hostname.\n\n        Args:\n            hostname (str): the name of the host\n\n        Returns:\n            hostinfo (HostInfo): the HostInfo object which matches with the hostname\n        \"\"\"\n\n        for hostinfo in self.hostinfo_list:\n            if hostinfo.hostname == hostname:\n                return hostinfo\n\n        raise Exception(f\"Hostname {hostname} is not found\")\n\n    def has(self, hostname: str) -> bool:\n        \"\"\"\n        Check if the hostname has been added.\n\n        Args:\n            hostname (str): the name of the host\n\n        Returns:\n            bool: True if added, False otherwise\n        \"\"\"\n        for hostinfo in self.hostinfo_list:\n            if hostinfo.hostname == hostname:\n                return True\n        return False\n\n    def __iter__(self):\n        return iter(self.hostinfo_list)\n\n    def __len__(self):\n        return len(self.hostinfo_list)\n", "path": "colossalai/cli/launcher/hostinfo.py"}], "after_files": [{"content": "import socket\nfrom typing import List\n\n\nclass HostInfo:\n    \"\"\"\n    A data class to store host connection-related data.\n\n    Args:\n        hostname (str): name or IP address of the host\n        port (str): the port for ssh connection\n    \"\"\"\n\n    def __init__(\n        self,\n        hostname: str,\n        port: str = None,\n    ):\n        self.hostname = hostname\n        self.port = port\n        self.is_local_host = HostInfo.is_host_localhost(hostname, port)\n\n    @staticmethod\n    def is_host_localhost(hostname: str, port: str = None) -> None:\n        \"\"\"\n        Check if the host refers to the local machine.\n\n        Args:\n            hostname (str): name or IP address of the host\n            port (str): the port for ssh connection\n\n        Returns:\n            bool: True if it is local, False otherwise\n        \"\"\"\n\n        if port is None:\n            port = 22    # no port specified, lets just use the ssh port\n\n        # socket.getfqdn(\"127.0.0.1\") does not return localhost\n        # on some users' machines\n        # thus, we directly return True if hostname is localhost, 127.0.0.1 or 0.0.0.0\n        if hostname in (\"localhost\", \"127.0.0.1\", \"0.0.0.0\"):\n            return True\n\n        hostname = socket.getfqdn(hostname)\n        localhost = socket.gethostname()\n        localaddrs = socket.getaddrinfo(localhost, port)\n        targetaddrs = socket.getaddrinfo(hostname, port)\n\n        return localaddrs == targetaddrs\n\n    def __str__(self):\n        return f'hostname: {self.hostname}, port: {self.port}'\n\n    def __repr__(self):\n        return self.__str__()\n\n\nclass HostInfoList:\n    \"\"\"\n    A data class to store a list of HostInfo objects.\n    \"\"\"\n\n    def __init__(self):\n        self.hostinfo_list = []\n\n    def append(self, hostinfo: HostInfo) -> None:\n        \"\"\"\n        Add an HostInfo object to the list.\n\n        Args:\n            hostinfo (HostInfo): host information\n        \"\"\"\n\n        self.hostinfo_list.append(hostinfo)\n\n    def remove(self, hostname: str) -> None:\n        \"\"\"\n        Add an HostInfo object to the list.\n\n        Args:\n            hostname (str): the name of the host\n        \"\"\"\n\n        hostinfo = self.get_hostinfo(hostname)\n        self.hostinfo_list.remove(hostinfo)\n\n    def get_hostinfo(self, hostname: str) -> HostInfo:\n        \"\"\"\n        Return the HostInfo object which matches with the hostname.\n\n        Args:\n            hostname (str): the name of the host\n\n        Returns:\n            hostinfo (HostInfo): the HostInfo object which matches with the hostname\n        \"\"\"\n\n        for hostinfo in self.hostinfo_list:\n            if hostinfo.hostname == hostname:\n                return hostinfo\n\n        raise Exception(f\"Hostname {hostname} is not found\")\n\n    def has(self, hostname: str) -> bool:\n        \"\"\"\n        Check if the hostname has been added.\n\n        Args:\n            hostname (str): the name of the host\n\n        Returns:\n            bool: True if added, False otherwise\n        \"\"\"\n        for hostinfo in self.hostinfo_list:\n            if hostinfo.hostname == hostname:\n                return True\n        return False\n\n    def __iter__(self):\n        return iter(self.hostinfo_list)\n\n    def __len__(self):\n        return len(self.hostinfo_list)\n", "path": "colossalai/cli/launcher/hostinfo.py"}]}