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

Humble corrections #915

Closed
wants to merge 23 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
3fd2fab
XMLRPC server accepts request from all local IP addresses. (#729) (#733)
mergify[bot] Jul 25, 2022
0bef9e0
[humble] Backport. Expand auto to the current time when passed to a H…
esteve Sep 7, 2022
9e7f721
Fix the component load help to mention load, not unload. (#756) (#757)
mergify[bot] Sep 22, 2022
74bd3eb
0.18.4
audrow Nov 7, 2022
1cf39d4
Add support use_sim_time for ros2 topic hz/bw/pub. (#754) (#777)
fujitatomoya Nov 22, 2022
2309182
Extend timeout to shutdown the command line process. (#783) (#784)
mergify[bot] Dec 15, 2022
4bcfdca
Fix network aware node issue (#785) (#786)
mergify[bot] Dec 19, 2022
13870ad
0.18.5
audrow Jan 10, 2023
e4364a7
Save method list via connection check to XMLRPC server. (#796) (#798)
mergify[bot] Feb 21, 2023
7d79d06
0.18.6
audrow Apr 25, 2023
7d5c743
Set automatically_declare_parameters_from_overrides in DirectNode. (#…
mergify[bot] May 6, 2023
86ae393
resolve #790 (#801) (#832)
mergify[bot] May 16, 2023
1580a03
Update ros2 param dump dosctring. (#837) (#840)
mergify[bot] Jul 10, 2023
38d4fa9
0.18.7
audrow Jul 18, 2023
9dd90cf
catch ExternalShutdownException ros2cli main. (#854) (#859)
mergify[bot] Nov 16, 2023
61f98ce
make handles not inheritable to prevent from blocking durning tab-com…
mergify[bot] Dec 27, 2023
7cd8084
0.18.8
audrow Jan 24, 2024
8df36c4
Conditionally use valid_signals. (#880)
clalancette Feb 6, 2024
9c02c6b
0.18.9
cottsay Feb 16, 2024
22d5810
call get_action_interfaces() properly. (#898) (#902)
mergify[bot] Apr 24, 2024
58b61c9
0.18.10
audrow May 15, 2024
0c8ae6d
ros2cli.node.daemon : try getting fdsize from /proc for open fd limit…
mergify[bot] Jun 4, 2024
40cbb32
string manipulation- python3.8 friendly
nidhicj Jun 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions ros2action/CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,29 @@
Changelog for package ros2action
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

0.18.10 (2024-05-15)
--------------------
* call get_action_interfaces() properly. (`#898 <https://github.com/ros2/ros2cli/issues/898>`_) (`#902 <https://github.com/ros2/ros2cli/issues/902>`_)
* Contributors: mergify[bot]

0.18.9 (2024-02-16)
-------------------

0.18.8 (2024-01-24)
-------------------

0.18.7 (2023-07-18)
-------------------

0.18.6 (2023-04-25)
-------------------

0.18.5 (2023-01-10)
-------------------

0.18.4 (2022-11-07)
-------------------

0.18.3 (2022-04-08)
-------------------

Expand Down
2 changes: 1 addition & 1 deletion ros2action/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="2">
<name>ros2action</name>
<version>0.18.3</version>
<version>0.18.10</version>
<description>
The action command for ROS 2 command line tools.
</description>
Expand Down
2 changes: 1 addition & 1 deletion ros2action/ros2action/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def action_name_completer(prefix, parsed_args, **kwargs):
def action_type_completer(**kwargs):
"""Callable returning a list of action types."""
action_types = []
for package_name, action_names in get_action_interfaces.items():
for package_name, action_names in get_action_interfaces().items():
for action_name in action_names:
action_types.append(f'{package_name}/{action_name}')
return action_types
Expand Down
2 changes: 1 addition & 1 deletion ros2action/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setup(
name=package_name,
version='0.18.3',
version='0.18.10',
packages=find_packages(exclude=['test']),
data_files=[
('share/' + package_name, ['package.xml']),
Expand Down
32 changes: 32 additions & 0 deletions ros2cli/CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,38 @@
Changelog for package ros2cli
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

0.18.10 (2024-05-15)
--------------------

0.18.9 (2024-02-16)
-------------------

0.18.8 (2024-01-24)
-------------------
* make handles not inheritable to prevent from blocking durning tab-completion (`#852 <https://github.com/ros2/ros2cli/issues/852>`_) (`#873 <https://github.com/ros2/ros2cli/issues/873>`_)
* catch ExternalShutdownException ros2cli main. (`#854 <https://github.com/ros2/ros2cli/issues/854>`_) (`#859 <https://github.com/ros2/ros2cli/issues/859>`_)
* Contributors: mergify[bot]

0.18.7 (2023-07-18)
-------------------
* Set automatically_declare_parameters_from_overrides in DirectNode. (`#813 <https://github.com/ros2/ros2cli/issues/813>`_) (`#815 <https://github.com/ros2/ros2cli/issues/815>`_)
* Contributors: mergify[bot]

0.18.6 (2023-04-25)
-------------------
* Save method list via connection check to XMLRPC server. (`#796 <https://github.com/ros2/ros2cli/issues/796>`_) (`#798 <https://github.com/ros2/ros2cli/issues/798>`_)
* Contributors: mergify[bot]

0.18.5 (2023-01-10)
-------------------
* Fix network aware node issue (`#785 <https://github.com/ros2/ros2cli/issues/785>`_) (`#786 <https://github.com/ros2/ros2cli/issues/786>`_)
* Contributors: mergify[bot]

0.18.4 (2022-11-07)
-------------------
* XMLRPC server accepts request from all local IP addresses. (`#729 <https://github.com/ros2/ros2cli/issues/729>`_) (`#733 <https://github.com/ros2/ros2cli/issues/733>`_)
* Contributors: mergify[bot]

0.18.3 (2022-04-08)
-------------------
* Fix importlib_metadata warning on Python 3.10. (`#706 <https://github.com/ros2/ros2cli/issues/706>`_)
Expand Down
2 changes: 1 addition & 1 deletion ros2cli/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<?xml-model href="http://download.ros.org/schema/package_format2.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="2">
<name>ros2cli</name>
<version>0.18.3</version>
<version>0.18.10</version>
<description>
Framework for ROS 2 command line tools.
</description>
Expand Down
4 changes: 4 additions & 0 deletions ros2cli/ros2cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import signal
import sys

from rclpy.executors import ExternalShutdownException

from ros2cli.command import add_subparsers_on_demand


Expand Down Expand Up @@ -89,6 +91,8 @@ def main(*, script_name='ros2', argv=None, description=None, extension=None):
rc = extension.main(parser=parser, args=args)
except KeyboardInterrupt:
rc = signal.SIGINT
except ExternalShutdownException:
rc = signal.SIGTERM
except RuntimeError as e:
rc = str(e)
return rc
43 changes: 37 additions & 6 deletions ros2cli/ros2cli/node/daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

import errno
import functools
import os
import platform
import socket

import rclpy
Expand All @@ -39,18 +41,18 @@ def __init__(self, args):
@property
def connected(self):
try:
self._proxy.system.listMethods()
self._methods = [
method
for method in self._proxy.system.listMethods()
if not method.startswith('system.')
]
except ConnectionRefusedError:
return False
return True

@property
def methods(self):
return [
method
for method in self._proxy.system.listMethods()
if not method.startswith('system.')
]
return self._methods

def __enter__(self):
self._proxy.__enter__()
Expand Down Expand Up @@ -130,6 +132,35 @@ def spawn_daemon(args, timeout=None, debug=False):
return False
raise

# During tab completion on the ros2 tooling, we can get here and attempt to spawn a daemon.
# In that scenario, there may be open file descriptors that can prevent us from successfully
# daemonizing, and instead cause the terminal to hang. Here we mark all file handles except
# for 0, 1, 2, and the server socket as non-inheritable, which will cause daemonize() to close
# those file descriptors. See https://github.com/ros2/ros2cli/issues/851 for more details.
if platform.system() != 'Windows':
# Some unices have a high soft_limit; read fdsize if available.
fdlimit = None
try:
string_to_find = 'FDSize:'
with open('/proc/self/status', 'r') as f:
for line in f:
if line.startswith(string_to_find):
fdlimit = int(line[len(string_to_find):].strip())
break
except (FileNotFoundError, ValueError):
pass
# The soft limit might be quite high on some systems.
if fdlimit is None:
import resource
fdlimit, _ = resource.getrlimit(resource.RLIMIT_NOFILE)
for i in range(3, fdlimit):
try:
if i != server.socket.fileno() and os.get_inheritable(i):
os.set_inheritable(i, False)
except OSError:
# Just in case the file handles might be [3(closed), ..., 8(pipe handle), ...]
continue

# Transfer XMLRPC server to daemon (and the socket with it).
try:
tags = {
Expand Down
2 changes: 1 addition & 1 deletion ros2cli/ros2cli/node/direct.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def timer_callback():
start_parameter_services=start_parameter_services,
parameter_overrides=[
Parameter('use_sim_time', value=use_sim_time)
])
], automatically_declare_parameters_from_overrides=True)

timeout = getattr(args, 'spin_time', DEFAULT_TIMEOUT)
timer = self.node.create_timer(timeout, timer_callback)
Expand Down
33 changes: 16 additions & 17 deletions ros2cli/ros2cli/node/network_aware.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,23 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from collections import defaultdict
import functools
import inspect

import netifaces
import rclpy

from ros2cli.helpers import before_invocation

from ros2cli.node.direct import DirectNode


def get_interfaces_ip_addresses():
addresses_by_interfaces = {}
for (kind, info_list) in netifaces.gateways().items():
if kind not in (netifaces.AF_INET, netifaces.AF_INET6):
continue
print('Interface kind: {}, info: {}'.format(kind, info_list))
addresses_by_interfaces[kind] = {}
for info in info_list:
interface_name = info[1]
addresses_by_interfaces[kind][interface_name] = (
netifaces.ifaddresses(interface_name)[kind][0]['addr']
)
print('Addresses by interfaces: {}'.format(addresses_by_interfaces))
addresses_by_interfaces = defaultdict(functools.partial(defaultdict, set))
for interface_name in netifaces.interfaces():
for kind, info_list in netifaces.ifaddresses(interface_name).items():
for info in info_list:
addresses_by_interfaces[kind][interface_name].add(info['addr'])
print(f'Addresses by interfaces: {addresses_by_interfaces}')
return addresses_by_interfaces


Expand All @@ -56,8 +50,13 @@ def __getattr__(self, name):
attr = getattr(self.node, name)

if inspect.ismethod(attr):
return before_invocation(
attr, self.reset_if_addresses_changed)
@functools.wraps(attr)
def wrapper(*args, **kwargs):
self.reset_if_addresses_changed()
# The attribute has to be get here again, in case self.node changed
return getattr(self.node, name)(*args, **kwargs)
wrapper.__signature__ = inspect.signature(attr)
return wrapper
self.reset_if_addresses_changed()
return attr

Expand All @@ -72,4 +71,4 @@ def reset_if_addresses_changed(self):
rclpy.shutdown()
self.node = DirectNode(self.args)
self.node.__enter__()
print('Daemon node was reset')
print('Network interfaces changed, daemon node was reset!')
3 changes: 3 additions & 0 deletions ros2cli/ros2cli/node/strategy.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ def __init__(self, args):
if use_daemon and is_daemon_running(args):
self._daemon_node = DaemonNode(args)
self._direct_node = None
if not self._daemon_node.connected:
self._direct_node = DirectNode(args)
self._daemon_node = None
else:
if use_daemon:
spawn_daemon(args)
Expand Down
15 changes: 14 additions & 1 deletion ros2cli/ros2cli/xmlrpc/local_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,19 @@
from xmlrpc.server import SimpleXMLRPCRequestHandler # noqa
from xmlrpc.server import SimpleXMLRPCServer

import netifaces


def get_local_ipaddrs():
iplist = []
interfaces = netifaces.interfaces()
for interface in interfaces:
addrs = netifaces.ifaddresses(interface)
if netifaces.AF_INET in addrs.keys():
for value in addrs[netifaces.AF_INET]:
iplist.append(value['addr'])
return iplist


class LocalXMLRPCServer(SimpleXMLRPCServer):

Expand All @@ -37,6 +50,6 @@ def get_request(self):
return sock, addr

def verify_request(self, request, client_address):
if client_address[0] != '127.0.0.1':
if client_address[0] not in get_local_ipaddrs():
return False
return super(LocalXMLRPCServer, self).verify_request(request, client_address)
2 changes: 1 addition & 1 deletion ros2cli/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

setup(
name='ros2cli',
version='0.18.3',
version='0.18.10',
packages=find_packages(exclude=['test']),
extras_require={
'completion': ['argcomplete'],
Expand Down
4 changes: 4 additions & 0 deletions ros2cli/test/test_daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ def daemon_node():
assert shutdown_daemon(args=[], timeout=5.0)
assert spawn_daemon(args=[], timeout=5.0)
with DaemonNode(args=[]) as node:
if not node.connected:
pytest.fail(
f'failed to connect daemon {TEST_NODE_NAMESPACE}/{TEST_NODE_NAME}'
)
attempts = 3
delay_between_attempts = 2 # seconds
for _ in range(attempts):
Expand Down
10 changes: 10 additions & 0 deletions ros2cli/test/test_strategy.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ def test_with_daemon_running(enforce_daemon_is_running):
assert direct is not None


def test_with_daemon_spawn(enforce_no_daemon_is_running):
with NodeStrategy(args=[]) as node:
assert node._daemon_node is None
assert node._direct_node is not None
# Daemon should be spawned by NodeStrategy call above
with NodeStrategy(args=[]) as node:
assert node._daemon_node is not None
assert node._direct_node is None


def test_with_no_daemon_running(enforce_no_daemon_is_running):
with NodeStrategy(args=[]) as node:
assert node._daemon_node is None
Expand Down
21 changes: 21 additions & 0 deletions ros2cli_test_interfaces/CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,27 @@
Changelog for package ros2cli_test_interfaces
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

0.18.10 (2024-05-15)
--------------------

0.18.9 (2024-02-16)
-------------------

0.18.8 (2024-01-24)
-------------------

0.18.7 (2023-07-18)
-------------------

0.18.6 (2023-04-25)
-------------------

0.18.5 (2023-01-10)
-------------------

0.18.4 (2022-11-07)
-------------------

0.18.3 (2022-04-08)
-------------------

Expand Down
2 changes: 1 addition & 1 deletion ros2cli_test_interfaces/package.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>ros2cli_test_interfaces</name>
<version>0.18.3</version>
<version>0.18.10</version>
<description>A package containing interface definitions for testing ros2cli.</description>

<maintainer email="[email protected]">Aditya Pande</maintainer>
Expand Down
Loading