Skip to content

Latest commit

 

History

History
96 lines (80 loc) · 2.76 KB

File metadata and controls

96 lines (80 loc) · 2.76 KB

Timeouts

Plugins and extensions have variable runtimes (network calls, daemon queries, heavy computation), so each one declares its own runtime budget in its code. This page explains how that works.

The problem

The core runs plugins and extensions as subprocesses. Without any time control, a hung plugin hangs xfetch (and the config load, for extensions) forever.

The solution: with_timeout

All three crates (xfetch-plugin-api, xfetch-extension-api, xfetch-effect-api) expose the same helper:

pub fn with_timeout<T: Send + 'static>(
    budget: Duration,
    task: impl FnOnce() -> T + Send + 'static,
) -> Result<T, TimedOut>
  • The task runs on a worker thread.
  • Ok(task()) is returned when it finishes within budget.
  • Err(TimedOut) is returned when the budget elapses. The worker thread keeps running until the process exits — which is immediate, because the plugin/extension responds (or errors) and terminates.

Guidelines

  • Declare a const BUDGET that fits the work: ~2 s for local probes, 15–25 s for network calls.
  • Wrap everything (including reading the request from stdin) in the closure.
  • On Err(TimedOut), respond with fallback lines (info plugins), fallback frames or the unmodified lines (effects), or exit with an error (animation plugins, extensions).

Example

use std::time::Duration;
use xfetch_plugin_api::{read_info_plugin_args_or_default, with_timeout, write_info_lines};

const BUDGET: Duration = Duration::from_secs(10);

fn main() {
    let lines = with_timeout(BUDGET, || {
        let args = match read_info_plugin_args_or_default::<MyArgs>() {
            Ok(v) => v,
            Err(err) => {
                eprintln!("{}", err);
                std::process::exit(1);
            }
        };
        do_work(&args)
    })
    .unwrap_or_else(|_| vec!["MyPlugin: timed out".to_string()]);

    if let Err(err) = write_info_lines(lines) {
        eprintln!("{}", err);
        std::process::exit(1);
    }
}

Safety net

with_timeout is the standard for official plugins and extensions (enforced in CI). As an extra safety net, the core can also kill the process after an optional per-plugin deadline (timeout_secs in the config), which protects against third-party or uncooperative plugins. See the main xfetch documentation.