[Bug]: Possible race in implicit volume creation (`Utility.getOrCreateVolume()`)
- Dominant language
- Swift
- Stars
- 49.9k
- Forks
- 1.8k
- Avg merge
- 1d 20h
- Merged PRs (30d)
- 22
Description
### I have done the following
- [x] I have searched the existing issues
- [x] If possible, I've reproduced the issue using the 'main' branch of this project
### Steps to reproduce
The current implicit volume creation logic in `Utility.getOrCreateVolume()` has a race condition in the create or inspect pattern:
```
do {
volume = try await ClientVolume.create(...)
} catch let error as VolumeError {
guard case .volumeAlreadyExists = error else { throw error }
volume = try await ClientVolume.inspect(parsed.name)
}
```
### Current behavior
1. Container A calls getOrCreateVolume(“vol”) which attempts to create a volume
2. Container B calls getOrCreateVolume(“vol”) which also attempts to create a volume
3. Container A’s create succeeds
4. Container B’s create fails with volumeAlreadyExists
5. Container B calls inspect() to get the volume
6. But between steps 3 and 5, if Container A’s container fails and is cleaned up along with its volume,
Container B’s inspect() will fail with volumeNotFound
### Expected behavior
In practice the race window is small. What I added in ContainersService is a precedent that solves similar races using withContainerList() (see [ContainersService.swift#L122](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Containers/ContainersService.swift#L122)), where we do atomic check-and-create operations within a single lock context.
### Environment
```markdown
N/A
```
### Relevant log output
```shell
N/A
```
### Code of Conduct
- [x] I agree to follow this project's Code of Conduct
Contributor guide
Assessment
This issue has not been assessed yet.