Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

services: autopilot-manager: avoid double starts #3057

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 25 additions & 7 deletions core/services/ardupilot_manager/autopilot_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ def __init__(self) -> None:
self.settings = Settings()
self.settings.create_app_folders()
self._current_board: Optional[FlightController] = None
self.should_be_running = False
self.mavlink_manager = MavlinkManager()

# Load settings and do the initial configuration
if self.settings.load():
Expand All @@ -55,6 +57,10 @@ async def setup(self) -> None:
# This is the logical continuation of __init__(), extracted due to its async nature
self.configuration = deepcopy(self.settings.content)

# Undesired state, only to avoid losing the reference to a running MavlinkManager
if self.mavlink_manager is not None:
await self.mavlink_manager.stop()

self.mavlink_manager = MavlinkManager()
preferred_router = self.load_preferred_router()
try:
Expand Down Expand Up @@ -99,16 +105,24 @@ def need_to_remove_file(file: pathlib.Path) -> bool:
except Exception as error:
logger.warning(f"Failed to remove logs: {error}")

def is_running(self) -> bool:
if self.current_board is None:
return False

if self.current_board.type in [PlatformType.SITL, PlatformType.Linux]:
return (
self.ardupilot_subprocess is not None
and self.ardupilot_subprocess.poll() is None
and len(self.running_ardupilot_processes()) != 0
)

# Serial or others that are not processes based
return self.should_be_running

async def auto_restart_ardupilot(self) -> None:
"""Auto-restart Ardupilot when it's not running but was supposed to."""
while True:
process_not_running = (
self.ardupilot_subprocess is not None and self.ardupilot_subprocess.poll() is not None
) or len(self.running_ardupilot_processes()) == 0
needs_restart = self.should_be_running and (
self.current_board is None
or (self.current_board.type in [PlatformType.SITL, PlatformType.Linux] and process_not_running)
)
needs_restart = self.should_be_running and not self.is_running()
if needs_restart:
logger.debug("Restarting ardupilot...")
try:
Expand Down Expand Up @@ -547,6 +561,10 @@ async def kill_ardupilot(self) -> None:
logger.info("Mavlink manager stopped.")

async def start_ardupilot(self) -> None:
# This only applies to autopilot process itself, mavlink manager will check by itself
if self.should_be_running and self.is_running():
return

await self.setup()
try:
available_boards = await self.available_boards()
Expand Down
4 changes: 4 additions & 0 deletions core/services/ardupilot_manager/mavlink_proxy/Manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ def master_endpoint(self) -> Optional[Endpoint]:
return self.tool.master_endpoint

async def start(self, master_endpoint: Endpoint) -> None:
# If the tool is already running, don't start it again to avoid port conflicts
if self.should_be_running and await self.is_running():
return

if not self.tool:
logger.info("No tool selected. Falling back to the first one found")
self.tool = self.available_interfaces()[0]()
Expand Down
Loading