Skip to content

fix: MetaDrive simulator on macOS (spawn context, lazy imports)#38152

Closed
AmitabhainArunachala wants to merge 2 commits into
commaai:masterfrom
AmitabhainArunachala:fix/metadrive-macos-spawn
Closed

fix: MetaDrive simulator on macOS (spawn context, lazy imports)#38152
AmitabhainArunachala wants to merge 2 commits into
commaai:masterfrom
AmitabhainArunachala:fix/metadrive-macos-spawn

Conversation

@AmitabhainArunachala

Copy link
Copy Markdown

Summary

Fixes the MetaDrive simulator so it runs correctly on macOS, allowing tools/sim/tests/test_metadrive_bridge.py to pass.

Closes #33207

Root causes

On macOS, Python's multiprocessing defaults to the fork start method. Panda3D and MetaDrive initialize Cocoa and OpenGL on import, which is unsafe in a forked child process after the parent has set up GUI state.

Additionally:

  • dist_threshold = 1 is too aggressive on macOS where simulator ticks produce smaller position deltas, causing false vehicle_not_moving failures
  • Synthetic eof = frame_id * 0.05 * 1e9 fails camera freshness checks on macOS
  • forkpty in unblock_stdout() is incompatible with macOS simulation

Changes

tools/sim/bridge/metadrive/metadrive_world.py

  • Use multiprocessing.get_context("spawn") on Darwin for clean subprocess state
  • Use mp_ctx.{Array, Pipe, Event, Process} so all IPC primitives share the spawn context
  • Reduce dist_threshold to 0.05 on macOS to avoid false vehicle_not_moving failures

tools/sim/bridge/metadrive/metadrive_process.py

  • Remove top-level imports of panda3d and metadrive — these initialized Cocoa in the parent process
  • Lazy-load inside apply_metadrive_patches() and metadrive_process(), which run in the child subprocess
  • Move C3_POSITION/C3_HPR constants inside the lazy initialization

tools/sim/lib/camerad.py

  • Use time.monotonic() for the eof timestamp instead of frame_id * 0.05 * 1e9

system/manager/manager.py

  • Skip unblock_stdout() (which calls forkpty) on Darwin when SIMULATION=1

Testing

python -m pytest -vv -s -n0 tools/sim/tests/test_metadrive_bridge.py

…onic timestamps)

Fixes commaai#33207

Root causes:
- multiprocessing defaults to fork on macOS, but Panda3D/Cocoa cannot
  safely initialize in a forked child after parent GUI state setup
- Top-level imports of panda3d/metadrive modules initialize Cocoa in
  the parent process before the child is spawned
- dist_threshold of 1 is too aggressive for macOS where simulator ticks
  produce smaller position deltas
- Synthetic eof timestamp (frame_id * 0.05) fails camera freshness
  checks on macOS where frame timing differs
- forkpty in unblock_stdout() is incompatible with macOS simulation

Changes:
- metadrive_world.py: use spawn context on Darwin, reduce dist_threshold
- metadrive_process.py: lazy-load panda3d/metadrive inside subprocess
- camerad.py: use time.monotonic() for eof timestamp
- manager.py: skip forkpty on macOS when SIMULATION=1
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Process replay diff report

Replays driving segments through this PR and compares the behavior to master.
Please review any changes carefully to ensure they are expected.

✅ 0 changed, 66 passed, 0 errors

@AmitabhainArunachala

Copy link
Copy Markdown
Author

Closing this in favor of #38156 which takes a cleaner approach with fewer changes and passes all CI checks. The spawn-context and lazy-import changes in this PR were addressing symptoms rather than root causes — process.py preimport guard is the correct fix since macOS uses spawn by default since Python 3.8.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Get MetaDrive simulator working on macOS

1 participant