Skip to content

Commit 3f13b66

Browse files
committed
fix(#140): acquire rotation lock before first await to close TOCTOU race
1 parent 64728d4 commit 3f13b66

1 file changed

Lines changed: 9 additions & 7 deletions

File tree

custom_components/petlibro/devices/feeders/polar_wet_food_feeder.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -221,15 +221,17 @@ async def set_plate_position(self, value: str | int) -> None:
221221
if target not in (1, 2, 3):
222222
raise PetLibroAPIError(f"Plate must be 1, 2, or 3, got {target}")
223223

224-
if not self.plate_position:
225-
await self.refresh()
226-
curr = self.plate_position or 1
227-
228-
steps = (target - curr) % 3
229-
_LOGGER.debug("Rotate-to-plate: curr=%s target=%s steps=%s for %s", curr, target, steps, self.serial)
230-
224+
# Acquire the lock before the first await so concurrent calls can't
225+
# both pass the guard above (TOCTOU).
231226
self._rotating = True
232227
try:
228+
if not self.plate_position:
229+
await self.refresh()
230+
curr = self.plate_position or 1
231+
232+
steps = (target - curr) % 3
233+
_LOGGER.debug("Rotate-to-plate: curr=%s target=%s steps=%s for %s", curr, target, steps, self.serial)
234+
233235
ROTATE_COOLDOWN = 2.0
234236
for _ in range(steps):
235237
await self.api.set_rotate_food_bowl(self.serial)

0 commit comments

Comments
 (0)