(udid: &str)
| 731 | } |
| 732 | |
| 733 | async fn discover_webinspector_socket(udid: &str) -> Result<Option<WebKitSocket>, AppError> { |
| 734 | let output = timeout( |
| 735 | WEBKIT_SOCKET_DISCOVERY_TIMEOUT, |
| 736 | Command::new("/usr/sbin/lsof") |
| 737 | .args(["-nP", "-U", "-F", "pn"]) |
| 738 | .output(), |
| 739 | ) |
| 740 | .await |
| 741 | .map_err(|_| AppError::native("Timed out listing webinspectord sockets."))? |
| 742 | .map_err(|error| AppError::native(format!("Unable to run lsof: {error}")))?; |
| 743 | |
| 744 | if !output.status.success() { |
| 745 | debug!( |
| 746 | "Unable to list webinspectord sockets for {udid}: {}", |
| 747 | String::from_utf8_lossy(&output.stderr).trim() |
| 748 | ); |
| 749 | return discover_launchd_webinspector_socket(udid).await; |
| 750 | } |
| 751 | |
| 752 | let stdout = String::from_utf8_lossy(&output.stdout); |
| 753 | let mut processes: HashMap<String, LsofProcess> = HashMap::new(); |
| 754 | let device_marker = format!("/Devices/{udid}/"); |
| 755 | let launchd_marker = format!("CoreSimulator.SimDevice.{udid}/"); |
| 756 | let mut current_pid: Option<String> = None; |
| 757 | for line in stdout.lines() { |
| 758 | if let Some(pid) = line.strip_prefix('p') { |
| 759 | current_pid = Some(pid.to_owned()); |
| 760 | processes.entry(pid.to_owned()).or_default(); |
| 761 | continue; |
| 762 | } |
| 763 | let Some(name) = line.strip_prefix('n') else { |
| 764 | continue; |
| 765 | }; |
| 766 | let Some(pid) = current_pid.as_ref() else { |
| 767 | continue; |
| 768 | }; |
| 769 | let process = processes.entry(pid.clone()).or_default(); |
| 770 | if name.contains(&device_marker) || name.contains(&launchd_marker) { |
| 771 | process.belongs_to_udid = true; |
| 772 | } |
| 773 | if name.ends_with(WEBINSPECTORD_SOCKET_NAME) { |
| 774 | process.sockets.push(name.to_owned()); |
| 775 | } |
| 776 | } |
| 777 | |
| 778 | let mut candidates = processes |
| 779 | .into_values() |
| 780 | .filter(|process| process.belongs_to_udid) |
| 781 | .flat_map(|process| process.sockets) |
| 782 | .filter(|path| Path::new(path).exists()) |
| 783 | .collect::<Vec<_>>(); |
| 784 | candidates.sort(); |
| 785 | candidates.dedup(); |
| 786 | |
| 787 | if let Some(path) = candidates.into_iter().next() { |
| 788 | return Ok(Some(WebKitSocket { path })); |
| 789 | } |
| 790 |
no test coverage detected