Skip to content

Commit d0963d5

Browse files
committed
Memory leak in client when using python wrapper to send request to service
ros2/rclpy#822 Signed-off-by: Tomoya Fujita <[email protected]>
1 parent a91d264 commit d0963d5

File tree

12 files changed

+159
-2
lines changed

12 files changed

+159
-2
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,7 @@ test sample to reproduce and investigate issues, easy to distribute.
1010
## prover_rclpy
1111

1212
[rclpy](https://github.com/ros2/rclpy) related issue and reproducible tests.
13+
14+
### prover_interfaces
15+
16+
only applied to prover packages.

prover_interfaces/CMakeLists.txt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
cmake_minimum_required(VERSION 3.8)
2+
project(prover_interfaces)
3+
4+
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
5+
add_compile_options(-Wall -Wextra -Wpedantic)
6+
endif()
7+
8+
# find dependencies
9+
find_package(ament_cmake REQUIRED)
10+
find_package(rosidl_default_generators REQUIRED)
11+
# uncomment the following section in order to fill in
12+
# further dependencies manually.
13+
# find_package(<dependency> REQUIRED)
14+
15+
set(srv_files
16+
"srv/Huge.srv"
17+
)
18+
rosidl_generate_interfaces(${PROJECT_NAME}
19+
${srv_files}
20+
ADD_LINTER_TESTS
21+
)
22+
23+
if(BUILD_TESTING)
24+
find_package(ament_lint_auto REQUIRED)
25+
# the following line skips the linter which checks for copyrights
26+
# uncomment the line when a copyright and license is not present in all source files
27+
#set(ament_cmake_copyright_FOUND TRUE)
28+
# the following line skips cpplint (only works in a git repo)
29+
# uncomment the line when this package is not in a git repo
30+
#set(ament_cmake_cpplint_FOUND TRUE)
31+
ament_lint_auto_find_test_dependencies()
32+
endif()
33+
34+
ament_export_dependencies(rosidl_default_runtime)
35+
36+
ament_package()

prover_interfaces/package.xml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0"?>
2+
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
3+
<package format="3">
4+
<name>prover_interfaces</name>
5+
<version>0.0.0</version>
6+
<description>only applied to prover packages.</description>
7+
<maintainer email="[email protected]">Tomoya Fujita</maintainer>
8+
<license>Apache License 2.0</license>
9+
10+
<author email="[email protected]">Tomoya Fujita</author>
11+
12+
<buildtool_depend>ament_cmake</buildtool_depend>
13+
<buildtool_depend>rosidl_default_generators</buildtool_depend>
14+
15+
<exec_depend>rosidl_default_runtime</exec_depend>
16+
17+
<test_depend>ament_lint_auto</test_depend>
18+
<test_depend>ament_lint_common</test_depend>
19+
20+
<member_of_group>rosidl_interface_packages</member_of_group>
21+
22+
<export>
23+
<build_type>ament_cmake</build_type>
24+
</export>
25+
</package>

prover_interfaces/srv/Huge.srv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
byte[1048576] input_tensor
2+
---
3+
byte[1048576] output_tensor

prover_rclpy/package.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
<exec_depend>example_interfaces</exec_depend>
1515
<exec_depend>rclpy</exec_depend>
1616
<exec_depend>std_msgs</exec_depend>
17+
<exec_depend>prover_interfaces</exec_depend>
1718

1819
<test_depend>ament_copyright</test_depend>
1920
<test_depend>ament_flake8</test_depend>

prover_rclpy/setup.cfg

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
[develop]
2-
script-dir=$base/lib/prover_rclpy
2+
script_dir=$base/lib/prover_rclpy
33
[install]
4-
install-scripts=$base/lib/prover_rclpy
4+
install_scripts=$base/lib/prover_rclpy

prover_rclpy/setup.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
#'rclpy_585 = src.rclpy_585:main',
3838
#'rclpy_760 = src.rclpy_760:main',
3939
'rclpy_792 = src.rclpy_792:main',
40+
'rclpy_client_822 = src.rclpy_client_822:main',
41+
'rclpy_server_822 = src.rclpy_server_822:main',
4042
],
4143
},
4244
)
Binary file not shown.
Binary file not shown.
Binary file not shown.

prover_rclpy/src/rclpy_client_822.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import sys
2+
3+
from prover_interfaces.srv import Huge
4+
import rclpy
5+
from rclpy.node import Node
6+
7+
import time
8+
9+
10+
class MinimalClientAsync(Node):
11+
12+
def __init__(self):
13+
super().__init__('minimal_client_async')
14+
self.cli = self.create_client(Huge, 'huge')
15+
while not self.cli.wait_for_service(timeout_sec=5.0):
16+
self.get_logger().info('service not available, waiting again...')
17+
self.req = Huge.Request()
18+
19+
def send_request(self):
20+
self.future = self.cli.call_async(self.req)
21+
22+
23+
def main(args=None):
24+
rclpy.init(args=args)
25+
26+
minimal_client = MinimalClientAsync()
27+
for _ in range(1000):
28+
minimal_client.get_logger().info('Sending async request...')
29+
minimal_client.send_request()
30+
31+
while rclpy.ok():
32+
rclpy.spin_once(minimal_client)
33+
time.sleep(0.1)
34+
if minimal_client.future.done():
35+
try:
36+
response = minimal_client.future.result()
37+
except Exception as e:
38+
minimal_client.get_logger().info(
39+
'Service call failed %r' % (e,))
40+
else:
41+
minimal_client.get_logger().info('Result received!!!')
42+
break
43+
44+
45+
minimal_client.destroy_node()
46+
rclpy.shutdown()
47+
48+
49+
if __name__ == '__main__':
50+
main()

prover_rclpy/src/rclpy_server_822.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import sys
2+
3+
from prover_interfaces.srv import Huge
4+
import rclpy
5+
from rclpy.node import Node
6+
7+
import time
8+
9+
10+
class MinimalServerAsync(Node):
11+
12+
def __init__(self):
13+
super().__init__('minimal_server')
14+
self.cli = self.create_service(Huge, 'huge', self.callback)
15+
16+
def callback(self, request, response):
17+
self.get_logger().info('Incoming request...')
18+
return response
19+
20+
21+
def main(args=None):
22+
rclpy.init(args=args)
23+
24+
minimal_server = MinimalServerAsync()
25+
26+
try:
27+
rclpy.spin(minimal_server)
28+
except KeyboardInterrupt:
29+
pass
30+
31+
minimal_server.destroy_node()
32+
rclpy.shutdown()
33+
34+
35+
if __name__ == '__main__':
36+
main()

0 commit comments

Comments
 (0)