You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: replay_command.rs
    path of file: ./repos/rd/src/commands
    
    the code of the file until where you have to start completion: use crate::{
    assert_prerequisites,
    bindings::kernel::{gettimeofday, timeval},
    commands::{gdb_server, RdCommand},
    flags::Flags,
    kernel_metadata::errno_name,
    log::{LogDebug, LogInfo},
    scoped_fd::ScopedFd,
    session::{
        replay_session,
        session_inner::{RunCommand, Statistics},
        SessionSharedPtr,
    },
    trace::trace_frame::FrameTime,
    util::{check_for_leaks, find_pid
    
    fn replay(&self) -> ExitResult<()> {
        let mut target = gdb_server::Target::default();
        match self.process_created_how {
            CreatedHow::Exec => {
                target.pid = self.target_process;
                target.require_exec = true;
            }
            CreatedHow::Fork => {
                target.pid = self.target_process;
                target.require_exec = false;
            }
            CreatedHow::None => (),
        }
        target.event = self.goto_event;

        // If we're not going to autolaunch the debugger, don't go
        // through the rigamarole to set that up.  All it does is
        // complicate the process tree and confuse users.
        if self.dont_launch_debugger {
            if target.event == FrameTime::MAX {
                if let Err(e) = self.serve_replay_no_debugger(&mut stderr()) {
                    return ExitResult::Err(Box::new(e), 1);
                }
            } else {
                let session = ReplaySession::create(self.trace_dir.as_ref(), self.session_flags());
                let conn_flags = ConnectionFlags {
                    dbg_port: self.dbg_port,
                    dbg_host: self.dbg_host.clone(),
                    keep_listening: self.keep_listening,
                    debugger_params_write_pipe: None,
                    debugger_name: self.gdb_binary_file_path.clone(),
                };
                GdbServer::new(session, &target).serve_replay(&conn_flags);
            }

            check_for_leaks();
            return ExitResult::Ok(());
        }

        let debugger_params_pipe: [i32; 2];
        match pipe2(OFlag::O_CLOEXEC) {
            Ok((fd1, fd2)) => {
                debugger_params_pipe = [fd1, fd2];
            }
            Err(e) => {
                fatal!("Couldn't open debugger params pipe: {:?}", e);
            }
        }

        let fork_result = unsafe { fork().unwrap() };
        match fork_result {
            ForkResult::Child => {
                // Ensure only the parent has the read end of the pipe open. Then if
                // the parent dies, our writes to the pipe will error out.
                // DIFF NOTE: Unlike rr we require close to be successful
                close(debugger_params_pipe[0]).unwrap();

                {
                    unsafe { libc::prctl(libc::PR_SET_PDEATHSIG, libc::SIGTERM) };

                    let debugger_params_write_pipe =
                        Rc::new(RefCell::new(ScopedFd::from_raw(debugger_params_pipe[1])));
                    let session =
                        ReplaySession::create(self.trace_dir.as_ref(), self.session_flags());
                    let conn_flags = ConnectionFlags {
                        dbg_port: self.dbg_port,
                        dbg_host: self.dbg_host.clone(),
                        keep_listening: self.keep_listening,
                        debugger_params_write_pipe: Some(Rc::downgrade(
                            &debugger_params_write_pipe,
                        )),
                        debugger_name: self.gdb_binary_file_path.clone(),
                    };
                    let mut server = GdbServer::new(session, &target);
                    let sa = SigAction::new(
                        SigHandler::Handler(handle_sigint_in_child),
                        SaFlags::SA_RESTART,
                        SigSet::empty(),
                    );
                    unsafe { SERVER_PTR = &raw mut server };
                    if let Err(e) = unsafe { sigaction(Signal::SIGINT, &sa) } {
                        fatal!("Couldn't set sigaction for SIGINT: {:?}", e);
                    }

                    server.serve_replay(&conn_flags);
                }
                // Everything should have been cleaned up by now.
                check_for_leaks();
            }
            ForkResult::Parent { child } => {
                // Ensure only the child has the write end of the pipe open. Then if
                // the child dies, our reads from the pipe will return EOF.
                close(debugger_params_pipe[1]).unwrap();
                log!(LogDebug, "{} : forked debugger server {}", getpid(), child);
                let sa = SigAction::new(
                    SigHandler::Handler(handle_sigint_in_parent),
                    SaFlags::SA_RESTART,
                    SigSet::empty(),
                );
                if let Err(e) = unsafe { sigaction(Signal::SIGINT, &sa) } {
                    fatal!("Couldn't set sigaction for SIGINT: {:?}", e);
                }

                {
                    let params_pipe_read_fd = ScopedFd::from_raw(debugger_params_pipe[0]);
                    GdbServer::launch_gdb(
                        &params_pipe_read_fd,
                        &self.gdb_binary_file_path,
                        &self.gdb_options,
                    );
                }
                // Child must have died before we were able to get debugger parameters
                // and exec gdb. Exit with the exit status of the child.
                loop {
                    let mut status: i32 = 0;
                    let ret = unsafe { libc::waitpid(child.as_raw(), &mut status, 0) };
                    let err = errno();
                    log!(
                        LogDebug,
                        "{}: waitpid({}) returned {} ({}); status: {:x}",
                        getpid(),
                        child,
                        errno_name(err),
                        err,
                        status
                    );
                    if child.as_raw() != ret {
                        if libc::EINTR == err {
                            continue;
                        }
                        fatal!("{}: waitpid({}) failed", getpid(), child);
                    }
                    if WIFEXITED(status) || WIFSIGNALED(status) {
                        log!(LogInfo, "Debugger server died.  Exiting.");
                        if WIFEXITED(status) {
                            let code = WEXITSTATUS(status);
                            return ExitResult::err_from(
                                io::Error::new(
                                    io::ErrorKind::Other,
                                    "Debugger server died.  Exiting.",
                                ),
                                code.try_into().unwrap(),
                            );
                        } else {
                            return ExitResult::err_from(
                                io::Error::new(
                                    io::ErrorKind::Other,
                                    "Debugger server died.  Exiting.",
                                ),
                                1,
                            );
                        }
                    }
                }
            }
        }
        ExitResult::Ok(())
    }