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

feat: make ctrlc available to plugins #13181

Merged
merged 52 commits into from
Jul 30, 2024
Merged

Conversation

cablehead
Copy link
Contributor

@cablehead cablehead commented Jun 19, 2024

Description

This PR adds a new method to EngineInterface: register_ctrlc_handler which takes a closure to run when the plugin's driving engine receives a ctrlc-signal. It also adds a mirror of the signals attribute from the main shell EngineState.

This is an example of how a plugin which makes a long poll http request can end the request on ctrlc: https://github.com/cablehead/nu_plugin_http/blob/main/src/commands/request.rs#L68-L77

To facilitate the feature, a new attribute has been added to EngineState: ctrlc_handlers. This is a Vec of closures that will be run when the engine's process receives a ctrlc signal.

When plugins are added to an engine_state during a merge_delta, the engine passes the ctrlc_handlers to the plugin's .configure_ctrlc_handler method, which gives the plugin a chance to register a handler that sends a ctrlc packet through the PluginInterface, if an instance of the plugin is currently running.

On the plugin side: EngineInterface also has a ctrlc_handlers Vec of closures. Plugin calls can use register_ctrlc_handler to register a closure that will be called in the plugin process when the PluginInput::Ctrlc command is received.

For future reference these are some alternate places that were investigated for tying the ctrlc trigger to transmitting a Ctrlc packet through the PluginInterface:

  • Directly from src/signals.rs: the handler there would need a reference to the Vec<Arc>, which would require us to wrap the plugins in a Mutex, which we don't want to do.

  • have PersistentPlugin.get_plugin pass down the engine's CtrlcHandlers to .get and then to .spawn (if the plugin isn't already running). Once we have CtrlcHandlers in spawn, we can register a handler to write directly to PluginInterface. We don't want to double down on passing engine_state to spawn this way though, as it's unpredictable because it would depend on whether the plugin has already been spawned or not.

  • pass ctrlc_handlers to PersistentPlugin::new so it can store it on itself so it's available to spawn.

  • in PersistentPlugin.spawn, create a handler that sends to a clone of the GC event loop's tx. this has the same issues with regards to how to get CtrlcHandlers to the spawn method, and is more complicated than a handler that writes directly to PluginInterface

User-Facing Changes

No breaking changes

@cablehead cablehead marked this pull request as ready for review June 23, 2024 20:10
@devyn devyn added wait-until-after-nushell-release plugins This issue is about plugins pr:plugins This PR is related to plugins labels Jun 23, 2024
@fdncred
Copy link
Collaborator

fdncred commented Jul 18, 2024

I saw the conversation with Ian about his Signals PR. Do we need to wait on some resolution to combine two approaches or should we land this like we discussed yesterday?

@cablehead
Copy link
Contributor Author

I saw the conversation with Ian about his Signals PR. Do we need to wait on some resolution to combine two approaches or should we land this like we discussed yesterday?

Thanks for checking in @fdncred! Let's wait on merging. I just want to think the Signals piece through a bit more.

@fdncred fdncred marked this pull request as draft July 18, 2024 17:20
@fdncred
Copy link
Collaborator

fdncred commented Jul 18, 2024

sounds good. i've made it draft until you're ready. thanks for working on this!

Copy link
Member

@IanManske IanManske left a comment

Choose a reason for hiding this comment

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

I looked over it very briefly, and nothing jumps out as needing fixing. Because the host shell and its plugins operate/run in different manners, I think it's fine if the underlying ctrl+c implementations are different (they might need to be). It would be nice though, if the interrupt interface for plugin authors mimicked that of the main shell code. But this is not strictly necessary.

crates/nu-plugin-engine/src/persistent.rs Outdated Show resolved Hide resolved
@cablehead
Copy link
Contributor Author

It would be nice though, if the interrupt interface for plugin authors mimicked that of the main shell code. But this is not strictly necessary.

Right, I'm going to update to set an AtomicBool on the plugin side when the ctrlc frame arrives. I'll make that a Signals though so it mirrors the main shell Engine.

@cablehead cablehead marked this pull request as ready for review July 23, 2024 21:02
@cablehead
Copy link
Contributor Author

signals is now available on the EngineInterface:

eprintln!("interrupt status: {:?}", engine.signals().interrupted());

@fdncred fdncred merged commit 7b82c6b into nushell:main Jul 30, 2024
13 checks passed
@fdncred
Copy link
Collaborator

fdncred commented Jul 30, 2024

Thanks

@hustcer hustcer added this to the v0.97.0 milestone Jul 30, 2024
@cablehead
Copy link
Contributor Author

Thank you @fdncred!

@cablehead cablehead deleted the plugin-ctrlc branch July 30, 2024 14:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pr:plugins This PR is related to plugins signal-cancel Problems with how executions react to signals or attempts at cancellation (CTRL-C) wait-until-after-nushell-release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants