Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions rcl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ set(${PROJECT_NAME}_sources
src/rcl/security.c
src/rcl/service.c
src/rcl/subscription.c
src/rcl/thread_attr_parse.c
src/rcl/thread_context.c
src/rcl/time.c
src/rcl/timer.c
src/rcl/validate_enclave_name.c
Expand Down
24 changes: 24 additions & 0 deletions rcl/include/rcl/arguments.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ typedef struct rcl_arguments_s
/// logging (must be preceded with --enable- or --disable-).
#define RCL_LOG_EXT_LIB_FLAG_SUFFIX "external-lib-logs"

/// The ROS flag that precedes the ROS thread attribute file path.
#define RCL_THREAD_ATTR_FILE_PATH_FLAG "--thread-attr-file-path"

/// The ROS flag that precedes the ROS logging thread attribute.
#define RCL_THREAD_ATTR_SETTING_FLAG "--thread-attr-setting"

/// Return a rcl_arguments_t struct with members initialized to `NULL`.
RCL_PUBLIC
RCL_WARN_UNUSED
Expand Down Expand Up @@ -447,6 +453,24 @@ rcl_ret_t
rcl_arguments_fini(
rcl_arguments_t * args);

/// Return thread attribute parsed from the command line.
/**
* Thread attribute are parsed directly from command line arguments and
* thread attribute files provided in the command line.
*
* \param[in] arguments An arguments structure that has been parsed.
* \param[out] thread_attrs thread attribute as parsed from command line arguments.
* This structure must be finalized by the caller.
* \return #RCL_RET_OK if everything goes correctly, or
* \return #RCL_RET_INVALID_ARGUMENT if any function arguments are invalid, or
*/
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
rcl_arguments_get_thread_attrs(
const rcl_arguments_t * arguments,
rcl_thread_attrs_t ** thread_attrs);

#ifdef __cplusplus
}
#endif
Expand Down
18 changes: 18 additions & 0 deletions rcl/include/rcl/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ extern "C"
#endif

#include "rmw/init.h"
#include "rcl/thread_context.h"

#include "rcl/allocator.h"
#include "rcl/arguments.h"
Expand Down Expand Up @@ -314,6 +315,23 @@ RCL_WARN_UNUSED
rmw_context_t *
rcl_context_get_rmw_context(rcl_context_t * context);

/// Returns the thread attribute context.
/**
* \param[in] context from which the thread attribute should be retrieved.
* \param[out] thread_attrs output variable where the thread attribute will be returned.
* \return #RCL_RET_INVALID_ARGUMENT if `context` is invalid (see rcl_context_is_valid()), or
* \return #RCL_RET_INVALID_ARGUMENT if `context->impl` is `NULL`, or
* \return #RCL_RET_INVALID_ARGUMENT if `*thread_attrs` is not `NULL`, or
* \return #RCL_RET_INVALID_ARGUMENT if `context->impl->thread_context.thread_attrs` is `NULL`, or
* \return #RCL_RET_OK if the thread attribute was correctly retrieved.
*/
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
rcl_context_get_thread_attrs(
const rcl_context_t * context,
rcl_thread_attrs_t ** thread_attrs);

#ifdef __cplusplus
}
#endif
Expand Down
70 changes: 70 additions & 0 deletions rcl/include/rcl/thread_context.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright 2023 eSOL Co.,Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef RCL__THREAD_CONTEXT_H_
#define RCL__THREAD_CONTEXT_H_

