Fail teardown when control withdrawal fails

This commit is contained in:
ms2k 2026-07-16 17:53:54 +09:00
commit a9c9cf7ab3

View file

@ -1010,9 +1010,12 @@ impl PublishedControlFace {
}
/// Withdraws exact discovery and connection paths while retaining live accepted streams.
pub fn withdraw(&self) {
remove_if_identity_matches(&self.paths.socket, self.socket_identity);
remove_if_identity_matches(&self.paths.identity, self.identity_file_identity);
///
/// # Errors
/// Refuses changed artifacts, removal failures, or artifacts that remain after removal.
pub fn withdraw(&self) -> Result<(), ControlError> {
remove_exact_if_identity_matches(&self.paths.socket, self.socket_identity)?;
remove_exact_if_identity_matches(&self.paths.identity, self.identity_file_identity)
}
/// Accepts and serves one TLS connection. Registered connections remain live until EOF.
@ -1260,7 +1263,32 @@ impl PublishedControlFace {
impl Drop for PublishedControlFace {
fn drop(&mut self) {
self.withdraw();
remove_if_identity_matches(&self.paths.socket, self.socket_identity);
remove_if_identity_matches(&self.paths.identity, self.identity_file_identity);
}
}
fn remove_exact_if_identity_matches(
path: &Path,
expected: FileIdentity,
) -> Result<(), ControlError> {
let metadata = match std::fs::symlink_metadata(path) {
Ok(metadata) => metadata,
Err(error) if error.kind() == io::ErrorKind::NotFound => return Ok(()),
Err(error) => return Err(error.into()),
};
if FileIdentity::from_metadata(&metadata) != expected {
return Err(ControlError::InvalidPublication(
"publication artifact identity changed before withdrawal",
));
}
std::fs::remove_file(path)?;
match std::fs::symlink_metadata(path) {
Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(()),
Err(error) => Err(error.into()),
Ok(_) => Err(ControlError::InvalidPublication(
"publication artifact remained after withdrawal",
)),
}
}