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

Counter and channel implementations #60

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@ edition = "2018"
readme = "README.md"

[target.'cfg(unix)'.dependencies]
nix = "0.20"
nix = "0.22"

[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["consoleapi", "handleapi", "synchapi", "winbase"] }
winapi = { version = "0.3", features = ["consoleapi", "fileapi", "handleapi", "namedpipeapi", "synchapi", "winbase", "winerror"] }

[dependencies]
byteorder = "1.4"
lazy_static = "1.4"

[target.'cfg(windows)'.dev-dependencies]
winapi = { version = "0.3", features = ["fileapi", "processenv", "winnt"] }
Expand Down
2 changes: 1 addition & 1 deletion LICENSE-APACHE
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ APPENDIX: How to apply the Apache License to your work.
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright 2017 CtrlC developers
Copyright 2021 CtrlC developers

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
59 changes: 44 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,62 @@ A simple easy to use wrapper around Ctrl-C signal.

[Documentation](http://detegr.github.io/doc/ctrlc/)

## Example usage
# Example usage
## Channel example

```rust
use std::sync::mpsc::channel;
use ctrlc;
use ctrlc::{Channel, SignalType};

fn main() {
let (tx, rx) = channel();

ctrlc::set_handler(move || tx.send(()).expect("Could not send signal on channel."))
.expect("Error setting Ctrl-C handler");

let channel = Channel::new(SignalType::Ctrlc).unwrap();
println!("Waiting for Ctrl-C...");
rx.recv().expect("Could not receive from channel.");
println!("Got it! Exiting...");
channel.recv().unwrap();
println!("Got it! Exiting...");
}
```

#### Try the example yourself
`cargo build --examples && target/debug/examples/readme_example`
## Counter example
```rust
use ctrlc;
use ctrlc::{Counter, SignalType};
use std::thread;
use std::time;

## Handling SIGTERM
Add CtrlC to Cargo.toml using `termination` feature and CtrlC will handle both SIGINT and SIGTERM.
fn main() {
let counter = Counter::new(SignalType::Ctrlc).unwrap();
println!("Waiting for Ctrl-C...");
while counter.get() == 0 {
thread::sleep(time::Duration::from_millis(10));
}
println!("Got it! Exiting...");
}
```
[dependencies]
ctrlc = { version = "3.0", features = ["termination"] }

## Handling multiple signals
```rust
use ctrlc;
use ctrlc::{Channel, Signal, SignalType};

fn main() {
let channel = Channel::new_with_multiple()
.add_signal(SignalType::Ctrlc)
.add_signal(SignalType::Other(
#[cfg(unix)] { Signal::SIGTERM },
#[cfg(windows)] { Signal::CTRL_BREAK_EVENT },
))
.build()
.unwrap();
println!("Waiting for signal...");
channel.recv().unwrap();
println!("Got it! Exiting...");
}
```

#### Try the examples yourself
`cargo run --example channel_example`
`cargo run --example counter_example`

## License

Licensed under either of
Expand Down
18 changes: 18 additions & 0 deletions examples/channel_example.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) 2021 CtrlC developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use ctrlc;
use ctrlc::{Channel, SignalType};

fn main() {
let channel = Channel::new(SignalType::Ctrlc).unwrap();
println!("Waiting for Ctrl-C...");
channel.recv().unwrap();
println!("Got it! Exiting...");
}
22 changes: 22 additions & 0 deletions examples/counter_example.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) 2021 CtrlC developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use ctrlc;
use ctrlc::{Counter, SignalType};
use std::thread;
use std::time;

fn main() {
let counter = Counter::new(SignalType::Ctrlc).unwrap();
println!("Waiting for Ctrl-C...");
while counter.get() == 0 {
thread::sleep(time::Duration::from_millis(10));
}
println!("Got it! Exiting...");
}
22 changes: 22 additions & 0 deletions examples/multiple_signals_example.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use ctrlc;
use ctrlc::{Channel, Signal, SignalType};

fn main() {
let channel = Channel::new_with_multiple()
.add_signal(SignalType::Ctrlc)
.add_signal(SignalType::Other(
#[cfg(unix)]
{
Signal::SIGTERM
},
#[cfg(windows)]
{
Signal::CTRL_BREAK_EVENT
},
))
.build()
.unwrap();
println!("Waiting for signal...");
channel.recv().unwrap();
println!("Got it! Exiting...");
}
2 changes: 1 addition & 1 deletion examples/readme_example.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2015 CtrlC developers
// Copyright (c) 2021 CtrlC developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
Expand Down
10 changes: 10 additions & 0 deletions src/channel.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Copyright (c) 2021 CtrlC developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

pub use crate::platform::channel::*;
13 changes: 13 additions & 0 deletions src/counter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) 2021 CtrlC developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! This module provides an abstraction over signal handler callbacks using an atomic counter to
//! tell the user the signal has been received and the handler has been run.

pub use crate::platform::counter::*;
33 changes: 32 additions & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,53 @@
// Copyright (c) 2021 CtrlC developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use crate::platform;
use std::fmt;

/// Ctrl-C error.
#[derive(Debug)]
pub enum Error {
/// Channel is empty
ChannelEmpty,
/// Signal could not be found from the system.
NoSuchSignal(crate::SignalType),
NoSuchSignal(crate::Signal),
/// Ctrl-C signal handler already registered.
MultipleHandlers,
/// Too many signals registered for a channel.
TooManySignals,
/// Unexpected system error.
System(std::io::Error),
}
impl PartialEq for Error {
fn eq(&self, e: &Error) -> bool {
match (self, e) {
(&Error::ChannelEmpty, &Error::ChannelEmpty) => true,
(&Error::NoSuchSignal(ref lhs), &Error::NoSuchSignal(ref rhs)) => lhs == rhs,
(&Error::MultipleHandlers, &Error::MultipleHandlers) => true,
(&Error::System(ref lhs), &Error::System(ref rhs)) => {
if lhs.kind() != rhs.kind() {
return false;
}
lhs.raw_os_error() == rhs.raw_os_error()
}
_ => false,
}
}
}

impl Error {
fn describe(&self) -> &str {
match *self {
Error::ChannelEmpty => "Channel is empty",
Error::NoSuchSignal(_) => "Signal could not be found from the system",
Error::MultipleHandlers => "Ctrl-C signal handler already registered",
Error::TooManySignals => "Too many signals registered for a channel",
Error::System(_) => "Unexpected system error",
}
}
Expand Down
Loading