Skip to content

Commit e789441

Browse files
authored
Only insert executable into cache once it starts (#528)
The observability hooks are created in `Executable::new` so we shouldn't miss any messages. This ensures that we only add started executables to the cache, which means that we don't end up with orphan executables in the cache.
1 parent 9b33eb4 commit e789441

File tree

1 file changed

+20
-14
lines changed

1 file changed

+20
-14
lines changed

auraed/src/cells/cell_service/executables/executables.rs

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -42,27 +42,30 @@ impl Executables {
4242
}
4343

4444
let executable_name = executable_spec.name.clone();
45-
// `or_insert` will always insert as we've already assured ourselves that the key does not exist.
46-
let executable = self
47-
.cache
48-
.entry(executable_name.clone())
49-
.or_insert_with(|| Executable::new(executable_spec));
50-
51-
// TODO: if we fail to start, the exe remains in the cache and start cannot be called again
52-
// solving ^^ was a borrow checker fight and I (future-highway) lost this round.
45+
let mut executable = Executable::new(executable_spec);
46+
47+
// start the exe before we add it to the cache, as otherwise a failure leads to the
48+
// executable remaining in the cache and start cannot be called again.
5349
executable.start().map_err(|e| {
5450
ExecutablesError::FailedToStartExecutable {
55-
executable_name,
51+
executable_name: executable_name.clone(),
5652
source: e,
5753
}
5854
})?;
5955

60-
Ok(executable)
56+
// `or_insert` will always insert as we've already assured ourselves that the key does not
57+
// exist.
58+
let inserted_executable =
59+
self.cache.entry(executable_name).or_insert_with(|| executable);
60+
61+
Ok(inserted_executable)
6162
}
6263

6364
pub fn get(&self, executable_name: &ExecutableName) -> Result<&Executable> {
6465
let Some(executable) = self.cache.get(executable_name) else {
65-
return Err(ExecutablesError::ExecutableNotFound { executable_name: executable_name.clone() });
66+
return Err(ExecutablesError::ExecutableNotFound {
67+
executable_name: executable_name.clone(),
68+
});
6669
};
6770
Ok(executable)
6871
}
@@ -72,7 +75,9 @@ impl Executables {
7275
executable_name: &ExecutableName,
7376
) -> Result<ExitStatus> {
7477
let Some(executable) = self.cache.get_mut(executable_name) else {
75-
return Err(ExecutablesError::ExecutableNotFound { executable_name: executable_name.clone() });
78+
return Err(ExecutablesError::ExecutableNotFound {
79+
executable_name: executable_name.clone(),
80+
});
7681
};
7782

7883
let exit_status = executable.kill().await.map_err(|e| {
@@ -84,7 +89,8 @@ impl Executables {
8489

8590
let Some(exit_status) = exit_status else {
8691
// Exes that never started return None
87-
let executable = self.cache.remove(executable_name).expect("exe in cache");
92+
let executable =
93+
self.cache.remove(executable_name).expect("exe in cache");
8894
return Err(ExecutablesError::ExecutableNotFound {
8995
executable_name: executable.name,
9096
});
@@ -112,4 +118,4 @@ impl Executables {
112118
let _ = self.cache.remove(&name);
113119
}
114120
}
115-
}
121+
}

0 commit comments

Comments
 (0)