Handles all incoming FIFO messages until it's closed, or until the child process exits. The `handle_cmd` callback is invoked first for each command. If it returns `Some(response)`, that response is sent and the shared implementation is skipped. If it returns `None`, the command falls through to the shared implementation for standard handling. Returns execution timestamps, benchmark data, and the
(
&mut self,
child: &mut std::process::Child,
mut handle_cmd: impl AsyncFnMut(&FifoCommand) -> anyhow::Result<Option<FifoCommand>>,
)
| 161 | /// |
| 162 | /// Returns execution timestamps, benchmark data, and the exit status of the child process. |
| 163 | pub async fn handle_fifo_messages( |
| 164 | &mut self, |
| 165 | child: &mut std::process::Child, |
| 166 | mut handle_cmd: impl AsyncFnMut(&FifoCommand) -> anyhow::Result<Option<FifoCommand>>, |
| 167 | ) -> anyhow::Result<( |
| 168 | ExecutionTimestamps, |
| 169 | FifoBenchmarkData, |
| 170 | std::process::ExitStatus, |
| 171 | )> { |
| 172 | let mut bench_order_by_timestamp = Vec::<(u64, String)>::new(); |
| 173 | let mut bench_pids = HashSet::<pid_t>::new(); |
| 174 | let mut markers = Vec::<MarkerType>::new(); |
| 175 | |
| 176 | let mut integration = None; |
| 177 | |
| 178 | // Must match the clock used by the benchmarked process so timestamps |
| 179 | // from both sides are comparable. |
| 180 | let get_current_time = instrument_hooks_bindings::InstrumentHooks::current_timestamp; |
| 181 | |
| 182 | let mut benchmark_started = false; |
| 183 | |
| 184 | // Outer loop: continues until health check fails |
| 185 | loop { |
| 186 | // Inner loop: process commands until timeout/error |
| 187 | loop { |
| 188 | let result: Result<_, Elapsed> = |
| 189 | tokio::time::timeout(Duration::from_secs(1), self.recv_cmd()).await; |
| 190 | let cmd = match result { |
| 191 | Ok(Ok(cmd)) => cmd, |
| 192 | Ok(Err(e)) => { |
| 193 | warn!("Failed to parse FIFO command: {e}"); |
| 194 | break; |
| 195 | } |
| 196 | Err(_) => break, // Timeout |
| 197 | }; |
| 198 | trace!("Received command: {cmd:?}"); |
| 199 | |
| 200 | // Try executor-specific handler first |
| 201 | if let Some(response) = handle_cmd(&cmd).await? { |
| 202 | self.send_cmd(response).await?; |
| 203 | continue; |
| 204 | } |
| 205 | |
| 206 | // Fall through to shared implementation for standard commands |
| 207 | match &cmd { |
| 208 | FifoCommand::CurrentBenchmark { pid, uri } => { |
| 209 | bench_order_by_timestamp.push((get_current_time(), uri.to_string())); |
| 210 | bench_pids.insert(*pid); |
| 211 | self.send_cmd(FifoCommand::Ack).await?; |
| 212 | } |
| 213 | FifoCommand::StartProfiler => { |
| 214 | if !benchmark_started { |
| 215 | benchmark_started = true; |
| 216 | markers.push(MarkerType::SampleStart(get_current_time())); |
| 217 | } else { |
| 218 | warn!("Received duplicate StartProfiler command, ignoring"); |
| 219 | } |
| 220 | self.send_cmd(FifoCommand::Ack).await?; |
no test coverage detected