bparli / fastping-rs

ICMP ping library in Rust inspired by go-fastping and AnyEvent::FastPing Perl module
MIT License
78 stars 12 forks source link

Getting stdout errors Error sending ping result on channel: sending on a closed channel #7

Closed glennpierce closed 5 years ago

glennpierce commented 5 years ago

I am running something very similar to your test_integration()

I have a struct called PingScanner that has a HashMap of ip addresses. My intention is run its run_pings in a thread and have it update the Hashmap of ip adresses which are reachable or not.

Trouble is I keep getting the errors

Error sending ping result on channel: sending on a closed channel repeating. Why do I get those errors ?

My very simplified code is below. (I removed setting the hashmap stuff)

Thanks

use fastping_rs::Pinger;
use fastping_rs::PingResult::{Idle, Receive};
use std::collections::{BTreeMap, HashMap};
use std::sync::{Mutex, RwLock, Arc};
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use std::time::Duration;

#[derive(Debug, Clone)]
pub struct PingScanner {
    results : Arc<RwLock<HashMap<String, Mutex<bool>>>>,
    addresses : Arc<Mutex<Vec<String>>>,
    running: Arc<AtomicBool>,
}

impl PingScanner {
    pub fn new() -> Self {

        PingScanner { results: Arc::new(RwLock::new(HashMap::new())), 
                      addresses: Arc::new(Mutex::new(Vec::new())),
                      running: Arc::new(AtomicBool::new(false)) }
    }

    pub fn contains(&self, addr: &str) -> bool {
        let map = self.results.read().expect("RwLock poisoned");
        map.contains_key(&addr.to_string())
    }

    pub fn add_ipaddr(&self, addr: &str) {

        let mut addresses = self.addresses.lock().expect("addresses locked");

        if addresses.iter().any(|x| x == addr) {
            return;
        }

        addresses.push(addr.to_string());
    }

    pub fn run_pings(&self) {

        let running = self.running.clone();

        let is_running = running.clone().load(Ordering::Relaxed);

        if is_running {
            return;
        }

        running.store(true, Ordering::Relaxed);

        info!("checking ping channels");

        match Pinger::new(None, None) {
            Ok((pinger, test_channel)) => {

                //let mut addresses = self.addresses.lock().expect("addresses locked");
                let mut addresses = vec!["10.0.128.174"];

                for addr in addresses.iter() {
                    pinger.add_ipaddr(addr);
                }

                //pinger.ping_once();
                pinger.run_pinger();

                for ip in addresses.iter() {

                    println!("matching ip {:?}", ip);

                    match test_channel.recv() {
                        Ok(result) => {
                            match result {
                                Idle{addr} => {
                                    error!("Idle Address {}.", addr);
                                },
                                Receive{addr, rtt: _} => {
                                    info!("Receive from Address {}.", addr);
                                }
                            }
                        },
                        Err(_) => assert!(false),
                    }
                }

                pinger.stop_pinger();
            }
            Err(e) => {
                println!("Test failed: {}", e);
            }
        }

        running.store(false, Ordering::Relaxed);
    }
}
bparli commented 5 years ago

Hello @glennpierce - thanks for submitting the issue! So I'm not able to replicate with your example above, but I see where might be causing this behavior. Do you mind testing against my bp-listeners-check-stop branch?

glennpierce commented 5 years ago

Yep that branch seems to fix the issue. Thanks

bparli commented 5 years ago

Thanks for verifying, this is merged and published now so going to close the issue