config: publish before a process reads configuration (#35023)

This commit is contained in:
Cheng Wan
2026-08-17 16:16:20 -07:00
committed by GitHub
parent 2b278b4ac4
commit 3d7ec00179
9 changed files with 504 additions and 16 deletions
@@ -309,13 +309,15 @@ class MMEncoder:
``base_gpu_id + rank`` — the DP launcher's per-worker placement. It is
this instance's value, not a config change, so it travels as an
argument."""
# The DP and TP encoder workers are spawned, so this constructor is
# the first publish in those processes.
publish(server_args, role="encoder")
logger.info(f"init MMEncoder {rank}/{server_args.tp_size}")
self.server_args = server_args
configure_media_url_security(
server_args.allowed_media_domains,
server_args.media_url_max_file_size_mb,
)
publish(server_args, role="encoder")
self.rank = rank
# DP rank for metric labels; overridden by run_dp_worker in DP mode.
# 0 in the single-instance (non-DP) path.
@@ -3952,6 +3954,9 @@ def _unregister_encoder_url_from_bootstrap(server_args: ServerArgs):
def launch_server(server_args: ServerArgs):
configure_logger(server_args, prefix=" encode_server")
# Publish before the launch path reads configuration; the encoder built
# below re-projects the same object.
publish(server_args, role="encoder")
if server_args.dp_size > 1:
_launch_server_dp(server_args)
return
+6
View File
@@ -99,6 +99,7 @@ from sglang.srt.observability.trace import process_tracing_init, trace_set_threa
from sglang.srt.parser.template_detection import resolve_auto_parsers
from sglang.srt.parser.template_manager import TemplateManager
from sglang.srt.plugins import load_plugins
from sglang.srt.runtime_context import publish
from sglang.srt.server_args import PortArgs, ServerArgs
from sglang.srt.utils import (
MultiprocessingSerializer,
@@ -1109,6 +1110,11 @@ class Engine(EngineScoreMixin, EngineBase):
):
resolve_auto_parsers(server_args)
# Resolution is complete here; this process goes on to host the
# tokenizer manager or the multi-tokenizer router, whose own publish
# re-projects the same object.
publish(server_args, role="tokenizer")
# Launch daemons (daemon mode only). The handles travel back to the
# Engine that spawned them; shutdown() reaps from there.
weight_cache_daemon_procs: List = []
@@ -39,6 +39,7 @@ from sglang.srt.managers.io_struct import (
)
from sglang.srt.managers.multi_tokenizer_mixin import MultiHttpWorkerDetokenizerMixin
from sglang.srt.observability.cpu_monitor import start_cpu_monitor_thread
from sglang.srt.runtime_context import publish
from sglang.srt.server_args import PortArgs, ServerArgs
from sglang.srt.utils import configure_logger, freeze_gc, kill_itself_when_parent_died
from sglang.srt.utils.hf_transformers_utils import get_tokenizer
@@ -520,6 +521,7 @@ def run_detokenizer_process(
kill_itself_when_parent_died()
setproctitle.setproctitle("sglang::detokenizer")
configure_logger(server_args)
publish(server_args, role="detokenizer")
parent_process = psutil.Process().parent()
manager = None
+2 -3
View File
@@ -5016,6 +5016,8 @@ def run_scheduler_process(
):
# Load plugins so hooks can override Scheduler and its dependencies.
load_plugins()
# Publish before anything in this process reads configuration.
publish(server_args, role="scheduler")
dp_rank = configure_scheduler_process(
server_args,
gpu_id,
@@ -5029,9 +5031,6 @@ def run_scheduler_process(
display_dp_rank=display_dp_rank,
display_moe_ep_rank=display_moe_ep_rank,
)
# Scheduler.__init__ reads the config namespaces before the model
# worker's own publish.
publish(server_args, role="scheduler")
parent_process = psutil.Process().parent()
# Set up tracing
@@ -393,6 +393,9 @@ class TokenizerManager(TokenizerControlMixin, TokenizerManagerScoreMixin):
):
# Parse args
self.server_args = server_args
# In a tokenizer-worker process this is the process's first publish;
# the in-process path re-projects the object the launcher published.
set_global_server_args_for_tokenizer(server_args)
self.startup_time: Optional[Dict[str, Any]] = None
self._config_updates: List[Tuple[str, Dict[str, Any]]] = []
self.elastic_worker_count = server_args.dp_size
@@ -407,7 +410,6 @@ class TokenizerManager(TokenizerControlMixin, TokenizerManagerScoreMixin):
self.skip_tokenizer_init = server_args.skip_tokenizer_init
self.preferred_sampling_params = server_args.preferred_sampling_params
self.crash_dump_folder = server_args.crash_dump_folder
set_global_server_args_for_tokenizer(server_args)
# Init model config
self.init_model_config()
+4 -4
View File
@@ -75,6 +75,10 @@ class SchedulerActor:
actual_gpu_id = gpu_id
logger.info(f"[TP{tp_rank}] Using passed gpu_id: {gpu_id}")
# This actor takes the place of run_scheduler_process, which is where
# a forked scheduler publishes.
publish(server_args, role="scheduler")
# Configure worker (logging, process title, etc.)
dp_rank = configure_scheduler_process(
server_args,
@@ -99,10 +103,6 @@ class SchedulerActor:
f"[TP{tp_rank}] Bound to NUMA node {numa_node} for GPU {actual_gpu_id}"
)
# This actor constructs Scheduler directly (no run_scheduler_process),
# which reads the config namespaces before the model worker's publish.
publish(server_args, role="scheduler")
# Create scheduler (loads model into GPU, initializes NCCL)
self.scheduler = Scheduler(
server_args=server_args,
+3 -3
View File
@@ -1155,6 +1155,7 @@ ROLE_NAMESPACE_SETS: dict[str, frozenset[str] | None] = {
# a wrong set fails a request rather than a test.
"tokenizer": None,
# Deployment shapes not exercised locally; audit before restricting.
"detokenizer": None,
"encoder": None,
"expert_backup": None,
"weight_cache_daemon": None,
@@ -1259,9 +1260,8 @@ def _dump_recorded_namespace_reads() -> None:
def publish(server_args, *, role: str, hf_config: Any = None) -> RuntimeContext:
"""Install process-wide config for this OS process.
Records the process ``role`` (``tokenizer`` / ``scheduler`` /
``dp_controller`` / ``encoder`` / ``expert_backup`` /
``weight_cache_daemon`` / ``test``) and
Records the process ``role`` one of the ``ROLE_NAMESPACE_SETS`` keys,
which is the one place the roles are enumerated and
projects the config bags. Draft workers skip publish (they must not clobber
the target). ``role`` is provenance, and when ``SGLANG_ROLE_NAMESPACES``
is ``enforce`` the key into ``ROLE_NAMESPACE_SETS`` for fail-closed