/// Spawns a child process, registers its stdout and stderr into a mio::Poll
/// and stores the process::Child in the 'children' map.
Spawns a child process, registers its stdout and stderr into a mio::Poll
and stores the process::Child in the 'children' map.
Spawns a child process registers its stdout and stderr into a mio :: Poll and stores the process :: Child in the ' children ' map .
pub fn spawn_and_register_child(&mut self, mut cfg: Cfg, registry: &mut Registry) -> Pid {
        let mut cmd = cfg.command();
        let cmd_str = format!("{:?}", cmd);
        let mut child = match cmd
            .stdin(Stdio::null())
            .stdout(Stdio::piped())
            .stderr(Stdio::piped())
            .spawn()
        {
            Ok(v) => v,
            Err(e) => panic!("spawn() failed for command `{:?}` with error: {:?}", cmd, e),
        };
        let pid: Pid =
            Pid::from_raw(i32::try_from(child.id()).expect("Can't convert child.id() to Pid"));
        trace!(
            self.logger,
            "spawn_and_register_child";
            "cmd" => cmd_str,
            "pid" => format!("{:?}", pid),
        );
        // We now take the children stdout and stderr raw file descriptors.
        // We use `into_raw_fd` to transfer ownership. The drop handle on Child
        // should close them.
        let stdout = child.stdout.take().unwrap();
        let stderr = child.stderr.take().unwrap();
        // Now, we register the child's stderr, stdout and auxsrc for polling.
        // Note that we first get the children lock. This is to prevent a scenario
        // where the poll thread is blocked on polling, but as soon as we add a new
        // mio source it wakes up and goes fetch input from that source, however,
        // this thread did not add the the new child to the children map
        // and we end up with the warning "Event for unregistered process"
        {
            let mut children = self.children.write().expect("couldn't lock");
            registry
                .register(
                    &mut SourceFd(&stdout.as_raw_fd()),
                    make_token(pid, InputSource::Stdout),
                    Interest::READABLE,
                )
                .expect("Failed to register child's stdout");
            registry
                .register(
                    &mut SourceFd(&stderr.as_raw_fd()),
                    make_token(pid, InputSource::Stderr),
                    Interest::READABLE,
                )
                .expect("Failed to register child's stderr");
            trace!(self.logger, "Registered stdout and stderr in mio");
            // Now we map over all the auxiliary information sources and attempt to open
            // them for reading. Those that suceed will get registered with
            // their respective Auxsrc(pos) tag in the mio registry.
            let vec_auxsrc = cfg
                .auxiliary_info_source()
                .into_iter()
                .enumerate()
                .filter_map(|(pos, path)| {
                    let mut open_opts = OpenOptions::new();
                    open_opts.read(true);
                    if cfg!(unix) {
                        open_opts.custom_flags(libc::O_NONBLOCK);
                    }
                    match open_opts.open(&path) {
                        Err(e) => {
                            warn!(
                                self.logger,
                                "Could not open auxsrc at {:?} for reading: {:?}", path, e
                            );
                            None
                        }
                        Ok(file) => {
                            registry
                                .register(
                                    &mut SourceFd(&file.as_raw_fd()),
                                    make_token(pid, InputSource::Auxsrc(pos)),
                                    Interest::READABLE,
                                )
                                .expect("Failed to register child's auxsrc");
                            trace!(self.logger, "Registered auxsrc in mio");
                            Some(file)
                        }
                    }
                });
            // Adds the child to the managed pool; this must happen AFTER registering
            // the stdout and stderr, otherwise we get the "borrow after move" error.
            children.insert(
                pid,
                Child {
                    pid,
                    stdout: BufferedReader::new(stdout),
                    stderr: BufferedReader::new(stderr),
                    auxsrc: vec_auxsrc
                        .map(BufferedReader::<File, LineBuffer>::new)
                        .collect(),
                    child,
                },
            );
            drop(children);
            trace!(self.logger, "Registered the new child in children map");
        }
        // Stores the config with the associated pid it launched.
        self.configs.insert(pid, cfg);
        debug!(self.logger, "Spawned child process (pid: {})", pid);
        pid
    }
pub fn spawn_and_register_child ( & mut self , mut cfg : Cfg , registry : & mut Registry ) -> Pid { let mut cmd = cfg . command ( ) ; let cmd_str = format ! ( " " cmd ) ; let mut child = match cmd . stdin ( Stdio :: null ( ) ) . stdout ( Stdio :: piped ( ) ) . stderr ( Stdio :: piped ( ) ) . spawn ( ) { Ok ( v ) => v , Err ( e ) => panic ! ( " " cmd e ) , } ; let pid : Pid = Pid :: from_raw ( i32 :: try_from ( child . id ( ) ) . expect ( " " ) ) ; trace ! ( self logger " " " " cmd_str " " format ( " " pid ) ) ; // We now take the children stdout and stderr raw file descriptors. // We use `into_raw_fd` to transfer ownership. The drop handle on Child // should close them. let stdout = child . stdout . take ( ) . unwrap ( ) ; let stderr = child . stderr . take ( ) . unwrap ( ) ; // Now, we register the child's stderr, stdout and auxsrc for polling. // Note that we first get the children lock. This is to prevent a scenario // where the poll thread is blocked on polling, but as soon as we add a new // mio source it wakes up and goes fetch input from that source, however, // this thread did not add the the new child to the children map // and we end up with the warning "Event for unregistered process" { let mut children = self . children . write ( ) . expect ( " " ) ; registry . register ( & mut SourceFd ( & stdout . as_raw_fd ( ) ) , make_token ( pid , InputSource :: Stdout ) , Interest :: READABLE , ) . expect ( " " ) ; registry . register ( & mut SourceFd ( & stderr . as_raw_fd ( ) ) , make_token ( pid , InputSource :: Stderr ) , Interest :: READABLE , ) . expect ( " " ) ; trace ! ( self logger " " ) ; // Now we map over all the auxiliary information sources and attempt to open // them for reading. Those that suceed will get registered with // their respective Auxsrc(pos) tag in the mio registry. let vec_auxsrc = cfg . auxiliary_info_source ( ) . into_iter ( ) . enumerate ( ) . filter_map ( | ( pos , path ) | { let mut open_opts = OpenOptions :: new ( ) ; open_opts . read ( true ) ; if cfg ! ( unix ) { open_opts . custom_flags ( libc :: O_NONBLOCK ) ; } match open_opts . open ( & path ) { Err ( e ) => { warn ! ( self logger " " path e ) ; None } Ok ( file ) => { registry . register ( & mut SourceFd ( & file . as_raw_fd ( ) ) , make_token ( pid , InputSource :: Auxsrc ( pos ) ) , Interest :: READABLE , ) . expect ( " " ) ; trace ! ( self logger " " ) ; Some ( file ) } } } ) ; // Adds the child to the managed pool; this must happen AFTER registering // the stdout and stderr, otherwise we get the "borrow after move" error. children . insert ( pid , Child { pid , stdout : BufferedReader :: new ( stdout ) , stderr : BufferedReader :: new ( stderr ) , auxsrc : vec_auxsrc . map ( BufferedReader :: < File , LineBuffer > :: new ) . collect ( ) , child , } , ) ; drop ( children ) ; trace ! ( self logger " " ) ; } // Stores the config with the associated pid it launched. self . configs . insert ( pid , cfg ) ; debug ! ( self logger " " pid ) ; pid }
Spawns a child process, registers its stdout and stderr into a mio::Poll
and stores the process::Child in the 'children' map.
Spawns a child process registers its stdout and stderr into a mio :: Poll and stores the process :: Child in the ' children ' map .
&mut self
cfg
Cfg
registry
&mut Registry