pub struct InterruptEvent { /* private fields */ }interruptible only.Expand description
Event object for interrupting blocking I/O operations.
InterruptEvent provides a mechanism to cancel blocking read/write operations
from another thread. It uses a pipe-based signaling mechanism internally.
§Thread Safety
This type is thread-safe and can be shared across threads using Arc<InterruptEvent>.
§Examples
Basic usage with interruptible read:
use std::sync::Arc;
use std::thread;
use std::time::Duration;
use tun_rs::{DeviceBuilder, InterruptEvent};
let device = DeviceBuilder::new()
.ipv4("10.0.0.1", 24, None)
.build_sync()?;
let event = Arc::new(InterruptEvent::new()?);
let event_clone = event.clone();
let reader = thread::spawn(move || {
let mut buf = vec![0u8; 1500];
device.recv_intr(&mut buf, &event_clone)
});
// Give the reader time to start blocking
thread::sleep(Duration::from_millis(100));
// Trigger the interrupt
event.trigger()?;
match reader.join().unwrap() {
Ok(n) => println!("Read {} bytes", n),
Err(e) if e.kind() == std::io::ErrorKind::Interrupted => {
println!("Successfully interrupted!");
}
Err(e) => eprintln!("Error: {}", e),
}Using with a timeout:
use std::time::Duration;
use tun_rs::{DeviceBuilder, InterruptEvent};
let device = DeviceBuilder::new()
.ipv4("10.0.0.1", 24, None)
.build_sync()?;
let event = InterruptEvent::new()?;
let mut buf = vec![0u8; 1500];
// Will return an error if no data arrives within 5 seconds
match device.recv_intr_timeout(&mut buf, &event, Some(Duration::from_secs(5))) {
Ok(n) => println!("Read {} bytes", n),
Err(e) if e.kind() == std::io::ErrorKind::TimedOut => {
println!("Timed out waiting for data");
}
Err(e) if e.kind() == std::io::ErrorKind::Interrupted => {
println!("Operation was interrupted");
}
Err(e) => eprintln!("Error: {}", e),
}§Implementation Details
- Uses a Unix pipe for signaling
- Both read and write ends are set to non-blocking mode
- State is protected by a mutex to prevent race conditions
- Once triggered, the event remains triggered until reset
Implementations§
Source§impl InterruptEvent
impl InterruptEvent
Sourcepub fn new() -> Result<Self>
pub fn new() -> Result<Self>
Creates a new InterruptEvent.
This allocates a Unix pipe for signaling and sets both ends to non-blocking mode.
§Errors
Returns an error if:
- The pipe creation fails (e.g., out of file descriptors)
- Setting non-blocking mode fails
§Example
use tun_rs::InterruptEvent;
let event = InterruptEvent::new()?;Sourcepub fn trigger(&self) -> Result<()>
pub fn trigger(&self) -> Result<()>
Triggers the interrupt event with value 1.
This will cause any blocking I/O operations waiting on this event to return
with ErrorKind::Interrupted.
Calling trigger() multiple times before reset() has no additional effect -
the event remains triggered.
§Errors
Returns an error if writing to the internal pipe fails, though this is rare
in practice (pipe write errors are usually WouldBlock, which is handled).
§Example
use std::sync::Arc;
use std::thread;
use tun_rs::{DeviceBuilder, InterruptEvent};
let event = Arc::new(InterruptEvent::new()?);
let event_clone = event.clone();
thread::spawn(move || {
// ... blocking I/O with event_clone ...
});
// Interrupt the operation
event.trigger()?;Sourcepub fn trigger_value(&self, val: i32) -> Result<()>
pub fn trigger_value(&self, val: i32) -> Result<()>
Triggers the interrupt event with a specific value.
Similar to trigger(), but allows specifying a custom value
that can be retrieved with value().
§Arguments
val- The value to store (must be non-zero)
§Errors
- Returns
ErrorKind::InvalidInputifvalis 0 - Returns an error if writing to the pipe fails
§Example
use tun_rs::InterruptEvent;
let event = InterruptEvent::new()?;
// Trigger with a custom value (e.g., signal number)
event.trigger_value(15)?; // SIGTERM
// Later, check what value was used
assert_eq!(event.value(), 15);Sourcepub fn is_trigger(&self) -> bool
pub fn is_trigger(&self) -> bool
Checks if the event has been triggered.
Returns true if the event is currently in the triggered state (value is non-zero).
§Example
use tun_rs::InterruptEvent;
let event = InterruptEvent::new()?;
assert!(!event.is_trigger());
event.trigger()?;
assert!(event.is_trigger());
event.reset()?;
assert!(!event.is_trigger());Sourcepub fn value(&self) -> i32
pub fn value(&self) -> i32
Returns the current trigger value.
Returns 0 if the event is not triggered, or the value passed to
trigger_value() if triggered.
§Example
use tun_rs::InterruptEvent;
let event = InterruptEvent::new()?;
assert_eq!(event.value(), 0);
event.trigger_value(42)?;
assert_eq!(event.value(), 42);Sourcepub fn reset(&self) -> Result<()>
pub fn reset(&self) -> Result<()>
Resets the event to the non-triggered state.
This drains any pending data from the internal pipe and sets the state back to 0.
After calling reset(), the event can be triggered again.
§Errors
Returns an error if reading from the pipe fails (other than WouldBlock).
§Example
use tun_rs::InterruptEvent;
let event = InterruptEvent::new()?;
event.trigger()?;
assert!(event.is_trigger());
event.reset()?;
assert!(!event.is_trigger());
// Can trigger again after reset
event.trigger()?;
assert!(event.is_trigger());