-
Notifications
You must be signed in to change notification settings - Fork 225
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ParameterUninitializedException on accessing parameter that is not yet set crashes node #1030
Comments
Yeah. Comparing rclpp, rclpy has different behaviors. According to the current implementation, rclpy doesn't support just setting the type. self.declare_parameter('my_parameter', Parameter.Type.STRING) will execute below code (value is None and without type) Line 504 in 3d8547a
For no type case, it tries to get type via input value. rclpy/rclpy/rclpy/parameter.py Lines 132 to 135 in 3d8547a
Since value is None, type is set rclpy/rclpy/rclpy/parameter.py Lines 51 to 52 in 3d8547a
So an exception is thrown while get parameter Lines 667 to 676 in 3d8547a
For current implementation of rclpy/rclpy/rclpy/parameter.py Lines 80 to 106 in 3d8547a
|
Yes, agreed with everything that @Barry-Xu-2018 said. Definitely a bug, and I think we should make it behave like rclcpp here. |
@Barry-Xu-2018 @iuhilnehc-ynos can we address this issue? for me, this is more like security level issue, since we can crash the different process space. |
…t set crashes node ros2/rclpy#1030 Signed-off-by: Tomoya Fujita <[email protected]>
@fujitatomoya Yes. I will submit a PR to fix this. |
During fixing this, I find a problem. Refer to the implementation of rclcpp, it uses exception For rclpy, the definition of declaration function is Lines 343 to 349 in 3d8547a
The value can be a parameter value or parameter type. For supporting static type, current interface have to be changed (break API). |
I think what we need to do is to deal with the extra exception rclpy/rclpy/rclpy/parameter_service.py Line 83 in e8850d6
|
Yes. Here we can deal with this exception. The above comment (#1030 (comment)) describe a problem which uninitialized static type parameter can be declared in rclpy. Besides, get_parameters_service_ = create_service<rcl_interfaces::srv::GetParameters>(
node_base, node_services,
node_name + "/" + parameter_service_names::get_parameters,
[node_params](
const std::shared_ptr<rmw_request_id_t>,
const std::shared_ptr<rcl_interfaces::srv::GetParameters::Request> request,
std::shared_ptr<rcl_interfaces::srv::GetParameters::Response> response)
{
try {
auto parameters = node_params->get_parameters(request->names);
for (const auto & param : parameters) {
response->values.push_back(param.get_value_message());
}
} catch (const rclcpp::exceptions::ParameterNotDeclaredException & ex) {
RCLCPP_DEBUG(rclcpp::get_logger("rclcpp"), "Failed to get parameters: %s", ex.what());
}
},
qos_profile, nullptr); For node_params->get_parameters() std::vector<rclcpp::Parameter>
NodeParameters::get_parameters(const std::vector<std::string> & names) const
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
std::vector<rclcpp::Parameter> results;
results.reserve(names.size());
for (auto & name : names) {
auto found_parameter = parameters_.find(name);
if (found_parameter != parameters_.cend()) {
// found
results.emplace_back(name, found_parameter->second.value);
} else if (this->allow_undeclared_) {
// not found, but undeclared allowed
results.emplace_back(name, rclcpp::ParameterValue());
} else {
// not found, and undeclared are not allowed
throw rclcpp::exceptions::ParameterNotDeclaredException(name);
}
}
return results;
} |
I believe that is the specification, so we need to change the API if we have to. |
In rclcpp, template<typename ParameterT>
auto
Node::declare_parameter(
const std::string & name,
const rcl_interfaces::msg::ParameterDescriptor & parameter_descriptor,
bool ignore_override)
{
// get advantage of parameter value template magic to get
// the correct rclcpp::ParameterType from ParameterT
rclcpp::ParameterValue value{ParameterT{}};
try {
return this->declare_parameter(
name,
value.get_type(),
parameter_descriptor,
ignore_override
).get<ParameterT>();
} catch (const ParameterTypeException &) {
throw exceptions::UninitializedStaticallyTypedParameterException(name);
}
} this->declare_parameter() return For rclpy, it provide interface Lines 343 to 349 in 3d8547a
The returned value is We can keep current API. User can do |
It should not crash. |
Bug report
I'm not sure if this is a bug or a feature. When you try to access a parameter on a node from the CLI or from another node, the node hosting the parameter will crash rather than return an error message.
Required Info:
Steps to reproduce issue
ros2 param get /minimal_param_node my_parameter
Expected behavior
successful=False
andreason="parameter 'my_parameter' not initialized yet"
Actual behavior
Additional information
I consider the node crashing undesired behavior in this scenario since it explicitly requires the user to wrap
rclpy.spin()
or equivalent in some try-catch loop. I can see several use cases for this, for example when a different node is responsible for managing another node's parameters or wants to get information of another node's parameters.The text was updated successfully, but these errors were encountered: