Skip to content
This repository has been archived by the owner on May 21, 2024. It is now read-only.

Some exception refactoring #1658

Merged
merged 8 commits into from
Apr 28, 2020
Merged

Conversation

lbonn
Copy link
Contributor

@lbonn lbonn commented Apr 24, 2020

Tests do not pass yet and it will probably need some changes in tuf-test-vectors as well.

@lbonn lbonn force-pushed the refactor/OTA-2178/exceptions-rework branch 2 times, most recently from 3b621ee to b192770 Compare April 24, 2020 12:41
@lbonn
Copy link
Contributor Author

lbonn commented Apr 24, 2020

@patrickvacek Just checking on uptane vectors

{director,image_repo}root_rotation_version{skip,unchanged} return "Uptane::SecurityException: Version in Root metadata doesn't match the expected value". I suppose it's better than unmet threshold? I'll probably change it to a more specific exception anyway.

@pattivacek
Copy link
Collaborator

{director,image_repo}_root_rotation_version_{skip,unchanged} return "Uptane::SecurityException: Version in Root metadata doesn't match the expected value". I suppose it's better than unmet threshold? I'll probably change it to a more specific exception anyway.

"Version in Root metadata doesn't match the expected value" sounds correct to me. A lot of the errors expected by the vector tests are bogus because we were waiting on this refactoring before spending too much time getting everything just right. I think the "umet threshold" and a few others are common exceptions that really should be something more detailed.

@pattivacek
Copy link
Collaborator

I'll probably change it to a more specific exception anyway.

Just saw the RootVersionChainMismatch that you added. That looks like an improvement!

@lbonn
Copy link
Contributor Author

lbonn commented Apr 24, 2020

"Version in Root metadata doesn't match the expected value" sounds correct to me. A lot of the errors expected by the vector tests are bogus because we were waiting on this refactoring before spending too much time getting everything just right. I think the "umet threshold" and a few others are common exceptions that really should be something more detailed.

Thanks, that's what I thought. I've opened a PR with the changes, the text is now "One Root version is not a strict increment of the preceding." (to not re-use a plain SecurityException). I guess we can discuss names and descriptions there advancedtelematic/tuf-test-vectors#71

@lbonn
Copy link
Contributor Author

lbonn commented Apr 24, 2020

I also realized that removing "plain throws" like I did here #1654 was a mistake. When done in a catch clause, it rethrows the caught exception.

@lbonn lbonn force-pushed the refactor/OTA-2178/exceptions-rework branch from 9989505 to b0faaaa Compare April 24, 2020 13:36
@pattivacek
Copy link
Collaborator

I also realized that removing "plain throws" like I did here #1654 was a mistake. When done in a catch clause, it rethrows the caught exception.

I don't think I understand the problem; that sounds like what I expected. What's wrong with rethrowing?

@lbonn
Copy link
Contributor Author

lbonn commented Apr 24, 2020

I also realized that removing "plain throws" like I did here #1654 was a mistake. When done in a catch clause, it rethrows the caught exception.

I don't think I understand the problem; that sounds like what I expected. What's wrong with rethrowing?

Ah sorry it was unclear. Exactly, nothing wrong with rethrowing :).

try {
} catch (const std::exception& e) {
  throw;
}

is actually better than

try {
} catch (const std::exception& e) {
  throw e;
}

Because in the second case, we slice the original exception and loose the original context.

@lbonn lbonn force-pushed the refactor/OTA-2178/exceptions-rework branch from b0faaaa to 846bbf7 Compare April 24, 2020 15:10
Copy link
Collaborator

@pattivacek pattivacek left a comment

Choose a reason for hiding this comment

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

Already looks like a big improvement! What's the benefit of last_exception in SotaUptaneClient, though? And I'd like to make sure that @eu-smirnov is on board with this direction.

Because in the second case, we slice the original exception and loose the original context.

Oh crap, right. Good catch.

src/libaktualizr/uptane/uptane_test.cc Outdated Show resolved Hide resolved
src/libaktualizr/uptane/imagerepository.cc Outdated Show resolved Hide resolved
src/libaktualizr/primary/sotauptaneclient.cc Outdated Show resolved Hide resolved
src/libaktualizr/uptane/imagerepository.cc Outdated Show resolved Hide resolved
src/libaktualizr/uptane/imagerepository.cc Outdated Show resolved Hide resolved
src/libaktualizr/uptane/directorrepository.cc Outdated Show resolved Hide resolved
src/libaktualizr/uptane/directorrepository.cc Show resolved Hide resolved
@@ -23,14 +23,17 @@ class RepositoryType {
enum class Type { kUnknown = -1, kImage = 0, kDirector = 1 };

public:
static const std::string IMAGE;
static const std::string DIRECTOR;

Copy link
Collaborator

Choose a reason for hiding this comment

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

👍👍👍👍👍👍 This should've been done long ago!

src/libaktualizr/primary/sotauptaneclient.cc Outdated Show resolved Hide resolved
@lbonn lbonn force-pushed the refactor/OTA-2178/exceptions-rework branch from 846bbf7 to ed5ae21 Compare April 24, 2020 15:44
@lbonn
Copy link
Contributor Author

lbonn commented Apr 24, 2020

Already looks like a big improvement! What's the benefit of last_exception in SotaUptaneClient, though? And I'd like to make sure that @eu-smirnov is on board with this direction.

I tried to not change the external API that tried its best no to throw, so the last_exception is used to report the error reason as understood by tuf-test-vectors. There might be a better way to expose that through the Aktualizr API.

Basically my conclusion was that the way we constructed the API, asynchronous and sending events, using exceptions would be quite awkward and hard to handle (for example, we still want to report something to the backend even if an install fails because of a metadata check). For now I've chosen to reserve them for cases that are hard/impossible to recover from. Otherwise I'm afraid it would actually worsen the usability of the API.

EDIT: so to summarize, the objective right now is to let roll exceptions as far as possible and catch them at a small number of points in API boundaries for error reporting.

@pattivacek
Copy link
Collaborator

I tried to not change the external API that tried its best no to throw, so the last_exception is used to report the error reason as understood by tuf-test-vectors. There might be a better way to expose that through the Aktualizr API.

Basically my conclusion was that the way we constructed the API, asynchronous and sending events, using exceptions would be quite awkward and hard to handle (for example, we still want to report something to the backend even if an install fails because of a metadata check). For now I've chosen to reserve them for cases that are hard/impossible to recover from. Otherwise I'm afraid it would actually worsen the usability of the API.

EDIT: so to summarize, the objective right now is to let roll exceptions as far as possible and catch them at a small number of points in API boundaries for error reporting.

Okay, that makes sense to me. Even if we want to throw exceptions through the API, we would need to do the work in this PR first to make sure we know what we're throwing. I'm open to discussion on what to do from here.

success = true;
} catch (const std::exception &e) {
LOG_ERROR << "Error downloading image: " << e.what();
last_exception = std::current_exception();
Copy link
Contributor

Choose a reason for hiding this comment

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

What prevents us from moving this try..catch block one level higher, to the downloadImages method and get rid of success return value?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because of the EcuDownloadCompleteReport and DownloadTarget event. I tried to move them out but then noticed that aktualizr-lite is calling downloadImage() directly, so it would miss these calls right now.

We'd have to make some changes there to fix this. I can add a comment.

Copy link
Contributor

Choose a reason for hiding this comment

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

Right, I missed them somehow.

@eu-siemann
Copy link
Contributor

Definitely looks like an improvement to me! I'm still unsure about a few places, where I left the comments, and about the idea of catching all exceptions before the API level. But we can discuss it later and it shouldn't prevent us from merging this PR.
It also would be cool if we could avoid

try {
  ...
} catch () {
  LOG_ERROR << "";
  throw;
}

blocks by having more information in the exception object, so we can move the prints higher in the call stack.

@lbonn lbonn force-pushed the refactor/OTA-2178/exceptions-rework branch 2 times, most recently from 4e67f84 to 4022569 Compare April 27, 2020 13:24
@lbonn
Copy link
Contributor Author

lbonn commented Apr 27, 2020

It also would be cool if we could avoid

try {
  ...
} catch () {
  LOG_ERROR << "";
  throw;
}

blocks by having more information in the exception object, so we can move the prints higher in the call stack.

That's true that they are a bit ugly but I thought it's often useful to know the high level operation that caused the error. Sometimes we only have one caller but otherwise, I don't know how to log that better.

Or we define a macro (:smiley:)

@lbonn lbonn force-pushed the refactor/OTA-2178/exceptions-rework branch from adc36c9 to 254ae16 Compare April 27, 2020 14:46
@lbonn lbonn force-pushed the refactor/OTA-2178/exceptions-rework branch 2 times, most recently from 0a6b5f8 to cf357b5 Compare April 28, 2020 07:52
This reverts commit 323ef5d.

Actually, re-throwing in catch clauses with "throw;" is a recommended
C++ idiom.

Signed-off-by: Laurent Bonnans <laurent.bonnans@here.com>
Signed-off-by: Laurent Bonnans <laurent.bonnans@here.com>
Signed-off-by: Laurent Bonnans <laurent.bonnans@here.com>
For now, our API does not throw exceptions in most cases but we still
want to inspect error reasons. However, the last_exception thing is now
limited to SotaUptaneClient.

Signed-off-by: Laurent Bonnans <laurent.bonnans@here.com>
Signed-off-by: Laurent Bonnans <laurent.bonnans@here.com>
Signed-off-by: Laurent Bonnans <laurent.bonnans@here.com>
Signed-off-by: Laurent Bonnans <laurent.bonnans@here.com>
They look better in their corresponding wrappers

Signed-off-by: Laurent Bonnans <laurent.bonnans@here.com>
@lbonn lbonn force-pushed the refactor/OTA-2178/exceptions-rework branch from cf357b5 to 3747ba3 Compare April 28, 2020 08:49
@lbonn
Copy link
Contributor Author

lbonn commented Apr 28, 2020

Should be ready to go

@lbonn lbonn merged commit 20c88a8 into master Apr 28, 2020
@lbonn lbonn deleted the refactor/OTA-2178/exceptions-rework branch April 28, 2020 10:09
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants