#mio #linux #api-bindings #signalfd

pakr-mio-signalfd

Adapter of Linux' signalfd to be used with mio 0.7

1 stable release

1.0.0 Sep 26, 2020

#60 in #mio

BSD-2-Clause

10KB
75 lines

Adapter of Linux' signalfd to be used with [mio] 0.7

use std::{thread, time::Duration};
use std::error::Error;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};

use mio::{Events, Interest, Poll, Token};
use pakr_signals::{Pid, Sig, SigSet};

use pakr_mio_signalfd::*;

const TOK: Token = Token(0);

fn main() -> Result<(), Box<dyn Error>> {
    const SIGS: &[Sig] = &[Sig::USR2, Sig::USR1, Sig::QUIT];

    // SigSet we are working with
    let sigs = SigSet::from(SIGS);

    // Make completion flags to be shared between threads
    let done = Arc::new(AtomicBool::new(false));
    let cdone = done.clone();

    // Disable default hadlers of signals we play with
    sigs.disable_default_handler()?;

    // Spawn background thread that will (slowny) bomb our process with signals
    let bomber = thread::spawn(move || {
        // Get my own PID
        let my_pid = Pid::own().unwrap();

        // Repeat some times
        for _ in 0..2 {
            // For each signal on the list
            for &sig in SIGS {
                // Sleep a second
                thread::sleep(Duration::from_secs(1));

                println!("Sending {:?}", sig);

                //  ... then self-send signal
                sig.send_to(my_pid).unwrap();
            }
        }
        // Tell we're done
        cdone.store(true, Ordering::Relaxed)
    });

    // Create a poll instance.
    let mut poll = Poll::new()?;

    // Create storage for events.
    let mut events = Events::with_capacity(128);

    // Create instance of signal watcher
    let mut watcher = SignalFd::new(&sigs)?;

    // Register watcher in mio registry. This handle is readable only
    poll.registry().register(
        &mut watcher,
        TOK,
        Interest::READABLE,
    )?;

    // Repeat while not told done
    while !done.load(Ordering::Relaxed) {

        // Poll Mio for events, blocking until we get an event or timeout on 3s.
        poll.poll(&mut events, Some(Duration::from_secs(3)))?;

        // Process each event.
        for event in events.iter() {
            // We can use the token we previously provided to `register` to
            // determine for which socket the event is.
            match event.token() {
                TOK => {
                    println!("Handled event");
                    while let Some(siginfo) = watcher.read()? {
                        println!("Got signal {:?}", Sig::from(siginfo.ssi_signo as i32));
                    }
                    println!("---");
                }

                // We don't expect any events with tokens other than those we provided.
                _ => { println!("Other event"); }
            }
        }
    }

    // Join with bomber thread
    bomber.join().unwrap();

    // Re-enable default handlers
    sigs.enable_default_handler()?;

    // We're done
    Ok(())
}

Dependencies

~0.5–0.8MB
~14K SLoC