Google Sanitizer

ROS 2 also provides the tools to perform dynamic analysis for your projects, which focuses on finding data races and deadlocks. The address sanitiser and thread sanitiser are available to perform the dynamic analysis, and the usage of these tools would be further elaborated in the following sections below.

Note

Ensure that colcon mixin is installed if you want to make use of it. Checkout the quick guide on how to setup mixin here: Setting up mixin.

Prerequisites

(Recommended) If you want to use the sanitizer-report plugin, the colcon-sanitiser-reports plugin needs to be installed. It is a plugin for colcon test that that parses sanitizer issues from stdout/stderr, deduplicates the issues, and outputs them to a CSV:

git clone https://github.com/colcon/colcon-sanitizer-reports.git
cd colcon-sanitizer-reports
sudo python3 setup.py install

Otherwise, you could skip this step and omit the --event-handlers flag later on if you did not install the colcon-sanitizer-reports plugin.

Address Sanitizer

Compilation

Build the package via the following command:

colcon build --build-base=build-asan --install-base=install-asan \
--cmake-args -DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_C_FLAGS='-fsanitize=address' \
-DCMAKE_CXX_FLAGS='-fsanitize=address'

Note

Alternatively, mixin flag could be ran instead to replace the CMake flags:

colcon build --build-base=build-asan --install-base=install-asan --mixin asan-gcc

3 directories would be generated after the compilation is complete: build-asan, install-asan & log

Testing

To generate the report for the address sanitiser, the colcon test would be used:

colcon test --build-base=build-asan --install-base=install-asan \
--event-handlers sanitizer_report+

2 files would be generated once the testing is done, which contains the results of the test: test_results.xml, sanitizer_report.csv

Thread Sanitizer

Compilation

Build the thread sanitizer with the following command:

colcon build --build-base=build-tsan --install-base=install-tsan \
--cmake-args -DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_C_FLAGS='-fsanitize=thread -O2 -g -fno-omit-frame-pointer' \
-DCMAKE_CXX_FLAGS='-fsanitize=thread -O2 -g -fno-omit-frame-pointer'

Note

Alternatively, mixin could be used instead:

colcon build --build-base=build-tsan --install-base=install-tsan --mixin tsan

Testing

Run the test and generate the report with the following command:

colcon test --build-base=build-tsan --install-base=install-tsan \
--event-handlers sanitizer_report+

Example

We would be using the packml_ros2 in this example, looking at the address sanitizer, followed by the thread sanitizer. Let’s git clone the repository:

git clone https://github.com/1487quantum/packml_ros2.git ~/packml_ros2       # Clone the repo
cd ~/packml_ros2                                                             # Enter the dir

Address Sanitiser

Compile the package with the build-asn flags:

colcon build --build-base=build-asan --install-base=install-asan \
--cmake-args -DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_C_FLAGS='-fsanitize=address' \
-DCMAKE_CXX_FLAGS='-fsanitize=address'

After that, run the test(s) with the following CMake flags as shown below.

colcon test --build-base=build-asan --install-base=install-asan --event-handlers sanitizer_report+

The test logs could be found in the log/latest_test directory. The following example below displays the 3 lines after the beginning of a ASAN reported issue:

cd ~/packml_ros2/log/latest_test
grep -R '==.*==ERROR: .*Sanitizer' -A 3 # Displays three lines after the beginning of a ASAN reported issue.

The output would look something like this:

$ grep -R '==.*==ERROR: .*Sanitizer' -A 3
events.log:[45.324988] (packml_ros) StdoutLine: {'line': b'1: ==88592==ERROR: LeakSanitizer: detected memory leaks\n'}
events.log-[45.325039] (packml_ros) StdoutLine: {'line': b'1: \n'}
events.log-[45.325091] (packml_ros) StdoutLine: {'line': b'1: Direct leak of 56 byte(s) in 1 object(s) allocated from:\n'}
events.log-[45.325165] (packml_ros) StdoutLine: {'line': b'1:     #0 0x7f0dacca6bc8 in malloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)\n'}
--
packml_ros/stdout.log:1: ==88592==ERROR: LeakSanitizer: detected memory leaks
packml_ros/stdout.log-1:
packml_ros/stdout.log-1: Direct leak of 56 byte(s) in 1 object(s) allocated from:
packml_ros/stdout.log-1:     #0 0x7f0dacca6bc8 in malloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)
--
packml_ros/streams.log:[21.380s] 1: ==88592==ERROR: LeakSanitizer: detected memory leaks
packml_ros/streams.log-[21.380s] 1:
packml_ros/streams.log-[21.380s] 1: Direct leak of 56 byte(s) in 1 object(s) allocated from:
packml_ros/streams.log-[21.380s] 1:     #0 0x7f0dacca6bc8 in malloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)
--
packml_ros/stdout_stderr.log:1: ==88592==ERROR: LeakSanitizer: detected memory leaks
packml_ros/stdout_stderr.log-1:
packml_ros/stdout_stderr.log-1: Direct leak of 56 byte(s) in 1 object(s) allocated from:
packml_ros/stdout_stderr.log-1:     #0 0x7f0dacca6bc8 in malloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)

Thread Sanitiser

We’ll now move on to the Thread Sanitizer. To run the thread sanitizer, the steps are similar to those of the address sanitizer, with some differences in the flag. Return to the root directory and remove the build files:

cd ~/packml_ros2
rm -rf build-asan/ log/ install-asan/ sanitizer_report.csv test_results.xml

After that, compile the packages:

colcon build --build-base=build-tsan --install-base=install-tsan \
--cmake-args -DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_C_FLAGS='-fsanitize=thread -O2 -g -fno-omit-frame-pointer' \
-DCMAKE_CXX_FLAGS='-fsanitize=thread -O2 -g -fno-omit-frame-pointer'

Once compiled, run the test(s):

colcon test --build-base=build-tsan --install-base=install-tsan --event-handlers sanitizer_report+

The log would be available in the log/latest_test directory:

cd ~/packml_ros2/log/latest_test