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

Safer transaction: add End() method and don't use as error #15

Merged
merged 15 commits into from
Nov 30, 2023

Conversation

3v1n0
Copy link
Collaborator

@3v1n0 3v1n0 commented Oct 12, 2023

As per discussions we had, Transaction is not fully thread safe and the fact it could be returned as an error makes things worse because its Error() value, that depends on the state could be changed while it's processed.

So:

  • Always return error structure/status values instead of the transaction itself
  • Remove the finalizer (or maybe make it toggable) adding an End() method.

These are both breaking changes, but would simplify #13 too.

Closes: #14


Note that this also includes #16

@3v1n0 3v1n0 force-pushed the safer-transaction branch 5 times, most recently from 01beba4 to 65c9789 Compare October 14, 2023 02:30
@3v1n0 3v1n0 force-pushed the safer-transaction branch from 65c9789 to 085f3e9 Compare October 25, 2023 19:13
@3v1n0 3v1n0 force-pushed the safer-transaction branch 2 times, most recently from 05f5108 to 3fd81f1 Compare November 6, 2023 21:58
@3v1n0 3v1n0 mentioned this pull request Nov 7, 2023
@3v1n0 3v1n0 force-pushed the safer-transaction branch 4 times, most recently from 34f1192 to 3e66e55 Compare November 7, 2023 15:48
@3v1n0 3v1n0 force-pushed the safer-transaction branch 5 times, most recently from a0acd6e to bdc316f Compare November 21, 2023 21:14
Copy link
Owner

@msteinert msteinert left a comment

Choose a reason for hiding this comment

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

Hi Marco, sorry for the delay in reviewing! I haven't been able to make much time for open source lately.

This looks really good, I'm excited for the 2.0 release. Let me know what you think. I'm willing to make some of the changes I suggested if you're feeling burned out on this project.

transaction.go Outdated Show resolved Hide resolved
transaction.go Outdated Show resolved Hide resolved
transaction.go Outdated Show resolved Hide resolved
transaction.go Show resolved Hide resolved
transaction.go Outdated Show resolved Hide resolved
transaction.go Outdated Show resolved Hide resolved
transaction.go Outdated Show resolved Hide resolved
transaction.go Outdated Show resolved Hide resolved
transaction.go Outdated Show resolved Hide resolved
transaction_test.go Show resolved Hide resolved
@3v1n0 3v1n0 force-pushed the safer-transaction branch 2 times, most recently from 40c6d38 to bb76ea3 Compare November 29, 2023 15:53
And use them instead of C ones. Given that we have strings for them we
can easily implement error interfaces for it too.
Use pam_debug.so to generate pam configurations at test time and
check if the returned values expect the ones we want.
If the transaction fails during start, there's no way to get the error
detail in a programmatic way, so let's wrap the pam.Error to allow more
per-type checks.
…atus

All the pam functions return an integer with the status of the operation
so instead of duplicating the same code everywhere, that is quite error
prone, use an helper function.

It would have been nice to make this more dynamic, but cgo doesn't allow
us to do much magic here.

This is enough though.
Transactions save the status of each operation in a status field, however
such field could be written concurrently by various operations, so we
need to be sure that:
 - We always return the status for the current operation
 - We store the status in a atomic way so that other actions won't
   create write races

In general, in a multi-thread operation one should not rely on
Transaction.Error() to get info about the last operation.
While transaction does implement error, it's not a valid error
implementer because it may have bogous values since it's not thread-safe
and so we may read the result of Error() when it's into an invalid state

As per this never return it as an error, while always return the Status
unless when not available, where we still return pam.Error.
…more

As per previous commit, Transaction can't be used anymore as an error
value, but we instead we always return the status code.
A PAM transaction needs to be ended in order to release the associated
resources, however this can't be sadly automated as the go finalizers
run in goroutines and this could cause problems to modules that we load.

In fact a module code may be called back during pam_end (to cleanup data
for example) and the module code could not be thread safe.

So let's make this more manual, but safer.
The transaction status is still preserved in the transaction so end will
be automatically called with the last-known status.

Closes: msteinert#14
@3v1n0 3v1n0 force-pushed the safer-transaction branch from 378f970 to 75e26f6 Compare November 30, 2023 00:24
transaction_test.go Outdated Show resolved Hide resolved
Check if a transaction is ended in in tests.
…nd Style types

We redefined various PAM constant values for items, flags and style, but
only few of them were marked as being Item's or Flag's. This caused go to
just consider them as generic integers instead of the actual subtype.
@3v1n0 3v1n0 force-pushed the safer-transaction branch from 75e26f6 to 067f634 Compare November 30, 2023 01:49
@msteinert msteinert merged commit 4ce1d8a into msteinert:master Nov 30, 2023
3 checks passed
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.

Finalizer is not thread safe and may end up breaking some modules
2 participants