Skip to content

Commit 1a085f3

Browse files
committed
error when shutdown happens before blackhole or generator ready
1 parent 2a7787b commit 1a085f3

1 file changed

Lines changed: 27 additions & 24 deletions

File tree

lading/src/neper/rr.rs

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ pub enum Error {
4545
/// Invalid configuration.
4646
#[error("invalid config: {0}")]
4747
Config(String),
48+
/// The shutdown signal arrived before startup finished. Both halves report
49+
/// this the same way so a stopped run fails identically on either side.
50+
#[error("Shutdown before {0}")]
51+
ShutdownDuringStartup(String),
4852
}
4953

5054
/// Parameters for [`run_client`].
@@ -171,8 +175,9 @@ async fn wait_for_shutdown_or_failure(
171175
///
172176
/// # Errors
173177
///
174-
/// Returns an error if configuration is invalid, the blackhole control port
175-
/// is never reachable, or a worker thread reports a fatal error or panics.
178+
/// Returns an error if configuration is invalid, the blackhole control port is
179+
/// never reachable, shutdown arrives before startup finishes, or a worker
180+
/// thread reports a fatal error or panics.
176181
pub(crate) async fn run_client(
177182
params: ClientParams,
178183
metric_labels: Vec<(String, String)>,
@@ -278,16 +283,16 @@ pub(crate) async fn run_client(
278283
///
279284
/// # Errors
280285
///
281-
/// Returns [`Error::Io`] if the control port never becomes reachable, if
282-
/// shutdown fires first, or if the handshake read fails.
286+
/// Returns [`Error::ShutdownDuringStartup`] if shutdown fires first, or
287+
/// [`Error::Io`] if the control port never becomes reachable or the handshake
288+
/// read fails.
283289
fn wait_for_blackhole(control_addr: SocketAddr, shutdown_flag: &AtomicBool) -> Result<u16, Error> {
284290
info!("waiting for blackhole control port at {control_addr}");
285291
let deadline = Instant::now() + CONTROL_CONNECT_TIMEOUT;
286292
loop {
287293
if shutdown_flag.load(Relaxed) {
288-
return Err(Error::Io(io::Error::new(
289-
ErrorKind::ConnectionRefused,
290-
format!("shutdown before blackhole control port {control_addr} became reachable"),
294+
return Err(Error::ShutdownDuringStartup(format!(
295+
"blackhole control port {control_addr} became reachable"
291296
)));
292297
}
293298
match net::TcpStream::connect(control_addr) {
@@ -439,8 +444,9 @@ fn handle_client_event(
439444
///
440445
/// # Errors
441446
///
442-
/// Returns an error if binding fails, if a worker thread reports a fatal
443-
/// error, or if a worker thread panics.
447+
/// Returns an error if binding fails, if shutdown arrives before the generator
448+
/// connects, if a worker thread reports a fatal error, or if a worker thread
449+
/// panics.
444450
pub(crate) async fn run_server(
445451
params: ServerParams,
446452
metric_labels: Vec<(String, String)>,
@@ -510,22 +516,19 @@ pub(crate) async fn run_server(
510516
flag.store(true, Relaxed);
511517
});
512518

513-
let generator_connected = match wait_for_generator(
519+
if let Err(e) = wait_for_generator(
514520
&control_listener,
515521
control_addr,
516522
params.flows,
517523
&shutdown_flag,
518524
)
519525
.await
520526
{
521-
Ok(connected) => connected,
522-
Err(e) => return Err(shutdown_and_join(e, &shutdown_flag, handles)),
523-
};
527+
return Err(shutdown_and_join(e, &shutdown_flag, handles));
528+
}
524529
drop(control_listener);
525530

526-
if generator_connected {
527-
wait_for_shutdown_or_failure(shutdown, &mut fail_rx).await;
528-
}
531+
wait_for_shutdown_or_failure(shutdown, &mut fail_rx).await;
529532
shutdown_flag.store(true, Relaxed);
530533

531534
join_workers(handles)?;
@@ -639,24 +642,24 @@ async fn prepare_data_listeners(
639642
/// Wait for the generator to connect to the control port, then hand it the
640643
/// flow count over that connection.
641644
///
642-
/// Returns `true` once the generator has connected and received the count,
643-
/// `false` if shutdown fired before any generator showed up.
644-
///
645645
/// # Errors
646646
///
647-
/// Returns an error if the handshake write fails or `accept` fails for a
647+
/// Returns [`Error::ShutdownDuringStartup`] if shutdown fires before any
648+
/// generator connects, matching how the client reports the same event. Also
649+
/// returns an error if the handshake write fails or `accept` fails for a
648650
/// reason other than `WouldBlock`.
649651
async fn wait_for_generator(
650652
control_listener: &net::TcpListener,
651653
control_addr: SocketAddr,
652654
flows: u16,
653655
shutdown_flag: &AtomicBool,
654-
) -> Result<bool, Error> {
656+
) -> Result<(), Error> {
655657
let flows_bytes = flows.to_be_bytes();
656658
loop {
657659
if shutdown_flag.load(Relaxed) {
658-
info!("shutdown before generator connected");
659-
return Ok(false);
660+
return Err(Error::ShutdownDuringStartup(
661+
"the generator connected to the control port".to_string(),
662+
));
660663
}
661664
match control_listener.accept() {
662665
Ok((mut conn, peer)) => {
@@ -666,7 +669,7 @@ async fn wait_for_generator(
666669
conn.set_write_timeout(Some(HANDSHAKE_TIMEOUT))?;
667670
conn.write_all(&flows_bytes)?;
668671
info!("generator connected from {peer}, sent flows={flows}, data threads running");
669-
return Ok(true);
672+
return Ok(());
670673
}
671674
Err(ref e) if e.kind() == ErrorKind::WouldBlock => {
672675
tokio::time::sleep(Duration::from_millis(100)).await;

0 commit comments

Comments
 (0)