config: publish before a process reads configuration (#35023)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user