Giter Site home page Giter Site logo

rcutils's Introduction

rcutils: ROS 2 C Utilities data structures

rcutils is a C API consisting of macros, functions, and data structures used through out the ROS 2 code base.

Quality Declaration

This package claims to be in the Quality Level 1 category, see the Quality Declaration for more details.

API

The API is a combination of parts:

  • Allocator concept, used to inject the allocating and deallocating methods into a function or type.
    • rcutils_allocator_t
    • rcutils/allocator.h
  • Command line interface utilities:
    • rcutils/cmdline_parser.h
  • Utilities for setting error states (error message, file, and line number) like strerror for errno:
    • rcutils/error_handling.h
  • Some basic filesystem utilities like checking for path existence, getting the cwd, etc...:
    • rcutils/filesystem.h
  • A C string find method:
    • rcutils_find()
    • rcutils_find_last()
    • rcutils/find.h
  • A convenient string formatting function, which takes a custom allocator:
    • rcutils_format_string()
    • rcutils/format_string.h
  • Functions for interfacing with process environment variables:
    • rcutils_get_env()
    • rcutils_get_home_dir()
    • rcutils_set_env()
    • rcutils/env.h
  • Extensible logging macros:
    • Some examples (not exhaustive):
      • RCUTILS_LOG_DEBUG()
      • RCUTILS_LOG_INFO_NAMED()
      • RCUTILS_LOG_WARN_ONCE()
      • RCUTILS_LOG_ERROR_SKIPFIRST_NAMED()
    • rcutils/logging_macros.h
    • rcutils/logging.h
  • Some basic utilities to load, unload and get symbols from shared libraries at run-time.
    • rcutils/shared_library.h
  • A string replacement function which takes an allocator, based on http://creativeandcritical.net/str-replace-c:
    • rcutils_repl_str()
    • rcutils/repl_str.h
  • String splitting functions which take a custom allocator:
    • rcutils_split()
    • rcutils_split_last()
    • rcutils/split.h
  • A version of strdup which takes an allocator:
    • rcutils_strdup()
    • rcutils/strdup.h
  • Portable implementations of "get system time" and "get steady time":
    • rcutils_system_time_now()
    • rcutils_steady_time_now()
    • rcutils/time.h
  • Some useful data structures:
    • A "string array" data structure (analogous to std::vector<std::string>):
      • rcutils_string_array_t
      • rcutils/types/string_array.h
    • A "string-string map" data structure (analogous to std::map<std::string, std::string>)
      • rcutils_string_map_t
      • rcutils/types/string_map.h
  • Macros for controlling symbol visibility and linkage for this library:
    • rcutils/visibility_control.h

rcutils's People

Contributors

ahcorde avatar asobhy-qnx avatar blast545 avatar brawner avatar christophebedard avatar clalancette avatar codebot avatar cottsay avatar dhood avatar dirk-thomas avatar emersonknapp avatar fujitatomoya avatar gaoethan avatar guijan avatar hidmic avatar ivanpauno avatar jacobperron avatar karsten1987 avatar malsbat avatar marcoag avatar mikaelarguedas avatar mjcarroll avatar nburek avatar nuclearsandwich avatar paudrow avatar sloretz avatar tfoote avatar theseankelly avatar thomas-moulard avatar wjwwood avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rcutils's Issues

test_logging_output_format tests broken

The tests in test_logging_output_format.py tests give worrying results in the CI log and when run locally. It seems like it may be a failure in the launch framework or in this package's usage of it.

Note particularly the error, which I think is saying that the test framework is sending a signal to a subprocess before it is set up to receive it: "RuntimeError: Signal event received before subprocess transport available."

http://build.ros2.org/job/Eci__nightly-cyclonedds_ubuntu_bionic_amd64/175/consoleText

5: Test command: /usr/bin/python3 "-u" "/tmp/ws/install_isolated/ament_cmake_test/share/ament_cmake_test/cmake/run_test.py" "/tmp/ws/test_results/rcutils/test_logging_long_messages.xunit.xml" "--package-name" "rcutils" "--output-file" "/tmp/ws/build_isolated/rcutils/launch_test/CHANGEME.txt" "--command" "/usr/bin/python3" "-m" "launch_testing.launch_test" "/tmp/ws/src/ros2/rcutils/test/test_logging_long_messages.py" "--junit-xml=/tmp/ws/test_results/rcutils/test_logging_long_messages.xunit.xml" "--package-name=rcutils"
5: Test timeout computed to be: 10
5: -- run_test.py: invoking following command in '/tmp/ws/build_isolated/rcutils':
5:  - /usr/bin/python3 -m launch_testing.launch_test /tmp/ws/src/ros2/rcutils/test/test_logging_long_messages.py --junit-xml=/tmp/ws/test_results/rcutils/test_logging_long_messages.xunit.xml --package-name=rcutils
5: [INFO] [launch]: All log files can be found below /home/buildfarm/.ros/log/2020-02-03-01-38-09-940584-47eaa799d93c-15284
5: [INFO] [launch]: Default logging verbosity is set to INFO
5: test_logging_output (rcutils.TestLoggingLongMessages)
5: Test executable output against expectation. ... [INFO] [test_logging_long_messages-1]: process started with pid [15288]
5: [test_logging_long_messages-1] [INFO] [name1]: XxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxX (func() at file:42)
5: [test_logging_long_messages-1] [INFO] [name2]: X42xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxX (func() at file:42)
5: ok
5: 
5: ----------------------------------------------------------------------
5: Ran 1 test in 0.005s
5: 
5: OK
5: [INFO] [test_logging_long_messages-1]: process has finished cleanly [pid 15288]
5: 
5: ----------------------------------------------------------------------
5: Ran 0 tests in 0.000s
5: 
5: OK
5: -- run_test.py: return code 0
5: -- run_test.py: verify result file '/tmp/ws/test_results/rcutils/test_logging_long_messages.xunit.xml'
 5/36 Test  #5: test_logging_long_messages .......   Passed    0.35 sec
test 6
      Start  6: test_logging_output_format

