MCPcopy Create free account
hub / github.com/NVIDIA/OpenShell / check_port_available

Function check_port_available

crates/openshell-core/src/forward.rs:626–674  ·  view source on GitHub ↗

Check whether a local port is available for forwarding. Uses a two-pronged check: 1. Attempts to bind ` : ` — catches same-family conflicts. 2. Runs `lsof -i : -sTCP:LISTEN` — catches cross-family conflicts (e.g. an IPv6 wildcard listener blocking a port the IPv4 bind test would miss). If the port is already in use the error message includes an actionable hint: - If an exis

(spec: &ForwardSpec)

Source from the content-addressed store, hash-verified

624/// - Otherwise, show the `lsof` output and suggest `kill` to terminate the
625/// owning process.
626pub fn check_port_available(spec: &ForwardSpec) -> Result<()> {
627 let port = spec.port;
628
629 // Fast path: try binding on the requested address. If this fails, the
630 // port is definitely taken on this address family.
631 let bind_ok = TcpListener::bind((spec.bind_addr.as_str(), port)).is_ok();
632
633 // Also ask the OS whether *any* process is listening on this port,
634 // regardless of address family. This catches situations where e.g. a
635 // server binds [::]:8080 but our IPv4 bind test succeeds.
636 let lsof_output = lsof_listeners(port);
637 let lsof_occupied = lsof_output.is_some();
638
639 if bind_ok && !lsof_occupied {
640 return Ok(());
641 }
642
643 // Port is occupied. Check if it belongs to a tracked openshell forward.
644 if let Ok(forwards) = list_forwards()
645 && let Some(fwd) = forwards
646 .iter()
647 .find(|f| f.port == port && f.validated_alive)
648 {
649 return Err(miette::miette!(
650 "Port {port} is already forwarded to sandbox '{}'.\n\
651 Stop it with: openshell forward stop {port} {}",
652 fwd.sandbox_name,
653 fwd.sandbox_name,
654 ));
655 }
656
657 // Build a helpful error with lsof details when available.
658 if let Some(output) = lsof_output {
659 return Err(miette::miette!(
660 "Port {port} is already in use by another process.\n\n\
661 {output}\n\n\
662 To free the port, find the PID above and run:\n \
663 kill <PID>\n\n\
664 Or find it yourself with:\n \
665 lsof -i :{port} -sTCP:LISTEN",
666 ));
667 }
668
669 Err(miette::miette!(
670 "Port {port} is already in use by another process.\n\
671 Find it with: lsof -i :{port} -sTCP:LISTEN\n\
672 Then terminate it with: kill <PID>",
673 ))
674}
675
676/// Run `lsof` to check for any process listening on `port`.
677///

Calls 3

lsof_listenersFunction · 0.85
list_forwardsFunction · 0.85
as_strMethod · 0.45