From 06153d0f28091dc6a18e9f3241e2e760741127c7 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 7 Sep 2016 00:03:43 -0700 Subject: [PATCH] Add docs and travis --- .travis.yml | 24 ++++++++++++++++++++ src/lib.rs | 23 +++++++++++++++++++ src/unix.rs | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..476dbb0d0 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,24 @@ +language: rust + +rust: + - stable + - beta + - nightly +sudo: false +before_script: + - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH +script: + - cargo build + - cargo test + - cargo doc --no-deps +after_success: + - travis-cargo --only nightly doc-upload +env: + global: + - secure: ZP6mBCD3U75sMAn29TtNCOt/ZS5A2GlyPTvbg0V5Ppjsk4L0S5zXLxGgBSA5d5Bay92uTd54u02uEhplIY8fp9AZ5sbHYVmzbnCK6m8iz2kcTL4QmlhqF3Hpv9QcUcnIzhnAmy2ucpk1QxF19vlwMwg7f1CDdEObDn0OcrhOK+tgRQwzDLwdIklkrrNhfv/WjM2vaht/0pRN2yfmDjNOxC8qESJKD85PnVrMyb5SmFVLY3tDiQstBA2hBZ+Lf2FoBD9JztuvMBAJsC6aTFx94Cv6CdcqtRyQRFNaOw65cj97Z5W/ELpcncNQh+VswDYVgoMi2OqSqpqSj3wdVFztb9UTXXuuEirUjoXxzIu0/rff93O3wAiXQKKzNvdZqLRvHYD9FV2e43m0ZlnzQi0f3LcORjOmbQy0tnQgS8anMjryW+20A1HYFAVsA3/GdGfVJY/YRkIV6rQCZ8J1cg4UDZMpiisYTi5qCHAYPmG/R1QzcVg6lKIF4KIvNNCBW2IDxZNDd7cc1MYXrT8GctVoTqcKREYX24UqrOZITaAutKjSasmp7rOtPkUCBHI8gBTEX5XFNWS39Y9J3Km8hrTvmGQ+1jEOCB6NVimpwo5Yljua1gYYmHCgavFuYgv0fntn7WEC4cfx4+xpJtj+5MOm8uzT4i9RUBU+Hjq8yZGl63Y= +notifications: + email: + on_success: never +os: + - linux + - osx diff --git a/src/lib.rs b/src/lib.rs index 2d304ecd0..2165715ab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,26 @@ +//! Asynchronous signal handling for Tokio +//! +//! This crate implements asynchronous signal handling for Tokio, and +//! asynchronous I/O framework in Rust. The primary type exported from this +//! crate, `unix::Signal`, allows listening for arbitrary signals on Unix +//! platforms, receiving them in an asynchronous fashion. +//! +//! Note that signal handling is in general a very tricky topic and should be +//! used with great care. This crate attempts to implement 'best practice' for +//! signal handling, but it should be evaluated for your own applications' needs +//! to see if it's suitable. +//! +//! The are some fundamental limitations of this crate documented on the +//! `Signal` structure as well. +//! +//! > **Note**: This crate compiles on Windows, but currently contains no +//! > bindings. Windows does not have signals like Unix does, but it +//! > does have a way to receive ctrl-c notifications at the console. +//! > It's planned that this will be bound and exported outside the +//! > `unix` module in the future! + +#![deny(missing_docs)] + #[macro_use] extern crate futures; extern crate tokio_core; diff --git a/src/unix.rs b/src/unix.rs index 7d1f30477..f41fe38ff 100644 --- a/src/unix.rs +++ b/src/unix.rs @@ -1,3 +1,8 @@ +//! Unix-specific types for signal handling. +//! +//! This module is only defined on Unix platforms and contains the primary +//! `Signal` type for receiving notifications of signals. + #![cfg(unix)] extern crate libc; @@ -20,6 +25,43 @@ use tokio_core::{LoopHandle, Sender, Receiver, ReadinessStream}; static INIT: Once = ONCE_INIT; static mut GLOBAL_STATE: *mut GlobalState = 0 as *mut _; +/// An implementation of `Stream` for receiving a particular type of signal. +/// +/// This structure implements the `Stream` trait and represents notifications +/// of the current process receiving a particular signal. The signal being +/// listened for is passed to `Signal::new`, and the same signal number is then +/// yielded as each element for the stream. +/// +/// In general signal handling on Unix is a pretty tricky topic, and this +/// structure is no exception! There are some important limitations to keep in +/// mind when using `Signal` streams: +/// +/// * While multiple event loops are supported, the *first* event loop to +/// register a signal handler is required to be active to ensure that signals +/// for other event loops are delivered. In other words, once an event loop +/// registers a signal, it's best to keep it around and running. This is +/// normally just a problem for tests, and the "workaround" is to spawn a +/// thread in the background at the beginning of the test suite which is +/// running an event loop (and listening for a signal). +/// +/// * Signals handling in Unix already necessitates coalescing signals +/// together sometimes. This `Signal` stream is also no exception here in +/// that it will also coalesce signals. That is, even if the signal handler +/// for this process runs multiple times, the `Signal` stream may only return +/// one signal notification. Specifically, before `poll` is called, all +/// signal notifications are coalesced into one item returned from `poll`. +/// Once `poll` has been called, however, a further signal is guaranteed to +/// be yielded as an item. +/// +/// * Signal handling in general is relatively inefficient. Although some +/// improvements are possible in this crate, it's recommended to not plan on +/// having millions of signal channels open. +/// +/// * Currently the "driver task" to process incoming signals never exits. +/// +/// If you've got any questions about this feel free to open an issue on the +/// repo, though, as I'd love to chat about this! In other words, I'd love to +/// alleviate some of these limitations if possible! pub struct Signal { signum: c_int, reg: ReadinessStream, @@ -54,8 +96,27 @@ struct SignalState { } impl Signal { - // TODO: document coalescing (happens everywhere) - // TODO: document multiple event loops (first must stay alive) + /// Creates a new stream which will receive notifications when the current + /// process receives the signal `signum`. + /// + /// This function will create a new stream which may be based on the + /// event loop handle provided. This function returns a future which will + /// then resolve to the signal stream, if successful. + /// + /// The `Signal` stream is an infinite stream which will receive + /// notifications whenever a signal is received. More documentation can be + /// found on `Signal` itself, but to reiterate: + /// + /// * Signals may be coalesced beyond what the kernel already does. + /// * While multiple event loops are supported, the first event loop to + /// register a signal handler must be active to deliver signal + /// notifications + /// * Once a signal handle is registered with the process the underlying + /// libc signal handler is never unregistered. + /// + /// A `Signal` stream can be created for a particular signal number + /// multiple times. When a signal is received then all the associated + /// channels will receive the signal notification. pub fn new(signum: c_int, handle: &LoopHandle) -> IoFuture { let mut init = None; INIT.call_once(|| {