[CI/Build][ROCm] Run the TileLang HIP symbol checks in their own interpreter (#53117)
Signed-off-by: Stefan Koncarevic <Stefan.Koncarevic@amd.com>
stefankoncarevic committed
Aug 21, 2026 at 23:17 UTC
f37d5868b9530497c9474f4850fdd0577f4dad79
2 files changed
+74
-45
tests/kernels/scripts/check_no_tilelang_hijack.py
new
+60
@@ -0,0 +1,60 @@
1
+#!/usr/bin/env python3
2
+# SPDX-License-Identifier: Apache-2.0
3
+# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
4
+"""Check that DeepSeek V4 and the JIT monitor leave the HIP symbols alone.
5
+
6
+TileLang ships a libhip_stub.so that takes over `hipFree` in the global symbol
7
+table once it is loaded, so neither the model import nor the JIT monitor may
8
+pull TileLang in on ROCm. Both claims are about process-global state, which is
9
+why this runs in an interpreter of its own.
10
+"""
11
+
12
+import ctypes
13
+import sys
14
+
15
+from vllm.model_executor.layers import mhc # noqa: F401
16
+from vllm.models import deepseek_v4 # noqa: F401
17
+from vllm.utils import jit_monitor
18
+
19
+
20
+class DlInfo(ctypes.Structure):
21
+ _fields_ = [
22
+ ("dli_fname", ctypes.c_char_p),
23
+ ("dli_fbase", ctypes.c_void_p),
24
+ ("dli_sname", ctypes.c_char_p),
25
+ ("dli_saddr", ctypes.c_void_p),
26
+ ]
27
+
28
+
29
+def _must_not_run() -> None:
30
+ raise AssertionError("TileLang JIT monitor must not run on ROCm")
31
+
32
+
33
+jit_monitor._active = False
34
+jit_monitor._setup_triton_autotuning_print = lambda: None
35
+jit_monitor._setup_triton_jit_hook = lambda: None
36
+jit_monitor._setup_cutedsl_jit_hook = lambda: None
37
+jit_monitor._setup_tilelang_jit_hook = _must_not_run
38
+jit_monitor.activate()
39
+
40
+imported = [
41
+ name for name in sys.modules if name == "tilelang" or name.startswith("tilelang.")
42
+]
43
+assert not imported, f"TileLang was imported: {imported}"
44
+
45
+libdl = ctypes.CDLL("libdl.so.2")
46
+dlsym = libdl.dlsym
47
+dlsym.argtypes = [ctypes.c_void_p, ctypes.c_char_p]
48
+dlsym.restype = ctypes.c_void_p
49
+dladdr = libdl.dladdr
50
+dladdr.argtypes = [ctypes.c_void_p, ctypes.POINTER(DlInfo)]
51
+dladdr.restype = ctypes.c_int
52
+
53
+address = dlsym(None, b"hipFree")
54
+assert address is not None, "hipFree is not available in the global symbol table"
55
+info = DlInfo()
56
+assert dladdr(address, ctypes.byref(info))
57
+source = info.dli_fname.decode() if info.dli_fname else "<unknown>"
58
+assert "libhip_stub.so" not in source, source
59
+assert "libamdhip64.so" in source, source
60
+print("OK")
tests/kernels/test_mhc_tilelang_jit.py
+14
-45
@@ -1,10 +1,11 @@
1
# SPDX-License-Identifier: Apache-2.0
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4
-import ctypes
4
import importlib
5
import importlib.util
6
+import subprocess
7
import sys
8
+from pathlib import Path
9
from types import ModuleType
10
from typing import Any
11
@@ -78,51 +79,19 @@ def test_tilelang_jit_decorator_is_lazy_only_on_rocm(
79
80
81
@pytest.mark.skipif(not current_platform.is_rocm(), reason="Test requires ROCm")
81
-def test_deepseek_v4_import_and_jit_monitor_do_not_hijack_hip_symbols(
82
- monkeypatch: pytest.MonkeyPatch,
83
-) -> None:
82
+def test_deepseek_v4_import_and_jit_monitor_do_not_hijack_hip_symbols() -> None:
83
if importlib.util.find_spec("tilelang") is None:
84
pytest.skip("Test requires TileLang to be installed")
85
87
- class DlInfo(ctypes.Structure):
88
- _fields_ = [
89
- ("dli_fname", ctypes.c_char_p),
90
- ("dli_fbase", ctypes.c_void_p),
91
- ("dli_sname", ctypes.c_char_p),
92
- ("dli_saddr", ctypes.c_void_p),
93
- ]
94
-
95
- libdl = ctypes.CDLL("libdl.so.2")
96
- dlsym = libdl.dlsym
97
- dlsym.argtypes = [ctypes.c_void_p, ctypes.c_char_p]
98
- dlsym.restype = ctypes.c_void_p
99
- dladdr = libdl.dladdr
100
- dladdr.argtypes = [ctypes.c_void_p, ctypes.POINTER(DlInfo)]
101
- dladdr.restype = ctypes.c_int
102
-
103
- from vllm.model_executor.layers import mhc # noqa: F401
104
- from vllm.models import deepseek_v4 # noqa: F401
105
- from vllm.utils import jit_monitor
106
-
107
- monkeypatch.setattr(jit_monitor, "_active", False)
108
- monkeypatch.setattr(jit_monitor, "_setup_triton_autotuning_print", lambda: None)
109
- monkeypatch.setattr(jit_monitor, "_setup_triton_jit_hook", lambda: None)
110
- monkeypatch.setattr(jit_monitor, "_setup_cutedsl_jit_hook", lambda: None)
111
- monkeypatch.setattr(
112
- jit_monitor,
113
- "_setup_tilelang_jit_hook",
114
- lambda: pytest.fail("TileLang JIT monitor must not run on ROCm"),
86
+ # Both claims are about process-global state, `sys.modules` and the symbol
87
+ # table, and a sibling test legitimately imports TileLang to exercise those
88
+ # kernels, so the checks only mean something in an interpreter of their own.
89
+ script = Path(__file__).parent / "scripts" / "check_no_tilelang_hijack.py"
90
+ result = subprocess.run(
91
+ [sys.executable, str(script)],
92
+ capture_output=True,
93
+ text=True,
94
+ timeout=300,
95
)
116
- jit_monitor.activate()
117
-
118
- assert not any(
119
- name == "tilelang" or name.startswith("tilelang.") for name in sys.modules
120
- )
121
-
122
- address = dlsym(None, b"hipFree")
123
- assert address is not None, "hipFree is not available in the global symbol table"
124
- info = DlInfo()
125
- assert dladdr(address, ctypes.byref(info))
126
- source = info.dli_fname.decode() if info.dli_fname else "<unknown>"
127
- assert "libhip_stub.so" not in source, source
128
- assert "libamdhip64.so" in source, source
96
+ if result.returncode != 0:
97
+ pytest.fail(f"HIP symbols were hijacked:\n{result.stdout}\n{result.stderr}")