feat(entrypoints): job scheduler improvements for the HTTP eval server#1383
Merged
Conversation
… eval server
Redirect the eval subprocess's stdout/stderr to a per-job log file instead
of draining it through an asyncio StreamReader in the server's event loop.
The previous readline()-based loop crashed with
ValueError("Separator is not found, and chunk exceed the limit") whenever
a single chunk (long tqdm line, traceback, etc.) exceeded asyncio's 64 KiB
separator limit. Writing directly to a file removes that failure class and
lets failures surface the log tail in the raised error.
Also fixes a latent bug where num_gpus=1 went through
`accelerate launch --num_processes 1`, which uses accelerate's
simple_launcher and never sets WORLD_SIZE/RANK/MASTER_ADDR, causing
lmms_eval's unconditional Accelerator() construction to crash on env://
rendezvous. Single-GPU jobs now invoke `python -m lmms_eval` directly;
multi-GPU jobs go through `accelerate.commands.launch --multi_gpu`.
Command construction, subprocess execution, and log tailing are split into
testable static methods (_build_eval_cmd, _run_subprocess_with_log,
_tail_log), plus a chunked-read _iter_stream_lines helper for streaming
consumers that need line-shaped output without readline()'s separator cap.
_run_subprocess_with_log also scrubs Slurm/torch.distributed env vars that
can otherwise leak into the eval child when the HTTP server itself runs
under a distributed launcher.
Ports the corresponding test/entrypoints/test_job_scheduler_subprocess.py
coverage (trimmed of internal-only CLI passthrough assertions that don't
apply here).
…used stream helper
kcz358
approved these changes
Jul 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
accelerate launch --num_processes 1, which uses accelerate'ssimple_launcherand never setsWORLD_SIZE/RANK/MASTER_ADDR—lmms_eval's unconditionalAccelerator()construction then crashes withValueError: ... WORLD_SIZE expected, but not set. Single-GPU jobs now invokepython -m lmms_evaldirectly; multi-GPU jobs go throughaccelerate.commands.launch --multi_gpu.asyncio.StreamReader.readline()inside the server's event loop, which raisesValueError("Separator is not found, and chunk exceed the limit")as soon as a single chunk (long tqdm line, traceback, JSON dump) exceeds asyncio's 64 KiB separator limit. Output is now redirected straight to a per-job log file at the OS level, and failures raise aRuntimeErrorwith the log tail attached for fast debugging.torch.distributedenv vars (SLURM_PROCID,RANK,WORLD_SIZE,MASTER_ADDR, etc.) from the eval subprocess's environment, so Accelerate doesn't mistake the child for a Slurm-launched distributed task when the HTTP server itself happens to run under a distributed launcher._build_eval_cmd,_run_subprocess_with_log,_tail_log).Test plan
python3 -m py_compileon alllmms_eval/entrypoints/*.pylmms_eval.entrypoints.{protocol,client,job_scheduler,server_args,http_server}and the package__init__ruff checkon changed files (clean)black --check/isort --checkon changed files (clean)pytest test/entrypoints/ -v— 15/15 passed (includes a new test asserting the subprocess starts in its own session)Review pass (2026-07-06)
Self-review follow-up commit:
start_new_session=Trueand cancellation kills the group (os.killpg,ProcessLookupError-guarded, plainkill()fallback). Previously only the direct child was SIGKILLed, so on the multi-GPU path theaccelerate launchwrapper's GPU worker grandchildren were orphaned holding GPU memory._iter_stream_lineshelper (and its tests) that had no production consumer — it was pre-landed for a future SSE streaming endpoint and can return with that feature.