6: Test command: /usr/bin/python3 "-u" "/tmp/ws/install_isolated/ament_cmake_test/share/ament_cmake_test/cmake/run_test.py" "/tmp/ws/test_results/rcutils/test_logging_output_format.xunit.xml" "--package-name" "rcutils" "--output-file" "/tmp/ws/build_isolated/rcutils/launch_test/CHANGEME.txt" "--command" "/usr/bin/python3" "-m" "launch_testing.launch_test" "/tmp/ws/src/ros2/rcutils/test/test_logging_output_format.py" "--junit-xml=/tmp/ws/test_results/rcutils/test_logging_output_format.xunit.xml" "--package-name=rcutils"
6: Test timeout computed to be: 10
6: -- run_test.py: invoking following command in '/tmp/ws/build_isolated/rcutils':
6:  - /usr/bin/python3 -m launch_testing.launch_test /tmp/ws/src/ros2/rcutils/test/test_logging_output_format.py --junit-xml=/tmp/ws/test_results/rcutils/test_logging_output_format.xunit.xml --package-name=rcutils
6: [INFO] [launch]: All log files can be found below /home/buildfarm/.ros/log/2020-02-03-01-38-10-295070-47eaa799d93c-15290
6: [INFO] [launch]: Default logging verbosity is set to INFO
6: 
6: ----------------------------------------------------------------------
6: Ran 0 tests in 0.000s
6: 
6: OK
6: Task exception was never retrieved
6: future: <Task finished coro=<LaunchService._process_one_event() done, defined at /tmp/ws/install_isolated/launch/lib/python3.6/site-packages/launch/launch_service.py:293> exception=RuntimeError('Signal event received before subprocess transport available.',)>
6: Traceback (most recent call last):
6:   File "/tmp/ws/install_isolated/launch/lib/python3.6/site-packages/launch/launch_service.py", line 295, in _process_one_event
6:     await self.__process_event(next_event)
6:   File "/tmp/ws/install_isolated/launch/lib/python3.6/site-packages/launch/launch_service.py", line 315, in __process_event
6:     visit_all_entities_and_collect_futures(entity, self.__context))
6:   File "/tmp/ws/install_isolated/launch/lib/python3.6/site-packages/launch/utilities/visit_all_entities_and_collect_futures_impl.py", line 38, in visit_all_entities_and_collect_futures
6:     sub_entities = entity.visit(context)
6:   File "/tmp/ws/install_isolated/launch/lib/python3.6/site-packages/launch/action.py", line 108, in visit
6:     return self.execute(context)
6:   File "/tmp/ws/install_isolated/launch/lib/python3.6/site-packages/launch/actions/opaque_function.py", line 75, in execute
6:     return self.__function(context, *self.__args, **self.__kwargs)
6:   File "/tmp/ws/install_isolated/launch/lib/python3.6/site-packages/launch/actions/execute_process.py", line 383, in __on_signal_process_event
6:     raise RuntimeError('Signal event received before subprocess transport available.')
6: RuntimeError: Signal event received before subprocess transport available.
6: [INFO] [test_logging_output_format_long-1]: process started with pid [15294]
6: [INFO] [test_logging_output_format_long-1]: process has finished cleanly [pid 15294]
6: [INFO] [test_logging_output_format_edge_cases-2]: process started with pid [15295]
6: [INFO] [test_logging_output_format_edge_cases-2]: process has finished cleanly [pid 15295]
6: [INFO] [test_logging_output_format_no_tokens-3]: process started with pid [15296]
6: [INFO] [test_logging_output_format_no_tokens-3]: process has finished cleanly [pid 15296]
6: [INFO] [test_logging_output_timestamps-4]: process started with pid [15297]
6: [INFO] [test_logging_output_timestamps-4]: process has finished cleanly [pid 15297]
6: Task exception was never retrieved
6: future: <Task finished coro=<LaunchService._process_one_event() done, defined at /tmp/ws/install_isolated/launch/lib/python3.6/site-packages/launch/launch_service.py:293> exception=RuntimeError('Signal event received before subprocess transport available.',)>
6: Traceback (most recent call last):
6:   File "/tmp/ws/install_isolated/launch/lib/python3.6/site-packages/launch/launch_service.py", line 295, in _process_one_event
6:     await self.__process_event(next_event)
6:   File "/tmp/ws/install_isolated/launch/lib/python3.6/site-packages/launch/launch_service.py", line 315, in __process_event
6:     visit_all_entities_and_collect_futures(entity, self.__context))
6:   File "/tmp/ws/install_isolated/launch/lib/python3.6/site-packages/launch/utilities/visit_all_entities_and_collect_futures_impl.py", line 38, in visit_all_entities_and_collect_futures
6:     sub_entities = entity.visit(context)
6:   File "/tmp/ws/install_isolated/launch/lib/python3.6/site-packages/launch/action.py", line 108, in visit
6:     return self.execute(context)
6:   File "/tmp/ws/install_isolated/launch/lib/python3.6/site-packages/launch/actions/opaque_function.py", line 75, in execute
6:     return self.__function(context, *self.__args, **self.__kwargs)
6:   File "/tmp/ws/install_isolated/launch/lib/python3.6/site-packages/launch/actions/execute_process.py", line 383, in __on_signal_process_event
6:     raise RuntimeError('Signal event received before subprocess transport available.')
6: RuntimeError: Signal event received before subprocess transport available.
6: [test_logging_output_format_long-1] [{name1}].(INFO) output: file:42 XxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxX, again: XxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxX (func()){
6: [test_logging_output_format_long-1] [{name2}].(INFO) output: file:42 X42xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxX, again: X42xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxX (func()){
6: [test_logging_output_format_edge_cases-2] {}}].({unknown_token}) {{{{
6: [test_logging_output_format_edge_cases-2] {}}].({unknown_token}) {{{{
6: [test_logging_output_format_no_tokens-3] no_tokens
6: [test_logging_output_format_no_tokens-3] no_tokens
6: [test_logging_output_timestamps-4] '1580722690.309443789' '1580722690309443789'
6: [test_logging_output_timestamps-4] '1580722690.309470948' '1580722690309470948'
6: test_logging_output (rcutils.TestLoggingOutputFormatAfterShutdown)
6: Test all executables output against expectations. ... ok
6: test_processes_exit_codes (rcutils.TestLoggingOutputFormatAfterShutdown)
6: Test that all executables finished cleanly. ... ok
6: 
6: ----------------------------------------------------------------------
6: Ran 2 tests in 0.003s
6: 
6: OK

rcutils logging macro warning

I was using the new logging macros like this:

#include "rcutils/logging_macros.h"
// ...
    RCUTILS_LOG_ERROR(
      "failed to clean up on error (leaking memory): '%s'", rcutils_get_error_string_safe());

But I get a warning like this:

In file included from /Users/william/ros2_ws/src/ros2/rcutils/src/split.c:26:
/Users/william/ros2_ws/build/rcutils/include/rcutils/logging_macros.h:948:13: warning: token pasting of ',' and __VA_ARGS__ is a GNU extension [-Wgnu-zero-variadic-macro-arguments]
    format, ## __VA_ARGS__)
            ^
/Users/william/ros2_ws/build/rcutils/include/rcutils/logging_macros.h:93:68: warning: token pasting of ',' and __VA_ARGS__ is a GNU extension [-Wgnu-zero-variadic-macro-arguments]
      rcl_log(&__rcutils_logging_location, severity, name, format, ## __VA_ARGS__); \
                                                                   ^
2 warnings generated.

I looked into it briefly, but I didn't dig too deep. Am I doing something wrong or is this just a warning we should fix in the logging macros?

The warning only references the line on which the header is included, but if I remove all uses of the logging macro (but leave the include) the warning goes away.

C flags when not building tests

I ran across this while building c_utilities on gcc 4.9.2:

[ 12%] Building C object CMakeFiles/c_utilities.dir/src/cmdline_parser.c.o
/home/chip/sros2/src/ros2/c_utilities/src/cmdline_parser.c: In function โ€˜cli_option_existโ€™:
/home/chip/sros2/src/ros2/c_utilities/src/cmdline_parser.c:22:3: error: โ€˜forโ€™ loop initial declarations are only allowed in C99 or C11 mode
   for (size_t i = 0; i < (size_t)(end - begin); ++i) {
   ^
/home/chip/sros2/src/ros2/c_utilities/src/cmdline_parser.c:22:3: note: use option -std=c99, -std=gnu99, -std=c11 or -std=gnu11 to compile your code
CMakeFiles/c_utilities.dir/build.make:62: recipe for target 'CMakeFiles/c_utilities.dir/src/cmdline_parser.c.o' failed
make[2]: *** [CMakeFiles/c_utilities.dir/src/cmdline_parser.c.o] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/c_utilities.dir/all' failed
make[1]: *** [CMakeFiles/c_utilities.dir/all] Error 2
Makefile:129: recipe for target 'all' failed
make: *** [all] Error 2

I think this is because the line specifying C11 is here:
https://github.com/ros2/c_utilities/blob/master/CMakeLists.txt#L35
which is only executed when tests are being built. If a build is kicked off without tests, it fails (or at least it did for me). Moving the CMAKE_C_FLAGS and CMAKE_CXX_FLAGS definitions up in the file (outside the if (BUILD_TESTING) block) allowed the build to work for me.

steady time overflow issue

As reported by @serge-nikulin, this test code will eventually produce unexpected output on Windows (I do not think it affects Linux/macOS):

int main()
{
  rcutils_time_point_value_t last_time_ns;
  rcutils_time_point_value_t this_time_ns;
  rcutils_steady_time_now(&last_time_ns);
  for (uint64_t count = 0ULL; ; ++count)
  {
    rcutils_steady_time_now(&this_time_ns);
    uint64_t delta_ns = this_time_ns - last_time_ns;
    if (delta_ns > 100000000ULL) {
      std::cout << "****** Unexpected delta: " << delta_ns << "*********\n";
    }
    if ((count % 1000000000ULL) == 0ULL) {
      std::ostringstream ss;
      ss.imbue(std::locale(""));
      ss << count;
      std::cout << ss.str() << "\n";
    }
    last_time_ns = this_time_ns;
  }
  return 0;
}

Something like this (after about 30 minutes or so):

41,000,000,000
42,000,000,000
43,000,000,000
44,000,000,000
45,000,000,000
****** Unexpected delta: 18446738826622249502*********
46,000,000,000
47,000,000,000
48,000,000,000

The theory is that this is due to an overflow of an intermediate calculation which uses the performance ticks on a computer with a GHz speed processor.

@serge-nikulin said:

The culprit is rcutils_steady_time_now: multiplication by 10^9 periodically overflows uint64_t (max ~10^19).
With GHZ frequencies (10^9) it should be a matter of time to get an overflow condition:

  // Convert to nanoseconds before converting from ticks to avoid precision loss.
  rcutils_time_point_value_t intermediate = RCUTILS_S_TO_NS(performance_count.QuadPart);
  *now = intermediate / cpu_frequency.QuadPart;

I already have brushed this bug in #79 (comment).

Rationale about what to test for performance

Took some time to check the rcutils submodules, here's a list of them and what I consider that should be tested for each of those in terms of performance:

โ”œโ”€โ”€ allocator.h
I/O, allocation, runtime critical

  • Allocation time
  • Memory leaks
  • Asymptotic complexity

โ”œโ”€โ”€ cmdline_parser.h
STABLE, not often used

  • Not required

โ”œโ”€โ”€ env.h
STABLE, I/O

  • Not required, maybe check platform runtime differences

โ”œโ”€โ”€ error_handling.h
STABLE, I/O, Allocation, runtime critical

  • Allocation time
  • Memory leaks
  • Asymptotic complexity

โ”œโ”€โ”€ filesystem.h
STABLE, I/O

  • Not required, maybe check platform runtime differences

โ”œโ”€โ”€ find.h
STABLE, Algorithm

  • Asymptotic complexity

โ”œโ”€โ”€ format_string.h
Allocation, Critical runtime

  • IMO This could be tested through logging or a higher level module

โ”œโ”€โ”€ get_env.h
STABLE, I/O, conf code

  • Not required

โ”œโ”€โ”€ isalnum_no_locale.h
STABLE

  • Not required

โ”œโ”€โ”€ logging.h
Allocation, Critical runtime

  • Allocation time
  • Memory leaks
  • Asymptotic complexity

โ”œโ”€โ”€ process.h
STABLE, IO, Allocation, not often used

  • Not required

โ”œโ”€โ”€ qsort.h
Algorithm

  • Asymptotic complexity

โ”œโ”€โ”€ repl_str.h
STABLE, Algorithm

  • Asymptotic complexity

โ”œโ”€โ”€ shared_library.h
IO, Conf code or critical runtime (?

  • Allocation time
  • Memory leaks
  • Asymptotic complexity

โ”œโ”€โ”€ snprintf.h
STABLE, IO

  • IMO This could be tested through logging or a higher level module. Or simple tests to check platform differences

โ”œโ”€โ”€ split.h
STABLE, Algorithm

  • Asymptotic complexity

โ”œโ”€โ”€ stdatomic_helper.h
STABLE, IO, Critical runtime

  • Can those be tested for performance?

โ”œโ”€โ”€ strdup.h
Allocation

  • Memory leaks

โ”œโ”€โ”€ strerror.h
STABLE, IO, Critical runtime

  • Allocation time
  • Memory leaks
  • Asymptotic complexity

โ”œโ”€โ”€ time.h
IO

  • Runtime platform differences, maybe test through higher level modules

Custom defined primitives:
โ”‚ย ย  โ”œโ”€โ”€ array_list.h
โ”‚ย ย  โ”œโ”€โ”€ char_array.h
โ”‚ย ย  โ”œโ”€โ”€ hash_map.h
โ”‚ย ย  โ”œโ”€โ”€ string_array.h
โ”‚ย ย  โ”œโ”€โ”€ string_map.h
โ”‚ย ย  โ””โ”€โ”€ uint8_array.h

  • Test basic operations runtime performance + Asymptotic complexity
  • Memory leaks

Implement a thread safe version of rcutils_get_env

While ensuring thread safety may be impossible we could improve robustness by using thread local storage for the result of the rcutils_get_env function.
This would also be a good time to refactor every part of the code reading environment variables to use this function
Related ticket ros2/rcl#97

types should be namespaced with utilities_

Currently types like string_array_t could easily, imo, collide with any arbitrary other system. I believe it would be better to prefix these types with utilities_.

I can foresee that this will be annoying to do, but in that case I'd argue we should try for a shorter and simpler package name/prefix name instead of avoiding namespacing in some places.

Force flush for rcutils logging

We have code that forces flushing of stdout in some places, particularly so that launch file prints sync. This includes python scripts that call sys.stdout.flush(). After switching to use rcutils logging (via python wrappers), sys.stdout.flush() will do nothing for python scripts, and they will not have a way to force flush.

Consider an environment variable similar to ros/ros_comm#1012.

Implement more stringent thread-safetyness in `rcutils_getenv`

There's a lot of detail in #237 (comment) , but to summarize the situation we are now in:

As of #237, on all platforms rcutils_get_env is thread-safe for simultaneously getting environment variables from separate threads. It is currently unsafe in the following cases:

  1. Getting an environment variable, holding onto the pointer, and then having a later method (in the same or different thread) call setenv. In that case, the pointer may be invalidated, but there is no way of knowing.
  2. Getting an environment variable in one thread while setting an environment variable from a separate thread at the same time (this is a well-known limitation of glibc, for instance).

The first issue can be solved by changing the contract of rcutils_get_env to take an allocator, allocate space, copy the contents of the environment variable into that space, and then having the caller free the memory when they are done.

The second issue can be solved by adding locking around getting environment variables and setting environment variables.

Logging macros aren't safe in all contexts

Consider the following structure:

if (condition)
    RCUTILS_LOG_ERROR("error");
else
{
    RCUTILS_LOG_INFO("info");
}

With the current ROS2 rcutils, this code will fail to compile with something like:

/home/ubuntu/teleop_twist_ws/src/badmacro/src/badmacro.cpp: In member function โ€˜int BadMacro::main()โ€™:
/home/ubuntu/teleop_twist_ws/src/badmacro/src/badmacro.cpp:21:7: error: expected โ€˜}โ€™ before โ€˜elseโ€™
       else
       ^~~~
In file included from /opt/ros/bouncy/include/rclcpp/client.hpp:39:0,
                 from /opt/ros/bouncy/include/rclcpp/callback_group.hpp:23,
                 from /opt/ros/bouncy/include/rclcpp/node_interfaces/node_base_interface.hpp:25,
                 from /opt/ros/bouncy/include/rclcpp/executor.hpp:31,
                 from /opt/ros/bouncy/include/rclcpp/executors/multi_threaded_executor.hpp:24,
                 from /opt/ros/bouncy/include/rclcpp/executors.hpp:21,
                 from /opt/ros/bouncy/include/rclcpp/rclcpp.hpp:144,
                 from /home/ubuntu/teleop_twist_ws/src/badmacro/src/badmacro.cpp:3:

I have a minimal reproducer of this problem over at https://github.com/clalancette/badmacro . We probably need to wrap all of these macros in the do { ... } while(0) construct to make them safe in these circumstances.

Add environment variable to configure logging level

Today I tried to debug my ROS2 setup, but I was unable to get detailed logging output. It would be good to be able to set the default log level via an environment variable.

My idea would be to be able to do this:

  • export RCUTILS_LOG_LEVEL=DEBUG
  • run executable with more debug output than normally the case.

Is this a good idea? Or did I miss some other option to troubleshoot my setup?

add namespace to some existing functions

For example (just the ones I've noticed):

  • cli_option_exist should be rcutils_cli_option_exist
  • cli_get_option should be rcutils_cli_get_option

That might be all of them, but those for sure.

Default logging format design

Was there a design discussion around the default logging format defined here?

static const char * g_rcutils_logging_default_output_format = "[{severity}] [{name}]: {message}";

I'd think the default you'd want a unix timestamp to determine relative timing of when events or logs occur. I can submit a PR to change this is folks agree. I can say from experience working with Navigation2 that this has been a pain point, which I know can be worked around setting RCUTILS_CONSOLE_OUTPUT_FORMAT however I'd think a timestamp is a reasonable default behavior.

Variable name in macro shadows other variable

Hi,

The logging code here triggers a lot of warnings on building. It is because a macro uses the very simple variable name ret, which is also used by the rclcpp function borrow_serialized_message (on my system in /opt/ros/dashing/include/rclcpp/message_memory_strategy.hpp L103) which uses that macro.

I would suggest to skip the assignment to the variable, as it is only used once. Alternatively, use a more unique name that is not likely to be used outside of the macro.

The full warning in question:

/opt/ros/dashing/include/rclcpp/message_memory_strategy.hpp:100:16: warning: declaration of โ€˜retโ€™ shadows a previous local [-Wshadow]
           auto ret = rmw_serialized_message_fini(msg);
                ^~~
/opt/ros/dashing/include/rclcpp/message_memory_strategy.hpp:93:10: note: shadowed declaration is here
     auto ret = rmw_serialized_message_init(msg, capacity, &rcutils_allocator_);
          ^~~
In file included from /opt/ros/dashing/include/rmw/types.h:28:0,
                 from /opt/ros/dashing/include/rcl/types.h:18,
                 from /opt/ros/dashing/include/rcl/arguments.h:20,
                 from /opt/ros/dashing/include/rcl/context.h:26,
                 from /opt/ros/dashing/include/rcl/guard_condition.h:24,
                 from /opt/ros/dashing/include/rclcpp/executor.hpp:29,
                 from /opt/ros/dashing/include/rclcpp/executors/multi_threaded_executor.hpp:24,
                 from /opt/ros/dashing/include/rclcpp/executors.hpp:21,
                 from /opt/ros/dashing/include/rclcpp/rclcpp.hpp:144,
                 from ../../../../../xxx.h:12,
                 from ../../../../../xxx.cpp:5:
/opt/ros/dashing/include/rcutils/logging.h:543:19: warning: declaration of โ€˜retโ€™ shadows a previous local [-Wshadow]
     rcutils_ret_t ret = rcutils_logging_initialize(); \
                   ^
/opt/ros/dashing/include/rcutils/logging_macros.h:68:5: note: in expansion of macro โ€˜RCUTILS_LOGGING_AUTOINITโ€™
     RCUTILS_LOGGING_AUTOINIT \
     ^~~~~~~~~~~~~~~~~~~~~~~~
/opt/ros/dashing/include/rcutils/logging_macros.h:994:3: note: in expansion of macro โ€˜RCUTILS_LOG_COND_NAMEDโ€™
   RCUTILS_LOG_COND_NAMED( \
   ^~~~~~~~~~~~~~~~~~~~~~
/opt/ros/dashing/include/rclcpp/message_memory_strategy.hpp:103:13: note: in expansion of macro โ€˜RCUTILS_LOG_ERROR_NAMEDโ€™
             RCUTILS_LOG_ERROR_NAMED(
             ^~~~~~~~~~~~~~~~~~~~~~~
In file included from /opt/ros/dashing/include/rclcpp/subscription.hpp:40:0,
                 from /opt/ros/dashing/include/rclcpp/callback_group.hpp:26,
                 from /opt/ros/dashing/include/rclcpp/any_executable.hpp:20,
                 from /opt/ros/dashing/include/rclcpp/memory_strategy.hpp:24,
                 from /opt/ros/dashing/include/rclcpp/memory_strategies.hpp:18,
                 from /opt/ros/dashing/include/rclcpp/executor.hpp:33,
                 from /opt/ros/dashing/include/rclcpp/executors/multi_threaded_executor.hpp:24,
                 from /opt/ros/dashing/include/rclcpp/executors.hpp:21,
                 from /opt/ros/dashing/include/rclcpp/rclcpp.hpp:144,
                 from ../../../../../xxx.h:12,
                 from ../../../../../xxx.cpp:5:
/opt/ros/dashing/include/rclcpp/message_memory_strategy.hpp:100:16: note: shadowed declaration is here
           auto ret = rmw_serialized_message_fini(msg);
                ^~~

Fix test_array_list leaks

Running main() from ../../../install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 31 tests from 2 test cases.
[----------] Global test environment set-up.
[----------] 19 tests from ArrayListTest
[ RUN      ] ArrayListTest.init_list_null_fails
[       OK ] ArrayListTest.init_list_null_fails (0 ms)
[ RUN      ] ArrayListTest.init_initial_capacity_zero_fails
[       OK ] ArrayListTest.init_initial_capacity_zero_fails (0 ms)
[ RUN      ] ArrayListTest.init_data_size_zero_fails
[       OK ] ArrayListTest.init_data_size_zero_fails (0 ms)
[ RUN      ] ArrayListTest.init_null_allocator_fails
[       OK ] ArrayListTest.init_null_allocator_fails (0 ms)
[ RUN      ] ArrayListTest.init_success
[       OK ] ArrayListTest.init_success (0 ms)
[ RUN      ] ArrayListTest.fini_list_null
[       OK ] ArrayListTest.fini_list_null (0 ms)
[ RUN      ] ArrayListTest.fini_list_not_initialized
[       OK ] ArrayListTest.fini_list_not_initialized (0 ms)
[ RUN      ] ArrayListTest.fini_success
[       OK ] ArrayListTest.fini_success (0 ms)
[ RUN      ] ArrayListTest.add_list_null_fails
[       OK ] ArrayListTest.add_list_null_fails (0 ms)
[ RUN      ] ArrayListTest.add_list_not_initialized_fails
[       OK ] ArrayListTest.add_list_not_initialized_fails (0 ms)
[ RUN      ] ArrayListTest.set_list_null_fails
[       OK ] ArrayListTest.set_list_null_fails (0 ms)
[ RUN      ] ArrayListTest.set_list_not_initialized_fails
[       OK ] ArrayListTest.set_list_not_initialized_fails (0 ms)
[ RUN      ] ArrayListTest.remove_list_null_fails
[       OK ] ArrayListTest.remove_list_null_fails (0 ms)
[ RUN      ] ArrayListTest.remove_list_not_initialized_fails
[       OK ] ArrayListTest.remove_list_not_initialized_fails (0 ms)
[ RUN      ] ArrayListTest.get_list_null_fails
[       OK ] ArrayListTest.get_list_null_fails (0 ms)
[ RUN      ] ArrayListTest.get_list_not_initialized_fails
[       OK ] ArrayListTest.get_list_not_initialized_fails (0 ms)
[ RUN      ] ArrayListTest.get_size_list_null_fails
[       OK ] ArrayListTest.get_size_list_null_fails (0 ms)
[ RUN      ] ArrayListTest.get_size_list_not_initialized_fails
[       OK ] ArrayListTest.get_size_list_not_initialized_fails (0 ms)
[ RUN      ] ArrayListTest.add_grow_capacity
[       OK ] ArrayListTest.add_grow_capacity (0 ms)
[----------] 19 tests from ArrayListTest (0 ms total)

[----------] 12 tests from ArrayListPreInitTest
[ RUN      ] ArrayListPreInitTest.add_data_null_fails
[       OK ] ArrayListPreInitTest.add_data_null_fails (0 ms)
[ RUN      ] ArrayListPreInitTest.add_success
[       OK ] ArrayListPreInitTest.add_success (0 ms)
[ RUN      ] ArrayListPreInitTest.set_data_null_fails
[       OK ] ArrayListPreInitTest.set_data_null_fails (0 ms)
[ RUN      ] ArrayListPreInitTest.set_data_index_oob_fails
[       OK ] ArrayListPreInitTest.set_data_index_oob_fails (0 ms)
[ RUN      ] ArrayListPreInitTest.set_success_changes_data
[       OK ] ArrayListPreInitTest.set_success_changes_data (0 ms)
[ RUN      ] ArrayListPreInitTest.remove_data_index_oob_fails
[       OK ] ArrayListPreInitTest.remove_data_index_oob_fails (0 ms)
[ RUN      ] ArrayListPreInitTest.remove_success_removes_from_list
[       OK ] ArrayListPreInitTest.remove_success_removes_from_list (0 ms)
[ RUN      ] ArrayListPreInitTest.get_data_index_oob_fails
[       OK ] ArrayListPreInitTest.get_data_index_oob_fails (0 ms)
[ RUN      ] ArrayListPreInitTest.get_data_success_returns_data
[       OK ] ArrayListPreInitTest.get_data_success_returns_data (0 ms)
[ RUN      ] ArrayListPreInitTest.get_size_size_null_fails
[       OK ] ArrayListPreInitTest.get_size_size_null_fails (0 ms)
[ RUN      ] ArrayListPreInitTest.get_size_increases_with_add
[       OK ] ArrayListPreInitTest.get_size_increases_with_add (0 ms)
[ RUN      ] ArrayListPreInitTest.remove_preserves_data_around_it
[       OK ] ArrayListPreInitTest.remove_preserves_data_around_it (0 ms)
[----------] 12 tests from ArrayListPreInitTest (0 ms total)

[----------] Global test environment tear-down
[==========] 31 tests from 2 test cases ran. (0 ms total)
[  PASSED  ] 31 tests.

=================================================================
==5522==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 72 byte(s) in 1 object(s) allocated from:
    #0 0x7fce6828db50 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb50)
    #1 0x7fce67f9fba5 in __default_allocate (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0x3ba5)
    #2 0x7fce67f9fe98 in rcutils_array_list_init (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0x3e98)
    #3 0x55a62186398c in ArrayListTest_init_success_Test::TestBody() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x1c98c)
    #4 0x55a6218f3769 in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0xac769)
    #5 0x55a6218e5491 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x9e491)
    #6 0x55a6218911ed in testing::Test::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x4a1ed)
    #7 0x55a621892618 in testing::TestInfo::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x4b618)
    #8 0x55a6218931bc in testing::TestCase::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x4c1bc)
    #9 0x55a6218ae2cd in testing::internal::UnitTestImpl::RunAllTests() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x672cd)
    #10 0x55a6218f621c in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0xaf21c)
    #11 0x55a6218e775a in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0xa075a)
    #12 0x55a6218ab061 in testing::UnitTest::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x64061)
    #13 0x55a62187e5b0 in RUN_ALL_TESTS() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x375b0)
    #14 0x55a62187e4f6 in main (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x374f6)
    #15 0x7fce6740cb96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)

Direct leak of 72 byte(s) in 1 object(s) allocated from:
    #0 0x7fce6828db50 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb50)
    #1 0x7fce67f9fba5 in __default_allocate (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0x3ba5)
    #2 0x7fce67f9fe98 in rcutils_array_list_init (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0x3e98)
    #3 0x55a62186f09c in ArrayListTest_add_grow_capacity_Test::TestBody() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x2809c)
    #4 0x55a6218f3769 in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0xac769)
    #5 0x55a6218e5491 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x9e491)
    #6 0x55a6218911ed in testing::Test::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x4a1ed)
    #7 0x55a621892618 in testing::TestInfo::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x4b618)
    #8 0x55a6218931bc in testing::TestCase::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x4c1bc)
    #9 0x55a6218ae2cd in testing::internal::UnitTestImpl::RunAllTests() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x672cd)
    #10 0x55a6218f621c in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0xaf21c)
    #11 0x55a6218e775a in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0xa075a)
    #12 0x55a6218ab061 in testing::UnitTest::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x64061)
    #13 0x55a62187e5b0 in RUN_ALL_TESTS() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x375b0)
    #14 0x55a62187e4f6 in main (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x374f6)
    #15 0x7fce6740cb96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)

Indirect leak of 128 byte(s) in 1 object(s) allocated from:
    #0 0x7fce6828df40 in realloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdef40)
    #1 0x7fce67f9fbed in __default_reallocate (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0x3bed)
    #2 0x7fce67fa00dd in rcutils_array_list_increase_capacity (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0x40dd)
    #3 0x7fce67fa0214 in rcutils_array_list_add (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0x4214)
    #4 0x55a62186f3cd in ArrayListTest_add_grow_capacity_Test::TestBody() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x283cd)
    #5 0x55a6218f3769 in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0xac769)
    #6 0x55a6218e5491 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x9e491)
    #7 0x55a6218911ed in testing::Test::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x4a1ed)
    #8 0x55a621892618 in testing::TestInfo::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x4b618)
    #9 0x55a6218931bc in testing::TestCase::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x4c1bc)
    #10 0x55a6218ae2cd in testing::internal::UnitTestImpl::RunAllTests() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x672cd)
    #11 0x55a6218f621c in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0xaf21c)
    #12 0x55a6218e775a in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0xa075a)
    #13 0x55a6218ab061 in testing::UnitTest::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x64061)
    #14 0x55a62187e5b0 in RUN_ALL_TESTS() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x375b0)
    #15 0x55a62187e4f6 in main (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x374f6)
    #16 0x7fce6740cb96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)

Indirect leak of 8 byte(s) in 1 object(s) allocated from:
    #0 0x7fce6828db50 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb50)
    #1 0x7fce67f9fba5 in __default_allocate (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0x3ba5)
    #2 0x7fce67f9ff23 in rcutils_array_list_init (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0x3f23)
    #3 0x55a62186398c in ArrayListTest_init_success_Test::TestBody() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x1c98c)
    #4 0x55a6218f3769 in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0xac769)
    #5 0x55a6218e5491 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x9e491)
    #6 0x55a6218911ed in testing::Test::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x4a1ed)
    #7 0x55a621892618 in testing::TestInfo::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x4b618)
    #8 0x55a6218931bc in testing::TestCase::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x4c1bc)
    #9 0x55a6218ae2cd in testing::internal::UnitTestImpl::RunAllTests() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x672cd)
    #10 0x55a6218f621c in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0xaf21c)
    #11 0x55a6218e775a in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0xa075a)
    #12 0x55a6218ab061 in testing::UnitTest::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x64061)
    #13 0x55a62187e5b0 in RUN_ALL_TESTS() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x375b0)
    #14 0x55a62187e4f6 in main (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_array_list+0x374f6)
    #15 0x7fce6740cb96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)

SUMMARY: AddressSanitizer: 280 byte(s) leaked in 4 allocation(s).

Potential buffer overflow

Function call rcutils_find(str + i, '}') can returns 0, if a malformed function.
if so size_t token_len = chars_to_end_delim - 1; will cause token_len = 18446744073709551615 and cause overflow

rcutils/src/logging.c

Lines 634 to 648 in 2497ff5

// Look for a token end delimiter.
size_t chars_to_end_delim = rcutils_find(str + i, token_end_delimiter);
remaining_chars = size - i;
if (chars_to_end_delim > remaining_chars) {
// No end delimiters found in the remainder of the format string;
// there won't be any more tokens so shortcut the rest of the checking.
status = rcutils_char_array_strncat(logging_output, str + i, remaining_chars);
OK_OR_RETURN_EARLY(status);
break;
}
// Found what looks like a token; determine if it's recognized.
size_t token_len = chars_to_end_delim - 1; // Not including delimiters.
memcpy(token, str + i + 1, token_len); // Skip the start delimiter.

RCUTILS_SAFE_FWRITE_TO_STDERR with variable length messages

If you pass a message of type const char * to RCUTILS_SAFE_FWRITE_TO_STDERR e.g.

RCUTILS_SAFE_FWRITE_TO_STDERR(rcutils_get_error_string_safe());

then the sizeof(msg) calculation in the macro gives the size of the pointer:

#define RCUTILS_SAFE_FWRITE_TO_STDERR(msg) fwrite(msg, sizeof(char), sizeof(msg), stderr)

From what I can tell the count passed to fwrite is not a max size, but the size, so I think this line can cause buffer overrun if the msg is less than length 8. That doesn't happen with our existing code because they're all longer (instead our messages get truncated), but it could happen.

What's the appropriate fix here?

  • continue using sizeof(msg) and only use this macro with static buffers
  • switch to strlen(msg) and only use this macro will null-terminated buffers (also a risk)

Simplify error handling in failure mode or during finalization

Rationale

Error handling support in rcutils (and by extension, in every ROS 2 C library implementation or client code) falls short when it comes to error propagation when in failure mode or during finalization. As discussed in ros2/rmw_fastrtps#414 and ros2/rmw_cyclonedds#210, ensuring the initial error gets propagated, while no subsequent error goes unnoticed, clutters client code significantly.

Proposal

Introduce a mechanism for rcutils to distinguish between an error overwrite and a nested error that should be handled differently (e.g. logging to stderr directly). For that matter, have a thread local integer to track nested error handling scopes and a boolean in local storage to ensure a single error handling scope per function.

With an API like:

typedef struct rcutils_error_handling_scope_t {
    bool active;
} rcutils_error_handling_scope_t;

void rcutils_error_handling_scope_init(rcutils_error_handling_scope_t * scope);
void rcutils_error_handling_scope_enter(rcutils_error_handling_scope_t * scope);
void rcutils_error_handling_scope_leave(rcutils_error_handling_scope_t * scope);

a function may request rcutils_set_error_state to behave differently in between _enter and _leave calls, for its own code and the call chain that follows after it. In C++, RAII may be used to simplify API use even further.

INFO and ERROR logging should come out in order by default

Right now, info-level logging output is not line-buffered by default, whereas error-level logging output is. This is a problem for usability, since it causes extremely confusing logs when an error message in one process is flushed before a much later info message in a simultaneous process. The buffering of stdout, while appropriate for some Linux programs, is inappropriate when diagnostic logging output is emitted from both streams stderr and stdout.

The consequences of having RCUTILS_CONSOLE_STDOUT_LINE_BUFFERED=1 when it should be 0 is a tiny (if noticeable) performance hit. The consequences of having it 0 when it should be 1 is incomprehensibly misordered logging output, often with info messages not emitted until a node dies, and no sequence numbers nor timestamps to indicate this misordering. Because of this, logging should default RCUTILS_CONSOLE_STDOUT_LINE_BUFFERED to 1 if unset.

Convert ROS2 time value to signed int64_t

I think that a signed value is a more metrologically and physically correct representation of any non-absolute, "non-Kelvin" time system in comparison the current ROS2 unsigned value.

Regardless of metrology correctness signed time value makes computations of durations (always a signed value!) more unerring in the programming sense. MISRA C 2012 rule 10.4 treats signed and unsigned as different incompatible types. It takes very messy coding to account for over- and underflow edge conditions in sign-mixed math.

The current nanoseconds uint64_t gives us ~584.5 years from 1970, int64_t is twice shorter. Correspondingly it's 2554AD and 2262AD.

I think both end dates are remote enough for both unsigned and signed values to be practical in today's applications.

CC: @wjwwood

find_library: Prefer currently loaded libraries over searching `LD_LIBRARY_PATH`

At present, find_library drops straight into searching libraries along LD_LIBRARY_PATH, rather than first querying loaded libraries. One of the 3 current implementations:
https://github.com/ros2/rmw_implementation/blob/32c3de1/rmw_implementation/src/functions.cpp#L77

It'd be nice if this code instead preferred currently loaded libraries, to support application code that don't want the ability to switch DDS implementations (e.g. simplifying repro cases, etc.) at runtime, and instead RPATH link the appropriate libraries.

Cross compilation rcutils with Android NDK

Cross compiling rcutils with Clang/Android NDK (Android NDK / 19.2.5345600)
results in following compilation error:

Scanning dependencies of target rcutils
[  4%] Building C object CMakeFiles/rcutils.dir/src/process.c.o
/home/EU/dekoehlr/work/ros2_core_ws/src/ros2/rcutils/src/process.c:53:26: error: use of undeclared identifier 'program_invocation_name'
  const char * appname = program_invocation_name;
                         ^
1 error generated.
CMakeFiles/rcutils.dir/build.make:332: recipe for target 'CMakeFiles/rcutils.dir/src/process.c.o' failed
make[2]: *** [CMakeFiles/rcutils.dir/src/process.c.o] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/rcutils.dir/all' failed
make[1]: *** [CMakeFiles/rcutils.dir/all] Error 2
Makefile:140: recipe for target 'all' failed
make: *** [all] Error 2

As possible fix for this issue is to check for the __clang__ flag and use getprogname() instead of program_invocation_name specific to GCC/glibc.

index 08122de..fd77318 100644
--- a/src/process.c
+++ b/src/process.c
@@ -47,7 +47,7 @@ char * rcutils_get_executable_name(rcutils_allocator_t allocator)
   RCUTILS_CHECK_ALLOCATOR_WITH_MSG(
     &allocator, "invalid allocator", return NULL);
 
-#if defined __APPLE__
+#if defined __APPLE__ || __clang__
   const char * appname = getprogname();
 #elif defined __GNUC__
   const char * appname = program_invocation_name;

The script to reproduce the results is as follows:

#!/usr/env bash
#
# ROS2 Cross compiler build setup for Android SDK
#
# Prerequisites: 
# - installed Android NDK and cmake build tool addons.

export WORK_DIR=$HOME/work
export ROS2_WORKSPACE=$WORK_DIR/ros2_core_ws

# Provide Android SDK location
export JAVA_HOME=$HOME/local/android-studio/jre
export ANDROID_SDK=$HOME/local/android-sdk
export ANDROID_NDK=$HOME/local/android-sdk/ndk-bundle

export PATH=$ANDROID_SDK/tools/bin:${PATH}
export PATH=$ANDROID_SDK/platform-tools:${PATH}

# Android build toolchain
export ANDROID_ABI=armeabi-v7a
export ANDROID_NATIVE_API_LEVEL=android-21
export ANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-clang
export ANDROID_STL=c++_shared

# Download and install ROS2 sources
mkdir -p $ROS2_WORKSPACE
cd $ROS2_WORKSPACE
if [ ! -d src ]; then
  mkdir src
  wget -nc https://raw.githubusercontent.com/ros2/ros2/master/ros2.repos
  vcs import src < ros2.repos

  # Patch rcutils/src/process.c to support compilation with clang
  echo -e "50c50\n< #if defined __APPLE__\n---\n> #if defined __APPLE__ || __clang__" | patch src/ros2/rcutils/src/process.c
fi

# Partition packages into host and device build
# Note: Amend index is dependency of rclcpp_components - do not build for host.
AMENT_LINT=$(echo ament_{lint_common,lint_auto,lint_cmake,flake8,pep257,copyright})
AMENT_CMAKE=$(echo ament_cmake ament_cmake_{core,test,gmock,gtest,pytest,libraries,nose,python,pytest})
AMENT_INDEX="ament_index_python"

PKG_AMENT="${AMENT_CMAKE} ${AMENT_LINT} ${AMENT_INDEX} ament_cmake_ros ament_package ament_pclint ament_clang_format osrf_pycommon uncrustify_vendor osrf_testing_tools_cpp"
PKG_PYTHON="python_cmake_module rosidl_generator_py rclpy rosidl_runtime_py launch launch_ros launch_testing_ament_cmake"
PKG_EXTRAS="intra_process_demo orocos_kdl rclpy resource_retriever tf2_ros libcurl_vendor tinyxml2_vendor tinyxml_vendor"
PKG_CONNEXT="rosidl_typesupport_connext_c rosidl_typesupport_connext_cpp rmw_connext_cpp rmw_connext_shared_cpp" 
PKG_OPENSPLICE="rosidl_typesupport_opensplice_c rmw_opensplice_cpp rosidl_typesupport_opensplice_cpp"

# Ignore packages which cannot be build on target device
PKG_IGNORE="rcl_logging_log4cxx  ${PKG_PYTHON} ${PKG_EXTRAS} ${PKG_CONNEXT} ${PKG_OPENSPLICE} ${PKG_AMENT}"
PKG_EXAMPLES=$(echo examples_rclcpp_minimal_{action_client,action_server,client,composition,publisher,subscriber,service,timer})
PKG_TARGET="${PKG_EXAMPLES} ament_index_cpp composition demo_nodes_cpp_native lifecycle logging_demo"

echo "* Host build of Ament:"
colcon build --symlink-install \
  --build-base build/host \
  --install-base install/host \
  --cmake-clean-cache \
  --packages-skip-build \
  --packages-up-to ${PKG_AMENT}

source install/host/local_setup.bash
  
echo "* Device build of ROS2:"
colcon build --symlink-install  \
  --build-base build/device \
  --install-base install/device \
  --packages-up-to ${PKG_TARGET} \
  --packages-ignore ${PKG_IGNORE} \
  --cmake-clean-cache \
  --cmake-args \
    --no-warn-unused-cli \
    -DCMAKE_BUILD_TYPE=Release \
    -DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake \
    -DANDROID_NATIVE_API_LEVEL=${ANDROID_NATIVE_API_LEVEL} \
    -DANDROID_TOOLCHAIN_NAME=${ANDROID_TOOLCHAIN_NAME} \
    -DANDROID_STL=${ANDROID_STL} \
    -DANDROID_ABI=${ANDROID_ABI} \
    -DANDROID_NDK=${ANDROID_NDK} \
    -DTHIRDPARTY=ON \
    -DCOMPILE_EXAMPLES=OFF \
    -DBUILD_TESTING=OFF \
    -DCMAKE_FIND_ROOT_PATH="$ROS2_WORKSPACE/install/host;$ROS2_WORKSPACE/install/device" \
    -DRCL_LOGGING_IMPLEMENTATION=rcl_logging_noop

Besides this minor issue, I was able to cross compile the core components of ROS2 on Android. Keep up the good work!

Best regards,

Roderick

Progress toward Quality Level 1

This issue tracks the progression of rcutils to Quality Level 1 and a 1.0 version level. It follows the outline described in REP 2004.

  • Version Policy
    • Follows ROS Core Quality Declaration
  • Version >= 1.0.0
  • Change Control Process
  • API and ABI stability within a ROS distribution
  • Vulnerability Disclosure Policy

Documentation

  • Per-feature documentation.
  • Per-item documentation in public API.
  • Declared set of licenses
  • Copyright statement in each source file
    • Checked with ament_copyright
  • Quality Declaration document

Testing:

  • System tests, which cover "features"
  • Tests covering public API
  • Code Coverage > 95%:
      • Must have code coverage tracking for the package -> here
      • Must have and enforce a code coverage policy for new changes Policy
  • Performance tests: not currently available.
  • Linters and Static Analysis:

Dependencies:

  • Runtime "ROS" dependencies are level 1
    • None
  • non-ROS dependencies are equivalent level 1
    • None

Platform Support

  • Supports all tier 1 platforms as described in REP-2000

failure to record due to QNX not defined in rcutils_get_platform_library_name()

in

#ifdef __linux__
if (debug) {
if (buffer_size >= (strlen(library_name) + 8)) {
written = rcutils_snprintf(
library_name_platform, strlen(library_name) + 8, "lib%sd.so", library_name);
}
} else {
if (buffer_size >= (strlen(library_name) + 7)) {
written = rcutils_snprintf(
library_name_platform, strlen(library_name) + 7, "lib%s.so", library_name);
}
}
#elif __APPLE__
if (debug) {
if (buffer_size >= (strlen(library_name) + 11)) {
written = rcutils_snprintf(
library_name_platform, strlen(library_name) + 11, "lib%sd.dylib", library_name);
}
} else {
if (buffer_size >= (strlen(library_name) + 10)) {
written = rcutils_snprintf(
library_name_platform, strlen(library_name) + 10, "lib%s.dylib", library_name);
}
}
#elif _WIN32
if (debug) {
if (buffer_size >= (strlen(library_name) + 6)) {
written = rcutils_snprintf(
library_name_platform, strlen(library_name) + 6, "%sd.dll", library_name);
}
} else {
if (buffer_size >= (strlen(library_name) + 5)) {
written = rcutils_snprintf(
library_name_platform, strlen(library_name) + 5, "%s.dll", library_name);
}
}
#endif

QNX is not defined so rcutils_snprintf() never gets called and variable "written" remains zero. This triggers the error checking code at
if (written <= 0) {
RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING(
"failed to format library name: '%s'\n",
library_name);
return RCUTILS_RET_ERROR;
}
which causes a call to "ros2 bag record /topic" to fail

`test_string_map` is leaking memory

ASAN detected, will send a PR to fix this.

Running main() from ../../../install-asan/gtest_vendor/src/gtest_vendor/src/gtest_main.cc
[==========] Running 16 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 16 tests from test_string_map
[ RUN      ] test_string_map.lifecycle
[       OK ] test_string_map.lifecycle (0 ms)
[ RUN      ] test_string_map.getters
[       OK ] test_string_map.getters (0 ms)
[ RUN      ] test_string_map.reserve_and_clear
[       OK ] test_string_map.reserve_and_clear (0 ms)
[ RUN      ] test_string_map.check_size_and_capacity
[       OK ] test_string_map.check_size_and_capacity (0 ms)
[ RUN      ] test_string_map.set_no_resize_check_size_and_capacity
[       OK ] test_string_map.set_no_resize_check_size_and_capacity (0 ms)
[ RUN      ] test_string_map.set_no_resize_exceeding_capacity
[       OK ] test_string_map.set_no_resize_exceeding_capacity (0 ms)
[ RUN      ] test_string_map.set_no_resize
[       OK ] test_string_map.set_no_resize (1 ms)
[ RUN      ] test_string_map.set
[       OK ] test_string_map.set (0 ms)
[ RUN      ] test_string_map.key_exists
[       OK ] test_string_map.key_exists (0 ms)
[ RUN      ] test_string_map.key_existsn
[       OK ] test_string_map.key_existsn (0 ms)
[ RUN      ] test_string_map.unset
[       OK ] test_string_map.unset (0 ms)
[ RUN      ] test_string_map.get
[       OK ] test_string_map.get (0 ms)
[ RUN      ] test_string_map.getn
[       OK ] test_string_map.getn (0 ms)
[ RUN      ] test_string_map.get_next_key
[       OK ] test_string_map.get_next_key (0 ms)
[ RUN      ] test_string_map.copy
[       OK ] test_string_map.copy (0 ms)
[ RUN      ] test_string_map.strange_keys
[       OK ] test_string_map.strange_keys (0 ms)
[----------] 16 tests from test_string_map (1 ms total)

[----------] Global test environment tear-down
[==========] 16 tests from 1 test case ran. (1 ms total)
[  PASSED  ] 16 tests.

=================================================================
==21916==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 72 byte(s) in 1 object(s) allocated from:
    #0 0x7f5be60feb50 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb50)
    #1 0x7f5be5e10ba5 in __default_allocate (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0x3ba5)
    #2 0x55a76cc9f832 in failing_malloc (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x19832)
    #3 0x7f5be5e189ff in rcutils_string_map_init (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0xb9ff)
    #4 0x55a76ccbd269 in test_string_map_set_no_resize_Test::TestBody() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x37269)
    #5 0x55a76cd72efb in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xecefb)
    #6 0x55a76cd64ca3 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xdeca3)
    #7 0x55a76cd10a97 in testing::Test::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x8aa97)
    #8 0x55a76cd11ec2 in testing::TestInfo::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x8bec2)
    #9 0x55a76cd12a66 in testing::TestCase::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x8ca66)
    #10 0x55a76cd2db77 in testing::internal::UnitTestImpl::RunAllTests() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xa7b77)
    #11 0x55a76cd759ae in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xef9ae)
    #12 0x55a76cd66f6c in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xe0f6c)
    #13 0x55a76cd2a90b in testing::UnitTest::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xa490b)
    #14 0x55a76ccfde5a in RUN_ALL_TESTS() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x77e5a)
    #15 0x55a76ccfdda0 in main (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x77da0)
    #16 0x7f5be527db96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)

Direct leak of 72 byte(s) in 1 object(s) allocated from:
    #0 0x7f5be60feb50 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb50)
    #1 0x7f5be5e10ba5 in __default_allocate (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0x3ba5)
    #2 0x7f5be5e189ff in rcutils_string_map_init (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0xb9ff)
    #3 0x55a76cca47d4 in test_string_map_getters_Test::TestBody() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x1e7d4)
    #4 0x55a76cd72efb in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xecefb)
    #5 0x55a76cd64ca3 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xdeca3)
    #6 0x55a76cd10a97 in testing::Test::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x8aa97)
    #7 0x55a76cd11ec2 in testing::TestInfo::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x8bec2)
    #8 0x55a76cd12a66 in testing::TestCase::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x8ca66)
    #9 0x55a76cd2db77 in testing::internal::UnitTestImpl::RunAllTests() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xa7b77)
    #10 0x55a76cd759ae in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xef9ae)
    #11 0x55a76cd66f6c in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xe0f6c)
    #12 0x55a76cd2a90b in testing::UnitTest::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xa490b)
    #13 0x55a76ccfde5a in RUN_ALL_TESTS() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x77e5a)
    #14 0x55a76ccfdda0 in main (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x77da0)
    #15 0x7f5be527db96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)

Direct leak of 72 byte(s) in 1 object(s) allocated from:
    #0 0x7f5be60feb50 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb50)
    #1 0x7f5be5e10ba5 in __default_allocate (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0x3ba5)
    #2 0x55a76cc9f832 in failing_malloc (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x19832)
    #3 0x7f5be5e189ff in rcutils_string_map_init (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0xb9ff)
    #4 0x55a76ccca40d in test_string_map_set_Test::TestBody() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x4440d)
    #5 0x55a76cd72efb in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xecefb)
    #6 0x55a76cd64ca3 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xdeca3)
    #7 0x55a76cd10a97 in testing::Test::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x8aa97)
    #8 0x55a76cd11ec2 in testing::TestInfo::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x8bec2)
    #9 0x55a76cd12a66 in testing::TestCase::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x8ca66)
    #10 0x55a76cd2db77 in testing::internal::UnitTestImpl::RunAllTests() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xa7b77)
    #11 0x55a76cd759ae in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xef9ae)
    #12 0x55a76cd66f6c in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xe0f6c)
    #13 0x55a76cd2a90b in testing::UnitTest::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xa490b)
    #14 0x55a76ccfde5a in RUN_ALL_TESTS() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x77e5a)
    #15 0x55a76ccfdda0 in main (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x77da0)
    #16 0x7f5be527db96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)

Direct leak of 8 byte(s) in 1 object(s) allocated from:
    #0 0x7f5be60fef40 in realloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdef40)
    #1 0x7f5be5e10bed in __default_reallocate (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0x3bed)
    #2 0x55a76cc9fb16 in failing_realloc (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x19b16)
    #3 0x7f5be5e18e9b in rcutils_string_map_reserve (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0xbe9b)
    #4 0x7f5be5e18ab4 in rcutils_string_map_init (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0xbab4)
    #5 0x55a76ccca40d in test_string_map_set_Test::TestBody() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x4440d)
    #6 0x55a76cd72efb in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xecefb)
    #7 0x55a76cd64ca3 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xdeca3)
    #8 0x55a76cd10a97 in testing::Test::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x8aa97)
    #9 0x55a76cd11ec2 in testing::TestInfo::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x8bec2)
    #10 0x55a76cd12a66 in testing::TestCase::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x8ca66)
    #11 0x55a76cd2db77 in testing::internal::UnitTestImpl::RunAllTests() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xa7b77)
    #12 0x55a76cd759ae in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xef9ae)
    #13 0x55a76cd66f6c in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xe0f6c)
    #14 0x55a76cd2a90b in testing::UnitTest::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xa490b)
    #15 0x55a76ccfde5a in RUN_ALL_TESTS() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x77e5a)
    #16 0x55a76ccfdda0 in main (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x77da0)
    #17 0x7f5be527db96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)

Direct leak of 8 byte(s) in 1 object(s) allocated from:
    #0 0x7f5be60fef40 in realloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdef40)
    #1 0x7f5be5e10bed in __default_reallocate (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0x3bed)
    #2 0x55a76cc9fb16 in failing_realloc (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x19b16)
    #3 0x7f5be5e18efa in rcutils_string_map_reserve (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0xbefa)
    #4 0x7f5be5e18ab4 in rcutils_string_map_init (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0xbab4)
    #5 0x55a76ccca40d in test_string_map_set_Test::TestBody() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x4440d)
    #6 0x55a76cd72efb in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xecefb)
    #7 0x55a76cd64ca3 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xdeca3)
    #8 0x55a76cd10a97 in testing::Test::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x8aa97)
    #9 0x55a76cd11ec2 in testing::TestInfo::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x8bec2)
    #10 0x55a76cd12a66 in testing::TestCase::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x8ca66)
    #11 0x55a76cd2db77 in testing::internal::UnitTestImpl::RunAllTests() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xa7b77)
    #12 0x55a76cd759ae in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xef9ae)
    #13 0x55a76cd66f6c in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xe0f6c)
    #14 0x55a76cd2a90b in testing::UnitTest::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xa490b)
    #15 0x55a76ccfde5a in RUN_ALL_TESTS() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x77e5a)
    #16 0x55a76ccfdda0 in main (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x77da0)
    #17 0x7f5be527db96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)

Direct leak of 8 byte(s) in 1 object(s) allocated from:
    #0 0x7f5be60fef40 in realloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdef40)
    #1 0x7f5be5e10bed in __default_reallocate (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0x3bed)
    #2 0x55a76cc9fb16 in failing_realloc (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x19b16)
    #3 0x7f5be5e18efa in rcutils_string_map_reserve (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0xbefa)
    #4 0x7f5be5e18ab4 in rcutils_string_map_init (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0xbab4)
    #5 0x55a76ccbd269 in test_string_map_set_no_resize_Test::TestBody() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x37269)
    #6 0x55a76cd72efb in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xecefb)
    #7 0x55a76cd64ca3 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xdeca3)
    #8 0x55a76cd10a97 in testing::Test::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x8aa97)
    #9 0x55a76cd11ec2 in testing::TestInfo::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x8bec2)
    #10 0x55a76cd12a66 in testing::TestCase::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x8ca66)
    #11 0x55a76cd2db77 in testing::internal::UnitTestImpl::RunAllTests() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xa7b77)
    #12 0x55a76cd759ae in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xef9ae)
    #13 0x55a76cd66f6c in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xe0f6c)
    #14 0x55a76cd2a90b in testing::UnitTest::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xa490b)
    #15 0x55a76ccfde5a in RUN_ALL_TESTS() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x77e5a)
    #16 0x55a76ccfdda0 in main (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x77da0)
    #17 0x7f5be527db96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)

Direct leak of 8 byte(s) in 1 object(s) allocated from:
    #0 0x7f5be60fef40 in realloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdef40)
    #1 0x7f5be5e10bed in __default_reallocate (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0x3bed)
    #2 0x55a76cc9fb16 in failing_realloc (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x19b16)
    #3 0x7f5be5e18e9b in rcutils_string_map_reserve (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0xbe9b)
    #4 0x7f5be5e18ab4 in rcutils_string_map_init (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/install/rcutils/lib/librcutils.so+0xbab4)
    #5 0x55a76ccbd269 in test_string_map_set_no_resize_Test::TestBody() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x37269)
    #6 0x55a76cd72efb in void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xecefb)
    #7 0x55a76cd64ca3 in void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xdeca3)
    #8 0x55a76cd10a97 in testing::Test::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x8aa97)
    #9 0x55a76cd11ec2 in testing::TestInfo::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x8bec2)
    #10 0x55a76cd12a66 in testing::TestCase::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x8ca66)
    #11 0x55a76cd2db77 in testing::internal::UnitTestImpl::RunAllTests() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xa7b77)
    #12 0x55a76cd759ae in bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xef9ae)
    #13 0x55a76cd66f6c in bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xe0f6c)
    #14 0x55a76cd2a90b in testing::UnitTest::Run() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0xa490b)
    #15 0x55a76ccfde5a in RUN_ALL_TESTS() (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x77e5a)
    #16 0x55a76ccfdda0 in main (/home/ANT.AMAZON.COM/tmoulard/ros2_ws/build-asan/rcutils/test_string_map+0x77da0)
    #17 0x7f5be527db96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)

SUMMARY: AddressSanitizer: 248 byte(s) leaked in 7 allocation(s).

RCUTILS_SET_ERROR_MSG use

According to doxygen and this line, RCUTILS_SET_ERROR_MSG() should produce output if rcutils_reset_error wasn't called and this library was built with the RCUTILS_REPORT_ERROR_HANDLING_ERRORS flag set. I see that the flag is set here and here. Since there are many of the RCUTILS_SET_ERROR_MSG (and RMW_SET_ERROR_MSG) calls in RCL and RMW, I wouldn't expect to see the stderr prints occur at all in run time unless turned by some means. What am I missing to turn these prints on?

find() and find_last() functions return ambiguous value

If a NULL or empty string is passed into rcutils_find() or rcutils_find_last(), they return 0. However, it may also be the case that the delimiter being searched for is in the zero'th position, and the caller doesn't have any way to disambiguate this. As discussed in #57 (review), we should probably change this so that rcutils and rcutils_find_last return something different; either a negative value (which would require us to change the return type), or the size of the string (indicating it wasn't found). The latter will obviously only work on empty strings, not NULL arguments. In either case, we need to audit all of the callers and make sure they do the correct thing.

Provide compile-time ROS2 version information

As ROS2 matures and introduces new API, we need ways to conditionally compile code against different, possibly compile-time incompatible, versions of ROS2.

Common ways to do it are:

  • Define version macros or constants in C or C++ header file, e.g. (from FDRS code):
    #define FASTCDR_VERSION_MAJOR 1
    #define FASTCDR_VERSION_MINOR 0
    #define FASTCDR_VERSION_MICRO 9
    #define FASTCDR_VERSION_STR "1.0.9"
  • Define version information in a CMake file and later generate a header file with C/C++ version macros or constants.

change name of this repository

Some people, including myself, feel that this repository/package name is not ideal and that we should change it, see: #13 (comment) (and perhaps other conversations). If you disagree please chime in here.


The top contenders seem to be:

  • rcutils
  • rcu
  • roscutils

I'll try to keep a running tally of people's preferences (in ranked choice where available):


When/if we select a new name, we should act quickly to update all instances to minimize impact on git history and cross-references. Also, we should update this package to use the full package name in the manual namespacing throughout.

I talked with @Karsten1987 offline about this and I came up with two criteria which could improve the name of this package:

  • A shorter name
    • since this is package contains C code, its functions and types need to be manually namespaced by prefixing them with the package name
    • @dirk-thomas pointed out that some shortcuts have been taken, using utitlities_ instead of the full c_utilities_ for example
      • I agree with him, that using the exact package name in the namespace is a very useful convention
    • a shorter name will keep it convenient and prevent the desire for shortcuts like these
  • A name with some reference to our project or organization
    • My concern is that c_utilities_ and especially utilities_ is not a very unique name
    • a unique name helps avoid symbol collisions and makes it more obvious that some part of the code is part of our project

Based on these goals I just threw out some alternatives, but I'm not really attached to any of them so please others chime in with options:

  • osrfcutils OSRF C Utilities
    • could be extended for other languages, e.g. for C++ as osrfcpputils
  • osrfcu OSRF C Utilities
    • could be extended for other languages, e.g. for C++ as osrfcppu
  • osrflibc OSRF Library for C
    • could be extended for other languages, e.g. for C++ as osrflibcpp
  • libosrfc Library used at OSRF for C
    • could be extended for other languages, e.g. for C++ as libosrfcpp
    • library names could be modified so that they come out as libosrfc.ext rather than liblibosrfc.ext
  • osrfc OSRF C utilities library
    • could be extended for other languages, e.g. for C++ as osrfcpp
    • library names would naturally be libosrfc.ext
  • rcutils ROS C Utilities
    • could be extended for other languages, e.g. for C++ as rcpputils

There were some others, but I didn't really like them or they collided with existing things, for example anything containing roslib might be confused with:

https://github.com/ros/ros/tree/lunar-devel/core/roslib

Or that ros2* sounds like you're converting to something from ros, or anything containing comm and not knowing if that's short for "common" or "communication".

My personal favorite atm is probably osrfc or libosrfc, as I think utils or utilities is a bit redundant or catch all, sort of like misc or common. To me leaving off words like that implies the same thing. I also think that they're pretty unlikely to collide with anything else and are relatively short.

Rename logger "severity threshold" to "level"

[Please speak up if you have any objections, otherwise I'll go ahead with this after lunch.]

Each log message has a particular severity level e.g. DEBUG. Loggers can be configured to only process messages at and above a level e.g. INFO by default, currently with the "severity threshold" of the logger.

While writing logging demos I've formed the opinion that using "severity threshold" to specify this in function names is long winded.

I propose to rename functions such as rcutils_logging_set_logger_severity_threshold to rcutils_logging_set_logger_level, and update wrapping in rclpy to match.

This will match terminology in ros1, python logging module and log4cxx.

rcutils logging cleanup

I am thinking about how to specify logger severities progammatically, and would like input regarding memory de-allocation.

Suppose that we already have an appropriate data structure that represents the mapping of logger names to severities, and users have a call that let's them specify severities of loggers at runtime. These are the options that I see for managing the memory of that data structure:

  1. We allow the memory for the severity data structure to grow at runtime.
  2. We pre-allocate an amount of memory for the data structure and don't let usage go above that amount.
  3. [Alternative for completeness] Don't store the data structure; just check a config file or other data source each time.

I've been assuming that (1) is preferred, but that might not be the case. If (1) is preferred, and if the memory allocation is managed in C, we will also have to have a way to de-allocate the memory, but there is no symmetric concept of the rcutils_logging_initialize that de-allocates memory at the moment.

These are the options that I see if we want to continue with (1):

  1. If sticking to C, create a fini function that de-allocates the severity data structure. It will be logging users' responsibility to call it when done with the logging system.
    1. Optionally the function could be called from within rcl_shutdown to assist ROS users. However, they might still want to call logging macros after rcl_shutdown.
  2. Switch to C++ underneath and use automatic memory management.
  3. Automatic memory management in C (I've read that we could implement/pull in a garbage collector).

Implementing the fini for option (1) is not necessarily an issue, but I'm not sure that requiring users to call it is quite reasonable, which is why I'm stopping to ask if we should go in the C or C++ direction.
Perhaps it's possible to have an implementation somewhere in the middle, where C++ users don't have to call the fini, but C users do: e.g. the memory management implemented in C, and optionally if C++ support is built we have a smart pointer that automatically calls the C fini on destruction.

What do others think regarding the two points?

Included utils to load, unload and get symbols from shared libraries

This PR is to track the process of get rid of Poco dependency. We use the poco library for loading shared libraries dynamically at runtime. It will be nice to remove this dependency which is relatively large. The idea is to include this functionality in this package.

Changes to be done:

Linking error (test_atomics_executable) on Raspbian/armv6l

I am trying to compile ROS dashing from source on Raspbian Buster (gcc (Raspbian 8.3.0-6+rpi1) 8.3.0) running on armv6l and encounter a linking error for target test_atomics_executable:

/usr/bin/ld: CMakeFiles/test_atomics_executable.dir/test/test_atomics.c.o: in function `main':
test_atomics.c:(.text+0x11a8): undefined reference to `__atomic_store_8'
/usr/bin/ld: test_atomics.c:(.text+0x11c0): undefined reference to `__atomic_load_8'
/usr/bin/ld: test_atomics.c:(.text+0x1268): undefined reference to `__atomic_store_8'
/usr/bin/ld: test_atomics.c:(.text+0x12b8): undefined reference to `__atomic_exchange_8'
[...]

I am using the standard repo at https://raw.githubusercontent.com/ros2/ros2/release-latest/ros2.repos, excluding rviz2 and rqt.

Edit: The problem can be resolved by manually adding -latomic, i.e. target_link_libraries(test_atomics_executable ${PROJECT_NAME} -latomic).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.