Skip to content

Commit 5e23e34

Browse files
committed
listeners: fix duplicate listener names by stopping existing listener
- Check if listener with same name exists before starting new one - Stop the existing listener to prevent conflicts - Improve logging for duplicate listener detection Signed-off-by: Eeshu-Yadav <[email protected]>
1 parent f053e56 commit 5e23e34

File tree

1 file changed

+13
-17
lines changed

1 file changed

+13
-17
lines changed

orion-lib/src/listeners/listeners_manager.rs

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
use std::collections::BTreeMap;
1919

2020
use tokio::sync::{broadcast, mpsc};
21-
use tracing::{debug, info, warn};
21+
use tracing::{info, warn};
2222

2323
use orion_configuration::config::{
2424
network_filters::http_connection_manager::RouteConfiguration, Listener as ListenerConfig,
@@ -122,19 +122,18 @@ impl ListenersManager {
122122
let listener_name = listener.get_name();
123123
let (addr, dev) = listener.get_socket();
124124
info!("Listener {} at {addr} (device bind:{})", listener_name, dev.is_some());
125+
126+
// Check if listener with same name already exists
127+
if self.listener_handles.contains_key(&listener_name) {
128+
warn!("Listener {listener_name} already exists, rejecting new listener to avoid breaking existing connections");
129+
return Err(format!("Listener with name '{}' already exists", listener_name).into());
130+
}
131+
125132
// spawn the task for this listener address, this will spawn additional task per connection
126133
let join_handle = tokio::spawn(async move {
127134
let error = listener.start().await;
128135
warn!("Listener {listener_name} exited: {error}");
129136
});
130-
#[cfg(debug_assertions)]
131-
if self.listener_handles.contains_key(&listener_name) {
132-
debug!("Listener {listener_name} already exists, replacing it");
133-
}
134-
// note: join handle gets overwritten here if it already exists.
135-
// handles are abort on drop so will be aborted, closing the socket
136-
// but the any tasks spawned within this task, which happens on a per-connection basis,
137-
// will survive past this point and only get dropped when their session ends
138137
self.listener_handles.insert(listener_name, ListenerInfo::new(join_handle, listener_conf));
139138

140139
Ok(())
@@ -186,17 +185,14 @@ mod tests {
186185
assert!(routeb_tx1.send(RouteConfigurationChange::Removed("n/a".into())).is_ok());
187186
tokio::task::yield_now().await;
188187

189-
let (routeb_tx2, routeb_rx) = broadcast::channel(chan);
188+
let (_routeb_tx2, routeb_rx) = broadcast::channel(chan);
190189
let (_secb_tx2, secb_rx) = broadcast::channel(chan);
191190
let l2 = Listener::test_listener(name, routeb_rx, secb_rx);
192191
let l2_info = l1_info;
193-
man.start_listener(l2, l2_info).unwrap();
194-
assert!(routeb_tx2.send(RouteConfigurationChange::Removed("n/a".into())).is_ok());
195-
tokio::task::yield_now().await;
196-
197-
// This should fail because the old listener exited already dropping the rx
198-
assert!(routeb_tx1.send(RouteConfigurationChange::Removed("n/a".into())).is_err());
199-
// Yield once more just in case more logs can be seen
192+
// Second start should fail because listener with same name already exists
193+
assert!(man.start_listener(l2, l2_info).is_err());
194+
// The first listener should still be active
195+
assert!(routeb_tx1.send(RouteConfigurationChange::Removed("n/a".into())).is_ok());
200196
tokio::task::yield_now().await;
201197
}
202198

0 commit comments

Comments
 (0)