Skip to content

Conversation

brody4hire
Copy link
Contributor

@brody4hire brody4hire commented Aug 23, 2024

STATUS: initial draft with some ugly hacks & ugly naming - needs some cleanup & discussion before merging - can we find a way to break this update into smaller & cleaner pieces?


WHAT

implement idea 1 discussed in: #2068 /cc @bjoernQ

with the following new features (need to discuss & improve naming):

  • withrcalias - use an internal alias to use alloc::rc::Rc instead of alloc::sync::Arc; this removes Send + Sync from many pub traits, making it impossible to share config state between threads
  • defaultproviderenabled - use this feature to enable default provider API functions, which will not work together with the withrcalias feature - TODO item is to add this to the default feature list (I encountered some issues with this, think I encountered this: cargo test --all don't honor --no-default-features for member project rust-lang/cargo#7160 (comment))

I decided to keep these as separate options as well, may make sense to consider combining them in some form / fashion.

May include some other, very minor code & testing updates, for example:

APPROACH

  • add & use new, internal alias module to alias alloc::rc::Rc as Arc when the withrcalias feature is enabled
  • add & use new, internal pub_api_trait & internal_generic_state_trait macros to define certain traits with or without Send + Sync, as needed for the build to succeed, depending on whether withrcalias feature is absent or present
  • use defaultproviderenabled feature configuration to enable or disable default provider API functions, which will not build or work when the withrcalias feature is enabled
  • UPDATED SOLUTION: using internal crypto_default_provider module to manage default crypto provider state in a cleaner manner, regardless of withrcalias feature, with thanks to once_cell with critical-section feature

NOTE that this includes an update I proposed in #2087, as needed to build when the withrcalias feature is enabled. (PR #2087 is now merged & merged into this proposal)

RATIONALE

HOW TESTED

  • cargo build -p rustls -F withrcalias (try building of package with withrcalias feature enabled)
  • cargo build -F defaultproviderenabled (try full build with defaultproviderenabled feature enabled)
  • cargo test -p rustls -F withrcalias (unit test of package with withrcalias feature enabled)
  • cargo test -F defaultproviderenabled (full unit testing with defaultproviderenabled feature enabled)
  • cargo test -p rustls (less important - unit test of package with both new feature options not enabled)
  • now working with multiple cross-rs test targets
  • build now tested with thumbv6m-none-eabi, with no atomic pointer functionality

TODO items & loose ends

  • git grep "pub.*trait.*Send" shows some more public traits that should probably be updated to use pub_api_trait macro, to remove Send + Sync when the withrcalias feature is enabled - it may be ideal to add some more unit tests to check that Send + Sync is gone for these public traits with optional withrcalias feature
  • it would be ideal if we can migrate from the new, internal macros to using conditional marker aliases, not sure if Rust will ever provide stable or even unstable support for this kind of thing
  • fix & update the generated API documentation
  • known CI testing issues that need to be resolved
  • add new feature options to CI feature testing
  • may have issue with --all-features cargo option (I am wondering if custom-provider could lead to a similar issue with built-in providers not enabled)
  • resolve many warning messages
  • clean up some ugly hacks
  • resolve commented XXX & TODO items - git grep XXX should not show any new results with this proposal
  • improve consistency of formatting of #[cfg(...)] formatting

…mics built-in

with the following new features:

* withrcalias - use an internal alias to use alloc::rc::Rc instead of alloc::sync::Arc
  removes Send + Sync from many pub traits, making it impossible to share
  config state between threads

* defaultproviderenabled - use this feature to enable default provider API functions
  will not work together with the withrcalias feature

APPROACH:

* add & use new, internal alias module to alias alloc::rc::Rc as Arc for withrcalias feature
* add & use new, internal macros to define certain traits  with or without Send + Sync,
  depending on whether withrcalias feature is absent or present
Copy link
Member

@djc djc left a comment

Choose a reason for hiding this comment

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

This looks pretty reasonable -- here's some initial feedback (but feel free to prioritize other stuff first).

# XXX TODO ADD THIS TO DEFAULT FEATURES
defaultproviderenabled = []
# XXX TODO NAMING - ADD SEPARATORS
withrcalias = []
Copy link
Member

Choose a reason for hiding this comment

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

For naming, I'd suggest rc-as-arc.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will likely propose a different solution for this, as discussed elsewhere thanks.

Comment on lines +638 to +639
#[cfg(not(feature = "withrcalias"))]
#[cfg(feature = "std")]
Copy link
Member

Choose a reason for hiding this comment

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

Should merge double cfg attributes everywhere.

Why disable this for withrcalias?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I recall using Rc led to an issue with this due to lack of Send + Sync marker traits.

#[cfg(not(feature = "withrcalias"))]
macro_rules! pub_api_trait {
($name:ident, $body:tt) => {
pub trait $name: core::fmt::Debug + Send + Sync $body
Copy link
Member

Choose a reason for hiding this comment

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

I haven't tried this, but I was assuming this would work:

#[cfg(target_has_atomic = "ptr")]
pub trait ThreadSafe : Send + Sync {}

#[cfg(not(target_has_atomic = "ptr"))]
pub trait ThreadSafe {}

(then each extension point trait would be pub trait ResolvesServerCert: Debug + ThreadSafe { ... })

Copy link
Member

Choose a reason for hiding this comment

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

Oh, good idea.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did already try this kind of idea, discovered that API user would need to add additional empty impl block for the added "ThreadSafe" trait. Looks like Rust unstable would support trait alias, not sure how well this would work for conditional usage of the Send + Sync marker traits.

# XXX TODO ADD THIS TO DEFAULT FEATURES
defaultproviderenabled = []
# XXX TODO NAMING - ADD SEPARATORS
withrcalias = []
Copy link
Member

Choose a reason for hiding this comment

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

Can we actually do this with features? It causes a public API breaking change. Perhaps we can use #[cfg(target_has_atomic = "ptr")], which simply echoes the non-portability of Arc?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I would totally like to get rid of the new features, do have a couple questions:

Any pointers or ideas how we might test this in CI (and on a local workstation)?

I would also love to add an option to keep the Arc support working with the portable-atomics crate. This could increase the complexity of the cfg conditions in multiple places. We could try to address this at some point in the future, with a little extra code churn.

@brody4hire brody4hire marked this pull request as draft August 26, 2024 02:14
Comment on lines 573 to 575
#[cfg(feature = "defaultproviderenabled")]
mod crypto_default_provider {
use alloc::sync::Arc;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have already proposed this update in PR #2089. I am planning to update this cfg attribute to get rid of the new feature options.

… is good practice for a library) ... with mutliple caveats to help avoid excess complexity in rustls/src/crypto/mod.rs:

- explicit critical-section now REQUIRED for non-std - enforced by compile error for now
- critical-section is now ALWAYS ENABLED in case withrcalias is enabled

add build & run steps with explicit critical-section

remove some commented code now obsolete from rustls/src/crypto/mod.rs

XXX TODO: SHOULD SUPPORT no-std without critical-section required (see portable-atomic crate for description why critical-section should not be required in a library)
…e_cell/tree/propagate-critical-section-to-portable-atomic - no more need for explicit portable-atomic dependency with explicit "portable-atomic/critical-section" setting for critical-section option
Comment on lines +231 to 243
/// This will be `None` if no default has been set yet.
#[cfg(not(feature = "withrcalias"))]
pub fn get_default() -> Option<&'static Arc<Self>> {
static_default::get_default()
}

/// Returns the default `CryptoProvider` for this process.
///
/// This will be `None` if no default has been set yet.
pub fn get_default() -> Option<&'static Arc<Self>> {
PROCESS_DEFAULT_PROVIDER.get()
#[cfg(feature = "withrcalias")]
pub fn get_default() -> Option<Arc<Self>> {
static_default::get_default()
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unfortunately this API function has a somewhat different return type depending on the build configuration.

Existing return type with static-lifetime reference to Arc cannot be replicated with Rc alias due to differences in storing & cloning.

I would rather not break existing API usage for any existing users.

I think I need to add a note to the source to explain this.

brody4hire and others added 4 commits September 3, 2024 16:25
…n rustls/Cargo.toml

with help from sed:

    % sed -i.orig~~ "s/#.*NOTE:/# NOTE:/g" rustls/Cargo.toml

verified that the following now shows no more weird results:

    % git grep "#.*NOTE:" | grep -v "# NOTE:"
@cpu
Copy link
Member

cpu commented Sep 9, 2024

Just wanted to leave a note here that I'm going to wait to review this until it's out of draft status and the commit history is easier to approach. Please tag if there are specific questions I could try to answer in the meantime!

…te XXX comment in rustls/Cargo.toml"

This reverts commit 68639d3.
@brody4hire brody4hire marked this pull request as ready for review September 10, 2024 00:37
@brody4hire
Copy link
Contributor Author

@cpu it looks to me like updating aws-lc-rs as proposed in PR #2118 is needed for cross testing to succeed in GitHub CI, hopeful that change will be merged in the near future.

I am now thinking of taking another approach which I may end up proposing in a brand-new PR. My apologies for all of the noise with this one!

@djc djc marked this pull request as draft September 10, 2024 10:00
@djc
Copy link
Member

djc commented Sep 10, 2024

I am now thinking of taking another approach which I may end up proposing in a brand-new PR. My apologies for all of the noise with this one!

Going to flip this back to draft for now, then.

@brody4hire brody4hire changed the title DRAFT RFC: add option to use alloc::rc::Rc for no-std targets w/o built-in atomic ops - FIRST HACK ALT DRAFT RFC: add option to use alloc::rc::Rc for no-std targets w/o built-in atomic ops - INITIAL HACK Nov 8, 2024
@brody4hire
Copy link
Contributor Author

brody4hire commented Nov 8, 2024

I would like to close this one for now. I think that the alternative I proposed in PR #2200 should be much cleaner & easier to understand. I do think this would be an interesting option to consider adding in the future, but it would likely be less drastic if we can finish & merge #2200 first.


P.S. I think & hope that I have addressed all feedback from here that may apply to PR #2200.

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.

5 participants