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

Async traits #159

Open
SidongYang opened this issue Nov 28, 2024 · 3 comments
Open

Async traits #159

SidongYang opened this issue Nov 28, 2024 · 3 comments
Labels
API-ergonomics Nothing's "broken", but the API could be improved design-required Getting this right will require some thought new-api Add a new feature to the API (possibly non-breaking)

Comments

@SidongYang
Copy link

Hi, I'm using gdbstub crate very well.
I'm writing code for gdbserver that controls embedded system in kernel. Preferred action is to write/read device file in implementing traits like SingleThreadSingleStep::step() or SwBreakpoint::add_sw_breakpoint().
I want to use async file write in these functions but they are not async callback.
Is there any good way to call async function in these traits? or it needs some patch?

@daniel5151
Copy link
Owner

The short answer is that, unfortunately, gdbstub's current feature-level IDET traits are all sync, so unless you're willing to use block_on, there's no good way to call an async function from those handlers.

For context: the last time the question of async in gdbstub came up was in the context of the top-level GdbStub API and the Connection trait, which used to force users to block / periodically poll in order to handle certain aspects of the GDB RSP (see #36). That limitation was worked around in 0.6 with the introduction of the state-machine API, which tweaked the APIs to allow users to manually "pump" the GDB state machine with incoming data, thereby making it easier to integrate into whatever existing async infrastructure their project was using.

This solved the async transport question, but it didn't solve the async handler question, like you're running into.

It seems most folks don't really mind this limitation, but its certainly a limitation nonetheless. The async Rust ecosystem and language support has evolved a lot in the years since gdbstub began development, so it may be time to re-evaluate the possibility of leveraging async / await in gdbstub.

The questions that immediately come to mind here are:

  • At the language level, how easy would it be to use async traits alongside gdbstub's IDET-based API?
  • At the integration level, what would the binary size impact be of using async traits?
    • Would there need to be two parallel GdbStub core implementations, so non-async users don't pay the binary-size tax of having the library be based on async?
  • At the gdbstub codebase level, what would be the best way to support both async and non-async families of traits?

I'm happy to use this issue as a tracking issue for folks to express interest in the feature, as well as explore / answer some of the questions I've posed above.

I'm not sure when I'll have cycles to do some of this work myself, but if you / other folks are interested in helping explore the design-space here, I could certainly try to find some more time and motivation to help work through some of these questions, and/or review some PRs.

@daniel5151 daniel5151 added API-ergonomics Nothing's "broken", but the API could be improved new-api Add a new feature to the API (possibly non-breaking) design-required Getting this right will require some thought labels Nov 28, 2024
@SidongYang
Copy link
Author

It might seem simplistic, but one potential solution could be duplicating all the code handling incoming data into an asynchronous function.

@daniel5151
Copy link
Owner

It might seem simplistic, but one potential solution could be duplicating all the code handling incoming data into an asynchronous function.

Yep, that's certainly an option, and one of the things I was thinking about when I posited: "At the gdbstub codebase level, what would be the best way to support both async and non-async families of traits?"

Note that whatever solution we come up with here needs to adhere to one "non-negotiable" property: gdbstub's codebase cannot manually maintain two parallel API sets - one sync, and one async. That is to say: even if that is the end-user API has two entrypoints - one sync, and one async - the codebase itself must be written such that all APIs only have a source-of-truth, possibly leveraging some kind of macro / code-generation mechanism to have the build system automatically generate the two API variants.

For a time, it seemed like Rust might gain some kind of keyword generics mechanism, to allow a single codebase to expose both sync and async APIs, but to my knowledge, that effort is stalling, and/or may not be the direction the language decides to go in.

In the absence of that sort of language level mechanism, I'm not sure what the current "state of the art" is for supporting that sort of parallel sync vs. async API.


There's also the possibility of swapping the entire gdbstub API from blocking to async, and simply providing some block_on-based helper methods for users that only wish to use GdbStub in a blocking manner. This would be a breaking change, and necessitate a new release, but not totally out of the question.

That said: this solution must conform to one critical property for it to be viable: it cannot bloat the binary size of minimal no_std integrations. This is a key condition, and one that my gut says will not be the case, given the current state of rustc and llvm optimizations.

If you or someone else would like to experiment with this approach, and profile what the impact looks like on codegen, that would be incredibly useful. If it turns out my gut was wrong, and this approach has minimal codegen impact, then I would be more than happy to go with this approach, as it maintains the "single source-of-truth" property without requiring any macros / build-system shenanigans.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API-ergonomics Nothing's "broken", but the API could be improved design-required Getting this right will require some thought new-api Add a new feature to the API (possibly non-breaking)
Projects
None yet
Development

No branches or pull requests

2 participants