Skip to content

fix(cli): default uni-cumps daemon path exceeds Linux MPS socket limit #2091

Closed

Description

@TATP-233

Problem

On a Linux single-GPU host, the zero-argument workflow fails after the first invocation or a crashed start:

uv run uni-cumps start
# error: Refusing to attach to an existing control path
# /home/<user>/.cache/unilab/cuda-mps/gpu-<uuid-prefix>/pipe/control

uv run uni-cumps env
# error: Cannot select a default daemon because no live UniLab-recorded daemon exists

uv run uni-cumps doctor
# valid=False; could not reach the control daemon

uv run uni-cumps stop
# error: Cannot select a default daemon because no live UniLab-recorded daemon exists

There are two distinct defects.

1. Default daemon record is not written

start_daemon() launches nvidia-cuda-mps-control -d, but the NVIDIA daemon can exit nonzero without stderr while leaving partial pipe artifacts. UniLab currently surfaces only:

nvidia-cuda-mps-control failed with exit code 1.

No daemon record is written, so env, default stop, and managed-pipe discovery cannot work.

2. Default path is too long for the control socket

The default runtime path is:

~/.cache/unilab/cuda-mps/gpu-<uuid-prefix>/pipe/control

Measured behavior on CUDA MPS 13.0 / driver 580:

  • paths of 95 bytes succeed;
  • paths of 96 bytes and above fail with exit code 1 and no stderr;
  • failed starts leave control_lock and a pipe/log FIFO behind, causing the next attempt to report “Refusing to attach to an existing control path.”

Linux sockaddr_un nominally allows 107 bytes, but the NVIDIA control implementation has this tighter effective boundary. The current full username plus UUID-prefixed cache path commonly exceeds it.

Deliverable

Make the zero-argument path work reliably on a normal Linux home-directory layout and recover cleanly from partial NVIDIA artifacts.

Required behavior:

  1. Use a short, user-owned default runtime root instead of the long home-cache path, for example:

    /tmp/uni-cumps/<name>/pipe
    /tmp/uni-cumps/<name>/log
    

    Create /tmp/uni-cumps, each daemon directory, and both pipe/log directories with mode 0700.

  2. Use the complete canonical GPU UUID in the default daemon name, not a short prefix, to avoid daemon-name collisions:

    gpu-<full-uuid>
    
  3. Before launch, reject any explicit --pipe-dir whose resulting .../control path exceeds the conservative 95-byte boundary, with an actionable message recommending a short path such as /tmp/<short-name>/pipe.

  4. Clean or quarantine only the known inert artifacts left by a failed control launch (control_lock, pipe/log FIFO) when no live control socket and no daemon record exist. Never remove an existing control/control_privileged socket or arbitrary user files.

  5. When nvidia-cuda-mps-control exits nonzero, include the control log path and relevant tail in the diagnostic instead of an empty error suffix.

  6. Keep daemon records under the existing user-scoped registry; records must point to the new runtime directories.

Scope and delivery boundaries

In this work item:

  • default-path selection and permissions;
  • full-UUID default name;
  • explicit-path length validation;
  • safe partial-artifact recovery;
  • actionable control failure diagnostics;
  • focused tests and production-guide updates.

Separate outcomes:

  • automatic lease/selection from the trainer;
  • multi-GPU or task-per-GPU execution;
  • MIG, SM percentage, memory limits, affinity, or multi-node daemon management.

Affected owner layers and contracts

  • CLI owner: src/unilab/training/cuda_mps_cli.py
  • Tests: tests/training/test_cuda_mps_cli.py
  • ADR: docs/sphinx/source/adr/ADR-0014-cuda-mps-cli-lifecycle-owner.md
  • Docs: English and Chinese tensor-runtime production guides

Definition of done

  • On a clean single-GPU host, these commands complete successfully:

    uv run uni-cumps start
    eval "$(uv run uni-cumps env)"
    uv run uni-cumps doctor   # exit 0
    uv run uni-cumps stop
  • Default directories are mode 0700 and owned by the current user.

  • Repeated start after a failed NVIDIA launch no longer strands the workflow on control_lock/pipe/log.

  • Existing live control sockets are never removed or attached to implicitly.

  • A 96-byte explicit control path fails before daemon launch with an actionable message.

  • Fake-host tests cover full-UUID naming, default-path modes, socket-length rejection, inert-artifact recovery, and preservation of live sockets.

  • make check and make test pass; make test-all passes on the final PR head.

Dependencies and blockers

None. PR #2085 has already merged, so this is a follow-up fix on main.

Proposed owner

UniLab training runtime maintainers

Validation plan

  1. Unit tests with fake process/filesystem state.
  2. Linux/NVIDIA integration smoke covering the exact four-command zero-argument lifecycle.
  3. Induce a control-daemon nonzero exit and verify diagnostics plus safe recovery.
  4. Final repository gate.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions