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

#105 - Panic Handlers #273

Merged
merged 12 commits into from
Mar 29, 2023
Merged

#105 - Panic Handlers #273

merged 12 commits into from
Mar 29, 2023

Conversation

jmickey
Copy link
Contributor

@jmickey jmickey commented Feb 21, 2023

What this PR does / why we need it:

Allow lib callers to register panic handlers, and choose decide if panics will continue to cause the code to crash.

A defer function has been added to the call sites where panics are made in the library code. Initially I was trying to follow the references up the stack to see if there were fewer places where a defer could be made, but in the end it made the more sense to place the defer close to the panic itself.

Lib consumers can register their own handlers that matches the PanicHandler type - func(interface{}):

import "github.com/open-component-model/ocm/pkg/util/panics"

func main() {

	panics.RegisterPanicHandler(func (in interface{}) {
		// do something
		return true
	})

}

By default panics will always log the stacktrace.

Which issue(s) this PR fixes:
Fixes #105

@jmickey jmickey changed the title add panic package and handler code #105 - Panic Handlers Feb 21, 2023
@jmickey jmickey marked this pull request as ready for review February 23, 2023 15:22
Skarlso
Skarlso previously approved these changes Feb 24, 2023
Copy link
Contributor

@Skarlso Skarlso left a comment

Choose a reason for hiding this comment

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

Nice work! :)

Copy link
Contributor

@mandelsoft mandelsoft left a comment

Choose a reason for hiding this comment

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

I'm wondering how (and why) you have selected the locations to place the defer. It looks like you have chosen places near the occurrence of panics. But this typically leads to a continuing program flow with undefined results, where the caller has no possibility to identify this case, which basically will lead to further runtime panics. These panics are for sure NOT handled by a panic handler, again, so that you still get panics, but now completely unrelated to the original problem.

Similar to the K8S handling, the defer should be placed near a resurrection point in a program flow, where typically a loop for request handling is in place to assure the handling of further requests, even if a single single one runs in such a problematic situation (for example, reconcilation loop). Or at least a place, where you can safely ignore the outcome of a called function and continue with a new calculation context.

A defer inside an ìnit function is questionable. If the program initialization fails because of some basic misalignment, it makes no sense to run the process at all.

The Must versions of functions panic if the non-Must versions return an error.
Placing defers here is also questionable, because you could directly call the error providing function if you want to deal with failures. The Must version is typically intended to be called in init functions (see above).

pkg/utils/panics/panics.go Outdated Show resolved Hide resolved
@jmickey
Copy link
Contributor Author

jmickey commented Mar 2, 2023

I'm wondering how (and why) you have selected the locations to place the defer. It looks like you have chosen places near the occurrence of panics.

Correct. Restricted to panics in the library code.

But this typically leads to a continuing program flow with undefined results, where the caller has no possibility to identify this case, which basically will lead to further runtime panics. These panics are for sure NOT handled by a panic handler, again, so that you still get panics, but now completely unrelated to the original problem.

I would argue that this isn't our concern, but rather the users concern. Optimally we wouldn't panic from library code, but because we do, we should at least provide the option to handle those panics as the user sees fit. I would imagine that in the vast majority of cases the crash will continue. If a user opts to continue the program flow then the consequences of that are for them to deal with.

Similar to the K8S handling, the defer should be placed near a resurrection point in a program flow, where typically a loop for request handling is in place to assure the handling of further requests, even if a single single one runs in such a problematic situation (for example, reconcilation loop). Or at least a place, where you can safely ignore the outcome of a called function and continue with a new calculation context.

I'm not really sure I understand what your saying here, and how it relates in the context of OCM and defer placements.

A defer inside an ìnit function is questionable. If the program initialization fails because of some basic misalignment, it makes no sense to run the process at all.

If you feel strongly about this I can remove the defers from inits. Panicking from an init is, at least to me, also questionable unless that init sits in code that is wholly owned by an executable context rather than lib context (e.g. a cmd executable).

The Must versions of functions panic if the non-Must versions return an error.

The user still may wish to execute some process or code before continuing with a crash, so I think it is still valid to call the handlers here?

@Skarlso
Copy link
Contributor

Skarlso commented Mar 13, 2023

We'll do a compromise and place handling at certain points only. The rest will be handled in a different manner.

The ADR has been accepted by all parties so we'll try to be more in line with that. :)

@In-Ko
Copy link
Member

In-Ko commented Mar 27, 2023

@jmickey / @Skarlso / @mandelsoft : Can we please get this clarified this week ? It is a long runner already, and I'd like to see this being finished soon. My take: If the current implementation is done according to the ACD which we all agreed on, than this should go out.

@Skarlso
Copy link
Contributor

Skarlso commented Mar 27, 2023

Right, so the main points are:

  • The problem with catching a panic where they are is that somewhere along the line another panic will happen because now the result is undefined or even nil so the resulting error will be unrelated to the first panic causing problem.
  • Put the handler into a place of recovering.
    Regarding this point.... There are no safe places in OCM after a panic. There are lot of places where error handling is non-existent so this is at least not really possible without significant changes. I guess in those cases, we will just ignore the panic. I don't have an alternative.
  • Remove the defer in init
  • Ignore MUST functions.

@Skarlso Skarlso requested a review from mandelsoft March 27, 2023 14:42
@Skarlso Skarlso dismissed mandelsoft’s stale review March 27, 2023 14:42

Please re-review with the new changes.

@Skarlso Skarlso force-pushed the 105-panic-handler branch from a510ed3 to 3e8092b Compare March 27, 2023 15:02
Copy link
Contributor

@mandelsoft mandelsoft left a comment

Choose a reason for hiding this comment

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

Good job, to find all the places where a regular error return can do the job to avoid panics at all.

One panic should be avoided by refactoring the interface and add an error return value.
If you want I can do this at short notice. There are probably many places involved.

pkg/signing/handlers/rsa/format.go Outdated Show resolved Hide resolved
pkg/utils/panics/panics.go Show resolved Hide resolved
pkg/contexts/ocm/utils.go Show resolved Hide resolved
pkg/contexts/oci/repositories/ocireg/namespace.go Outdated Show resolved Hide resolved
pkg/contexts/oci/repositories/ocireg/blobs.go Outdated Show resolved Hide resolved
pkg/cobrautils/links.go Outdated Show resolved Hide resolved
cmds/ocm/pkg/utils/handling.go Outdated Show resolved Hide resolved
cmds/ocm/pkg/processing/buffer.go Outdated Show resolved Hide resolved
@Skarlso Skarlso force-pushed the 105-panic-handler branch from 40f7f81 to b2606b4 Compare March 28, 2023 10:43
@Skarlso Skarlso force-pushed the 105-panic-handler branch from 4acaf89 to bb3253f Compare March 28, 2023 11:14
pkg/utils/panics/panics.go Outdated Show resolved Hide resolved
@Skarlso
Copy link
Contributor

Skarlso commented Mar 28, 2023

@mandelsoft This looks good to me now. :) Thanks for the additions. 👍

@Skarlso Skarlso dismissed mandelsoft’s stale review March 29, 2023 05:50

Feel free to merge at your earliest convenience. :)

@Skarlso Skarlso requested a review from mandelsoft March 29, 2023 05:50
pkg/signing/handlers/rsa/format.go Outdated Show resolved Hide resolved
@mandelsoft mandelsoft self-requested a review March 29, 2023 08:30
@mandelsoft mandelsoft merged commit d2d09d0 into main Mar 29, 2023
@Skarlso Skarlso deleted the 105-panic-handler branch March 29, 2023 08:58
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.

panic ADR research: implement a handling POC based on the ADR
4 participants