#ifdef __cplusplus
extern "C"
{
#endif

#include <stdint.h>

#include "rcl/types.h"
#include "rcl/macros.h"
#include "rcl/visibility_control.h"
#include "rcl_yaml_param_parser/types.h"

/// thread attribute from enviroment value.
typedef struct thread_attr_context_s
{
/// thread attribute.
rcl_thread_attrs_t * thread_attrs;
} thread_attr_context_t;

/// Return a zero initialization thread attribute context object.
RCL_PUBLIC
RCL_WARN_UNUSED
thread_attr_context_t
thread_attr_get_zero_initialized_context(void);

/// Finalize a thread attribute context.
/**
* \param[inout] context object to be finalized.
* \return #RCL_RET_OK if successful, or
* \return #RCL_RET_INVALID_ARGUMENT if any arguments are invalid, or
* \return #RCL_RET_BAD_ALLOC if allocating memory failed
*/
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
thread_attr_context_init(thread_attr_context_t * context, rcutils_allocator_t allocator);

/// Initialize a thread attribute context.
/**
* \param[inout] context object to be finalized.
* \return #RCL_RET_OK if the shutdown was completed successfully, or
* \return #RCL_RET_INVALID_ARGUMENT if any arguments are invalid
*/
RCL_PUBLIC
RCL_WARN_UNUSED
rcl_ret_t
thread_attr_context_fini(thread_attr_context_t * context);

#ifdef __cplusplus
}
#endif

#endif // RCL__THREAD_CONTEXT_H_
2 changes: 2 additions & 0 deletions rcl/include/rcl/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ typedef rmw_ret_t rcl_ret_t;
#define RCL_RET_INVALID_PARAM_RULE 1010
/// Argument is not a valid log level rule
#define RCL_RET_INVALID_LOG_LEVEL_RULE 1020
/// Argument is not a valid thread attr rule
#define RCL_RET_INVALID_THREAD_ATTRS 1030

// rcl event specific ret codes in 20XX
/// Invalid rcl_event_t given return code.
Expand Down
109 changes: 109 additions & 0 deletions rcl/src/rcl/arguments.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@

#include "./arguments_impl.h"
#include "./remap_impl.h"
#include "./thread_attr_parse.h"
#include "rcl/error_handling.h"
#include "rcl/lexer_lookahead.h"
#include "rcl/validate_topic_name.h"
#include "rcl_yaml_param_parser/thread_attr.h"
#include "rcl_yaml_param_parser/parser.h"
#include "rcl_yaml_param_parser/types.h"
#include "rcutils/allocator.h"
Expand Down Expand Up @@ -286,6 +288,12 @@ rcl_parse_arguments(
goto fail;
}

args_impl->thread_attrs = rcl_thread_attrs_struct_init(allocator);
if (NULL == args_impl->thread_attrs) {
ret = RCL_RET_BAD_ALLOC;
goto fail;
}

args_impl->parameter_overrides = rcl_yaml_node_struct_init(allocator);
if (NULL == args_impl->parameter_overrides) {
ret = RCL_RET_BAD_ALLOC;
Expand Down Expand Up @@ -559,6 +567,73 @@ rcl_parse_arguments(
RCL_DISABLE_FLAG_PREFIX, RCL_LOG_EXT_LIB_FLAG_SUFFIX, rcl_get_error_string().str);
rcl_reset_error();

// Attempt to parse argument as thread attribute flag
if (strcmp(RCL_THREAD_ATTR_SETTING_FLAG, argv[i]) == 0) {
if (i + 1 < argc) {
if (args_impl->thread_attrs->num_attributes != 0) {
RCL_SET_ERROR_MSG_WITH_FORMAT_STRING(
"Thread attributes already setted: '%s %s'.", argv[i], argv[i + 1]);
++i;
continue;
}
// Attempt to parse next argument as thread attribute rule
if (RCL_RET_OK ==
_rcl_parse_thread_attrs(argv[i + 1], args_impl->thread_attrs))
{
RCUTILS_LOG_DEBUG_NAMED(
ROS_PACKAGE_NAME, "Got thread attribute rule : %s\n", argv[i + 1]);
++i; // Skip flag here, for loop will skip rule.
continue;
}
rcl_error_string_t prev_error_string = rcl_get_error_string();
rcl_reset_error();
RCL_SET_ERROR_MSG_WITH_FORMAT_STRING(
"Couldn't parse thread attribute rule: '%s %s'. Error: %s", argv[i], argv[i + 1],
prev_error_string.str);
} else {
RCL_SET_ERROR_MSG_WITH_FORMAT_STRING(
"Couldn't parse trailing %s flag. No thread attribute rule found.", argv[i]);
}
ret = RCL_RET_INVALID_ROS_ARGS;
goto fail;
}
RCUTILS_LOG_DEBUG_NAMED(
ROS_PACKAGE_NAME, "Arg %d (%s) is not a %s flag.",
i, argv[i], RCL_THREAD_ATTR_SETTING_FLAG);

// Attempt to parse argument as thread attribute file rule
if (strcmp(RCL_THREAD_ATTR_FILE_PATH_FLAG, argv[i]) == 0) {
if (i + 1 < argc) {
if (args_impl->thread_attrs->num_attributes != 0) {
RCL_SET_ERROR_MSG_WITH_FORMAT_STRING(
"Thread attributes already setted: '%s %s'.", argv[i], argv[i + 1]);
++i;
continue;
}
// Attempt to parse next argument as thread attribute file rule
if (
RCL_RET_OK == _rcl_parse_thread_attr_file(
argv[i + 1], args_impl->thread_attrs))
{
++i; // Skip flag here, for loop will skip rule.
continue;
}
rcl_error_string_t prev_error_string = rcl_get_error_string();
rcl_reset_error();
RCL_SET_ERROR_MSG_WITH_FORMAT_STRING(
"Couldn't parse thread attr file: '%s %s'. Error: %s", argv[i], argv[i + 1],
prev_error_string.str);
} else {
RCL_SET_ERROR_MSG_WITH_FORMAT_STRING(
"Couldn't parse trailing %s flag. No file path provided.", argv[i]);
}
ret = RCL_RET_INVALID_ROS_ARGS;
goto fail;
}
RCUTILS_LOG_DEBUG_NAMED(
ROS_PACKAGE_NAME, "Arg %d (%s) is not a %s flag.",
i, argv[i], RCL_THREAD_ATTR_FILE_PATH_FLAG);

// Argument is an unknown ROS specific argument
args_impl->unparsed_ros_args[args_impl->num_unparsed_ros_args] = i;
++(args_impl->num_unparsed_ros_args);
Expand Down Expand Up @@ -988,6 +1063,17 @@ rcl_arguments_fini(
args->impl->external_log_config_file = NULL;
}

if (args->impl->thread_attrs) {
rcl_ret_t thread_ret = rcl_thread_attrs_fini(args->impl->thread_attrs);
if (thread_ret != RCL_RET_OK) {
ret = thread_ret;
RCUTILS_LOG_ERROR_NAMED(
ROS_PACKAGE_NAME,
"Failed to finalize thread attribute while finalizing arguments. Continuing...");
}
args->impl->thread_attrs = NULL;
}

args->impl->allocator.deallocate(args->impl, args->impl->allocator.state);
args->impl = NULL;
return ret;
Expand Down Expand Up @@ -2063,6 +2149,7 @@ _rcl_allocate_initialized_arguments_impl(rcl_arguments_t * args, rcl_allocator_t
args_impl->parameter_overrides = NULL;
args_impl->parameter_files = NULL;
args_impl->num_param_files_args = 0;
args_impl->thread_attrs = NULL;
args_impl->log_stdout_disabled = false;
args_impl->log_rosout_disabled = false;
args_impl->log_ext_lib_disabled = false;
Expand All @@ -2072,6 +2159,28 @@ _rcl_allocate_initialized_arguments_impl(rcl_arguments_t * args, rcl_allocator_t
return RCL_RET_OK;
}

rcl_ret_t
rcl_arguments_get_thread_attrs(
const rcl_arguments_t * arguments,
rcl_thread_attrs_t ** thread_attrs)
{
RCL_CHECK_ARGUMENT_FOR_NULL(arguments, RCL_RET_INVALID_ARGUMENT);
RCL_CHECK_ARGUMENT_FOR_NULL(arguments->impl, RCL_RET_INVALID_ARGUMENT);
RCL_CHECK_ARGUMENT_FOR_NULL(thread_attrs, RCL_RET_INVALID_ARGUMENT);
if (NULL != *thread_attrs) {
RCL_SET_ERROR_MSG("Output thread attribute pointer is not null. May leak memory.");
return RCL_RET_INVALID_ARGUMENT;
}
*thread_attrs = NULL;
if (NULL != arguments->impl->thread_attrs) {
*thread_attrs = arguments->impl->thread_attrs;
if (NULL == *thread_attrs) {
return RCL_RET_INVALID_ARGUMENT;
}
}
return RCL_RET_OK;
}

#ifdef __cplusplus
}
#endif
Expand Down
3 changes: 3 additions & 0 deletions rcl/src/rcl/arguments_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ struct rcl_arguments_impl_s
/// Length of remap_rules.
int num_remap_rules;

/// thread attribute.
rcl_thread_attrs_t * thread_attrs;

/// Log levels parsed from arguments.
rcl_log_levels_t log_levels;
/// A file used to configure the external logging library
Expand Down
36 changes: 36 additions & 0 deletions rcl/src/rcl/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,27 @@ rcl_context_get_rmw_context(rcl_context_t * context)
return &(context->impl->rmw_context);
}

rcl_ret_t
rcl_context_get_thread_attrs(
const rcl_context_t * context,
rcl_thread_attrs_t ** thread_attrs)
{
RCL_CHECK_ARGUMENT_FOR_NULL(context, RCL_RET_INVALID_ARGUMENT);
RCL_CHECK_ARGUMENT_FOR_NULL(context->impl, RCL_RET_INVALID_ARGUMENT);
if (NULL != *thread_attrs) {
RCL_SET_ERROR_MSG("Output thread attribute pointer is not null. May leak memory.");
return RCL_RET_INVALID_ARGUMENT;
}
*thread_attrs = NULL;
if (NULL != context->impl->thread_context.thread_attrs) {
*thread_attrs = context->impl->thread_context.thread_attrs;
if (NULL == *thread_attrs) {
return RCL_RET_INVALID_ARGUMENT;
}
}
return RCL_RET_OK;
}

rcl_ret_t
__cleanup_context(rcl_context_t * context)
{
Expand Down Expand Up @@ -146,6 +167,21 @@ __cleanup_context(rcl_context_t * context)
}
}

// clean up thread_attr_context
rcl_ret_t thread_attr_context_fini_ret =
thread_attr_context_fini(&(context->impl->thread_context));
if (RCL_RET_OK != thread_attr_context_fini_ret) {
if (RCL_RET_OK == ret) {
ret = thread_attr_context_fini_ret;
}
RCUTILS_SAFE_FWRITE_TO_STDERR(
"[rcl|context.c:" RCUTILS_STRINGIFY(__LINE__)
"] failed to finalize attr context while cleaning up context, memory may be leaked: ");
RCUTILS_SAFE_FWRITE_TO_STDERR(rcutils_get_error_string().str);
RCUTILS_SAFE_FWRITE_TO_STDERR("\n");
rcutils_reset_error();
}

// clean up rmw_context
if (NULL != context->impl->rmw_context.implementation_identifier) {
rmw_ret_t rmw_context_fini_ret = rmw_context_fini(&(context->impl->rmw_context));
Expand Down
2 changes: 2 additions & 0 deletions rcl/src/rcl/context_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ struct rcl_context_impl_s
char ** argv;
/// rmw context.
rmw_context_t rmw_context;
/// thread attribute context.
thread_attr_context_t thread_context;
};

RCL_LOCAL
Expand Down
Loading