Skip to content

Fix SubprocVecEnv ConnectionResetError with forkserver/spawn#668

Merged
eleurent merged 1 commit into
Farama-Foundation:masterfrom
Lidang-Jiang:fix/subproc-connection-reset
Apr 7, 2026
Merged

Fix SubprocVecEnv ConnectionResetError with forkserver/spawn#668
eleurent merged 1 commit into
Farama-Foundation:masterfrom
Lidang-Jiang:fix/subproc-connection-reset

Conversation

@Lidang-Jiang

Copy link
Copy Markdown
Contributor

Summary

Fix ConnectionResetError: [Errno 104] Connection reset by peer when creating highway-env environments via SubprocVecEnv (stable-baselines3) or any multiprocessing wrapper that uses the forkserver/spawn start method.

Root cause: SubprocVecEnv defaults to forkserver when available. Child processes started via forkserver or spawn do not inherit the parent's import highway_env, so gymnasium.register() calls in highway_env/__init__.py never execute in the subprocess. When gym.make("highway-fast-v0") runs in the child, the environment is not in the registry → NameNotFound → subprocess crash → ConnectionResetError in the parent.

Fix:

  • Make _register_highway_envs() idempotent (skip if already registered) so that re-importing highway_env via gymnasium's module:env_name resolution does not raise duplicate-registration errors
  • Add a gymnasium entry-point in pyproject.toml for potential future auto-discovery
  • Users should use gym.make("highway_env:highway-fast-v0") (with module prefix) when using SubprocVecEnv — gymnasium's _find_spec imports the module in the subprocess before looking up the environment

Fixes #648

Before
=== Using bare env ID with SubprocVecEnv ===

Process ForkServerProcess-1:
Traceback (most recent call last):
  File "multiprocessing/process.py", line 314, in _bootstrap
    self.run()
  File "multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "stable_baselines3/common/vec_env/subproc_vec_env.py", line 29, in _worker
    env = _patch_env(env_fn_wrapper.var())
  File "stable_baselines3/common/env_util.py", line 95, in _init
    env = gym.make(env_id, **kwargs)
  File "gymnasium/envs/registration.py", line 681, in make
    env_spec = _find_spec(id)
  File "gymnasium/envs/registration.py", line 526, in _find_spec
    _check_version_exists(ns, name, version)
  File "gymnasium/envs/registration.py", line 392, in _check_version_exists
    _check_name_exists(ns, name)
  File "gymnasium/envs/registration.py", line 369, in _check_name_exists
    raise error.NameNotFound(
gymnasium.error.NameNotFound: Environment `highway-fast` doesn't exist.
Process ForkServerProcess-2:
Traceback (most recent call last):
  ...
gymnasium.error.NameNotFound: Environment `highway-fast` doesn't exist.

ConnectionResetError: [Errno 104] Connection reset by peer
After
=== Using module:env_name syntax with SubprocVecEnv ===

gymnasium supports "module:env_name" syntax which imports the module
in the subprocess before looking up the environment.

SubprocVecEnv created: obs shape=(2, 5, 5)
5 steps completed successfully
Environment closed cleanly

SUCCESS: No ConnectionResetError!
============================= test session starts ==============================
platform linux -- Python 3.12.12, pytest-9.0.2, pluggy-1.6.0

tests/envs/test_multiprocessing.py::test_env_in_subprocess[forkserver-highway_env:highway-v0] PASSED
tests/envs/test_multiprocessing.py::test_env_in_subprocess[forkserver-highway_env:highway-fast-v0] PASSED
tests/envs/test_multiprocessing.py::test_env_in_subprocess[forkserver-highway_env:merge-v0] PASSED
tests/envs/test_multiprocessing.py::test_env_in_subprocess[forkserver-highway_env:roundabout-v0] PASSED
tests/envs/test_multiprocessing.py::test_env_in_subprocess[forkserver-highway_env:intersection-v0] PASSED
tests/envs/test_multiprocessing.py::test_env_in_subprocess[forkserver-highway_env:parking-v0] PASSED
tests/envs/test_multiprocessing.py::test_env_in_subprocess[spawn-highway_env:highway-v0] PASSED
tests/envs/test_multiprocessing.py::test_env_in_subprocess[spawn-highway_env:highway-fast-v0] PASSED
tests/envs/test_multiprocessing.py::test_env_in_subprocess[spawn-highway_env:merge-v0] PASSED
tests/envs/test_multiprocessing.py::test_env_in_subprocess[spawn-highway_env:roundabout-v0] PASSED
tests/envs/test_multiprocessing.py::test_env_in_subprocess[spawn-highway_env:intersection-v0] PASSED
tests/envs/test_multiprocessing.py::test_env_in_subprocess[spawn-highway_env:parking-v0] PASSED

============================= 12 passed in 15.11s ==============================

============================= full test suite ==============================
73 passed, 1 skipped, 0 failed in 37.31s

Test plan

  • 12 new multiprocessing tests: forkserver and spawn × 6 env IDs
  • Full test suite: 73 passed, 1 skipped, 0 failed (no regression)
  • Manual verification: SubprocVecEnv with stable-baselines3 works end-to-end

Make _register_highway_envs() idempotent so re-importing highway_env
in a forkserver/spawn subprocess does not raise a duplicate-registration
error. Add a gymnasium entry-point declaration for future auto-discovery.

Add 12 multiprocessing tests covering forkserver and spawn start methods
across 6 environment IDs.

Fixes Farama-Foundation#648

Signed-off-by: Lidang-Jiang <lidangjiang@gmail.com>
@eleurent eleurent merged commit 4681fb5 into Farama-Foundation:master Apr 7, 2026
5 checks passed
@eleurent

eleurent commented Apr 7, 2026

Copy link
Copy Markdown
Collaborator

Neat, thanks!

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.

ConnectionResetError: [Errno 104] Connection reset by peer

2 participants