Skip to content
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

Update subscription API documentation #256

Merged
merged 5 commits into from
Aug 6, 2020
Merged

Conversation

hidmic
Copy link
Contributor

@hidmic hidmic commented Jul 31, 2020

Precisely what the title says. Each commit is to be kept separately.

Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
@hidmic
Copy link
Contributor Author

hidmic commented Jul 31, 2020

CI up to test_rmw_implementation and rcl, against all RMW implementations:

  • Linux Build Status
  • Linux-aarch64 Build Status
  • macOS Build Status
  • Windows Build Status

* - topic_name is not a valid non-null topic name, according to
* `rmw_validate_full_topic_name()`
* - qos_profile is not a fully specified non-null profile i.e. no UNKNOWN policies
* - subscription_options is not a valid non-null option set, as returned by
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a minor language thing, but "as returned by" implies that you have to pass the rmw_subscription_options_t returned by rmw_get_default_subscription_options().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point.

/// Finalize a given subscription handle, reclaim the resources, and deallocate the subscription
/// handle.
/**
* This function will return early if a logical error, such as `RMW_RET_INVALID_ARGUMENT`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be specific about what logical errors are allowed to trigger an early return, rather than saying "such as"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it can, and in this case, it's purely phrasing i.e. replacing "such as" with "namely" will remain true.

* This function will return early if a logical error, such as `RMW_RET_INVALID_ARGUMENT`
* or `RMW_RET_INCORRECT_RMW_IMPLEMENTATION`, ensues, leaving the given subscription handle
* unchanged.
* Otherwise, it will proceed despite errors, freeing as many resources as it can, including
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

freeing as many resources as it can

This is terribly non-deterministic. After this function returns, the caller won't know what has been freed and what has not.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is terribly non-deterministic. After this function returns, the caller won't know what has been freed and what has not.

I guess the other alternative is to give up as soon as we hit the first error. That also seems non-deterministic (and hard to document), but would that be better in your view?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is terribly non-deterministic. After this function returns, the caller won't know what has been freed and what has not.

I wouldn't say non-deterministic, but rather unspecified. And yes, the caller won't know to what extent the entity was finalized, nor can do anything about it as the subscription will have been deallocated.

As to whether that's a good error handling approach during finalization or not, we've discussed this quite a bit throughout related PRs. To proceed with finalization despite errors precludes the need for strong error (exception) guarantees, which may not even be achievable for a given implementation, and/or dealing with partially finalized entities, likely implementation specific and thus unspecified. The fact that finalization functions are often invoked from object destructors in higher-level language bindings (i.e. at a point where the object is going out of scope anyways) may have also influenced the decision.

I've had mixed feelings about this in the past. But at this point I think that allowing a finalization function to fail helps no one, let alone returning before completion. If it does, it's because you've hit (a) a transient error, which an implementation could deal with by deferring side effects if need be, (b) a logical error, in which the case the program is already broken, or (c) a system error, in which case you can no longer trust the OS that's supporting you.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I guess it's the same as the approach that C++ destructors take: If there's an error in the destructor, give up and assume everything is broken beyond repair.

It is good, though, to be a bit more specific about what errors will cause predictable failure and which will leave things in an indeterminate state. The recent changing of "such as" to "namely" helps there but I think the text could be formatted to make it more obvious, e.g. using a list.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there's an error in the destructor, give up and assume everything is broken beyond repair.

Yeah, but that's largely dependent on the application. Just like in a C++ destructor, you could suppress/log that error (exception) and keep going, which is by far the common pattern in rcl and above.

It is good, though, to be a bit more specific about what errors will cause predictable failure and which will leave things in an indeterminate state.

Hmm, I'm not exactly sure what you're asking for. If you mean that we should specify all possible return codes, they are listed exhaustively below. If you mean that we should specify failure modes, we can't as that's RMW implementation specific. If you mean that we should split the generic RMW_RET_ERROR return code into a few ones to aid the caller on how to proceed, I agree we could but that's orthogonal to this patch (and a new feature entirely).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I guess it's the same as the approach that C++ destructors take: If there's an error in the destructor, give up and assume everything is broken beyond repair.

Maybe that will make destruction code simpler (no need to handle chained errors).

Copy link
Member

@gbiggs gbiggs Aug 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I'm not exactly sure what you're asking for.

If there are errors that could occur but will result in the function not doing anything, those need to be explicitly listed. If there are errors that are known that may leave things in an indefinite state, those also should be listed.

The two are separate from a statement saying "Unknown errors may occur". Basically I'm looking for information that allows a developer to be certain about whether things are now in an unknown state or not. The current wording achieves that, but I feel that a list is more understandable. It's not a requirement, though, so feel free to ignore this if you wish.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there are errors that could occur but will result in the function not doing anything, those need to be explicitly listed.

They are (though I'm not entirely convinced we should be handling logical errors in run-time in any way but terminating the program).

If there are errors that are known that may leave things in an indefinite state, those also should be listed.

There are no known errors, only a blanket one.

Basically I'm looking for information that allows a developer to be certain about whether things are now in an unknown state or not.

See e6620b0. If you get RMW_RET_ERROR, then it's highly likely that something didn't get fully finalized.

Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
@hidmic
Copy link
Contributor Author

hidmic commented Aug 5, 2020

@gbiggs PTAL!

@hidmic hidmic requested a review from gbiggs August 5, 2020 20:39
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
@hidmic hidmic merged commit 0176872 into master Aug 6, 2020
ahcorde pushed a commit that referenced this pull request Oct 13, 2020
* Update subscription creation/destruction API documentation.
* Update subscription QoS querying API documentation.

Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
ahcorde pushed a commit that referenced this pull request Oct 13, 2020
* Update subscription creation/destruction API documentation.
* Update subscription QoS querying API documentation.

Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
@wjwwood wjwwood deleted the hidmic/update-subscriber-docs branch April 22, 2021 18:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants