https://github.com/monoid/interruptable
Interruptable Read and Write wrappers in Rust
https://github.com/monoid/interruptable
Last synced: 10 months ago
JSON representation
Interruptable Read and Write wrappers in Rust
- Host: GitHub
- URL: https://github.com/monoid/interruptable
- Owner: monoid
- License: mit
- Created: 2022-01-19T05:44:47.000Z (over 4 years ago)
- Default Branch: main
- Last Pushed: 2022-01-19T11:07:28.000Z (over 4 years ago)
- Last Synced: 2025-08-11T06:26:36.961Z (10 months ago)
- Language: Rust
- Size: 5.86 KB
- Stars: 2
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# interruptable
Interruptable `Read` and `Write` wrappers in Rust
## Usage
This package is to be used for interrupting IO in conjunction with
signal handling crates like `ctrlc`. These crates do handle received
signals and allow to set some flag, but if application code is performing
IO, it will not able to check the flag until it completes. The Unix-like
OSes do interrupt IO operations on signals, returning `EINT` errno (aka
`ErrorKind::Interrupted`), but `std::io` utility methods sliently restart
such operations.
The `Interruptable` wrapper for `std::io::Read` and `std::io::Write` checks
the flag (`std::sync::atomic::AtomicBool`) on each `read` or `write` operation,
and when it sees that flag is set, it returns `std::io::Error` (standard error
for the IO operations) with `std::io::ErrorKind::Other` and nested error of
`ErrorKind::Interrupted`, thus hiding it from the retrying logic.
Life without `interruptabe`:
``` rust,ignore
use std::io;
use std::sync::atomic;
use ctrlc;
let interrupt_flag = atomic::Arc::new(atomic::AtomicBool::new(false));
let interrput_flag2 = interrupt_flag.clone();
ctrlc::set_handler(move || {
interrput_flag2.store(true, std::sync::atomic::Ordering::SeqCst);
}).unwrap();
let file = io::BufReader::new(
std::fs::File::open("/path/to/slow/media/data.data")?
);
let my_precious_resource = MyResource::new();
for line in file.lines() {
// It will be checked only after whole line is read, that may
// take arbitrary long time.
if interrput_flag2.load(std::sync::atomic::Ordering::SeqCst) {
std::mem::drop(my_precious_resource);
std::process::exit(42);
}
let line = line?;
...
}
```
Life with `interruptabe`:
``` rust,ignore
use std::io;
use std::sync::atomic;
use ctrlc;
let interrupt_flag = atomic::Arc::new(atomic::AtomicBool::new(false));
let interrput_flag2 = interrupt_flag.clone();
ctrlc::set_handler(move || {
interrput_flag2.store(true, std::sync::atomic::Ordering::SeqCst);
}).unwrap();
let file = io::BufReader::new(
// Work both for Read and Write.
interruptable::Interruptable::new(
std::fs::File::open("/path/to/slow/media/data.data")?,
interrupt_flag,
)
);
let my_precious_resource = MyResource::new();
for line in file.lines() {
// When the signal will arrive and flag is set, line will be Err(...)
// immediately, thus you will be able to handle it and gracefully
// shutdown your application: my_precious_resource is destroyed
// in the standard way, by Drop::drop.
let line = line?;
...
}
```