Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 30 additions & 6 deletions src/proxy/src/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,12 +138,17 @@ impl<S: ProxyStream> Controller<S> {
partition_finder: Arc<impl PartitionFinder<S> + Sync + Send + 'static>,
status_reporter: StatusReporter,
cw_publisher: Option<Arc<dyn CloudWatchClient>>,
) -> Self {
let Ok(listener) = TcpListener::bind(listen_addr).await else {
panic!("Failed to bind {}", listen_addr);
};
) -> Result<Self, std::io::Error> {
let listener = TcpListener::bind(listen_addr).await.map_err(|e| {
error!(
"Failed to bind to {}: {}. \
Ensure the address is reachable and the port is not already in use.",
listen_addr, e
);
e
})?;

Self {
Ok(Self {
listener,
partition_finder,
proxy_id: ProxyIdentifier::new(),
Expand All @@ -157,7 +162,7 @@ impl<S: ProxyStream> Controller<S> {
last_reachability_emit_at: None,
reachability_emit_period: METRICS_EMISSION_PERIOD,
consecutive_connect_failures: 0,
}
})
}

pub async fn run<T: RpcClient, V: S3ClientBuilder>(
Expand Down Expand Up @@ -839,4 +844,23 @@ mod tests {
"NFS client connecting after the idle socket was dropped was not served"
);
}

#[tokio::test]
async fn test_controller_new_bind_failure_returns_err() {
// Occupy a port so the second bind attempt fails.
let occupied = TcpListener::bind("127.0.0.1:0").await.unwrap();
let addr = occupied.local_addr().unwrap();

let (_status_requester, status_reporter) = create_status_channel();
let result = Controller::new(
&addr.to_string(),
ProxyConfig::default(),
Arc::new(MockPartitionFinder),
status_reporter,
None,
)
.await;

assert!(result.is_err(), "expected Err when port is already bound");
}
}
14 changes: 12 additions & 2 deletions src/proxy/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,8 @@ async fn run(args: Args) {
status_reporter,
cw_publisher.clone(),
)
.await;
.await
.unwrap_or_else(|_| bind_failure_exit(&proxy_config.pid_file_path));
tokio::spawn(controller.run(
sigterm_cancellation_token.clone(),
AwsFileRpcClient,
Expand All @@ -232,7 +233,8 @@ async fn run(args: Args) {
status_reporter,
cw_publisher.clone(),
)
.await;
.await
.unwrap_or_else(|_| bind_failure_exit(&proxy_config.pid_file_path));
tokio::spawn(controller.run(
sigterm_cancellation_token.clone(),
AwsFileRpcClient,
Expand Down Expand Up @@ -271,6 +273,14 @@ async fn write_pid_file(pid_file_path: &Path) -> Result<(), anyhow::Error> {
Ok(())
}

fn bind_failure_exit(pid_file_path: &str) -> ! {
let p = Path::new(pid_file_path);
if p.exists() {
let _ = std::fs::remove_file(p);
}
std::process::exit(1);
}

fn run_sighup_handler(proxy_config: ProxyConfig, tls_config: Arc<Mutex<TlsConfig>>) {
tokio::spawn(async move {
let mut sighup_listener = match signal::unix::signal(signal::unix::SignalKind::hangup()) {
Expand Down
Loading