Repository navigation
Add session_options.custom_ops_libraries and share session options with auxiliary sessions - #2725
Conversation
…th auxiliary sessions Models that combine several custom-op libraries (for example fused attention and fused hyper-connection ops shipped next to a model package) could only name one library through `session_options.custom_ops_library`. - `session_options.custom_ops_libraries` is a list of additional custom-op libraries, registered in order after `custom_ops_library`. Every entry goes through the same path-traversal and allow-list checks as the single library, and all entries are validated before any library is registered. - `custom_ops_libraries` is inherited together with the other session options. - `InheritSessionOptionsFromParent` exposes the existing inheritance helper so components that create extra sessions (auxiliary heads) can inherit the decoder's providers, provider options, config entries and custom ops. - Unit tests cover parsing, inheritance, and the allow-list for every entry. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved library names can bypass the intended directory allow-list.
1 open finding
What changed in this PR
Adds ordered multi-library custom-op configuration and session-option inheritance for auxiliary sessions.
Changes:
- Parses and inherits
custom_ops_libraries. - Validates and registers multiple libraries in order.
- Adds configuration, inheritance, and allow-list tests.
| File | Description |
|---|---|
src/config.h |
Declares the new option and inheritance API. |
src/config.cpp |
Parses and inherits library lists. |
src/models/model.cpp |
Validates and registers configured libraries. |
test/cpp/engine/custom_ops_libraries_tests.cpp |
Tests parsing, inheritance, and validation. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
- Reject custom ops library entries that cannot be resolved inside an allowed directory instead of handing the raw name to the platform loader. - Build the allow-list directories once instead of per entry. - Inherit custom_ops_library and custom_ops_libraries together, only when the child sets neither; register duplicate entries once. - Make error messages generic and extend tests (unresolved entries, inheritance, non-vacuous out-of-allow-list case with RAII cleanup). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Baiju Meswani (baijumeswani)
left a comment
There was a problem hiding this comment.
The approach looks good. I checked the latest commit and tested the config behavior. The earlier missing-library issue is fixed. Please fix the wrong-type check, explain the change to old library loading, and make the list rules clear. I also suggest a few tests that actually load libraries. Details are inline. I did not run the full engine test suite.
…ary load tests - Reject scalar values for `session_options.custom_ops_libraries` in `SessionOptions_Element::OnValue` instead of adding them to `config_entries`. - Document overlay append behavior, empty-list inheritance semantics, allowed library directories, and two-phase path validation vs. sequential registration. - Build two test custom-op shared libraries (`custom_ops_test_first` and `custom_ops_test_second`) and test actual loading, registration order (`custom_ops_library` before `custom_ops_libraries`), deduplication across relative/canonical paths, overlay rules, empty-list inheritance, and MTP `CreateMtpDecoderConfig` inheritance/override. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Description
Adds
session_options.custom_ops_libraries, a list of custom-op libraries registered in order after the existing singlecustom_ops_library, and exportsInheritSessionOptionsFromParentso components that create auxiliary sessions (for example MTP/draft heads) can inherit the decoder's providers, provider options, config entries and custom ops.Models whose graphs use several custom-op domains (fused attention, hyper-connection, GEMM and head ops shipped next to the model package) currently cannot name more than one library. This change is generic and has no dependency on any model type; it is the first step of the Qwen3.8-Flash static-graph backend series (see the end of this description), but stands alone and targets
main.Summary of Changes
src/config.h,src/config.cppsession_options.custom_ops_libraries(JSON string array; scalar values such as"custom_ops_libraries": "ops.so"are rejected during parsing). Overlays append tocustom_ops_libraries(and[]leaves existing entries unchanged).InheritSessionOptionsFromParentexposes the existing inheritance helper;custom_ops_libraryandcustom_ops_librariesare inherited together when the child sets neither (note that"custom_ops_libraries": []leaves the vector empty and therefore still inherits from the parent unlesscustom_ops_libraryis set).src/models/model.cppcustom_ops_libraryand then everycustom_ops_librariesentry go through the same path-traversal and allow-list checks, with duplicate resolved paths registered once. All paths are validated against the allow-list before loading starts; validated libraries are then loaded and registered sequentially in order (so a later load/registration error can still leave earlier libraries registered onsession_options).test/CMakeLists.txt,test/cpp/engine/custom_ops_test_lib/custom_ops_test_lib.cpp,test/cpp/engine/custom_ops_libraries_tests.cppcustom_ops_test_firstandcustom_ops_test_second) and tests parsing/ordering, overlay rules, rejection of non-string entries and scalar values, inheritance (including[]andCreateMtpDecoderConfig), allow-list validation, and actual library loading, ordering, and deduplication.Library Location Requirement
Every entry in
custom_ops_libraryandcustom_ops_librariesmust resolve to an existing file inside one of the allowed directories:genai_config.json),Previously, an unresolved bare library name in
custom_ops_librarywas passed directly toRegisterCustomOpsLibraryand could be resolved through the platform loader search path (LD_LIBRARY_PATH/PATH). Unresolved entries are now rejected before loading so the directory allow-list cannot be bypassed; users should place custom-op libraries in one of the allowed directories above (typically the model folder).Testing
-DUSE_CUDA=OFF) onmain:engine_unit_tests929 passed, 0 failed, 2 skipped (including all 9 tests inCustomOpsLibrariesConfigTest, which load real test custom-op shared libraries to verify registration, ordering, and deduplication).lintrunner,clang-format(20.1.8) andgit diff --checkare clean.Motivation and Context
Found while hosting a model that uses seven custom-op libraries. Registering them through one
custom_ops_libraryentry was not possible, and auxiliary sessions did not inherit the decoder's custom ops, so head graphs failed to load without repeating the whole session configuration.This is the first PR of a stack that adds an Engine-hosted CUDA-graph MTP backend for Qwen3.8-Flash-Next (greedy only, one resident request, Linux/CUDA, no prefix cache). The follow-ups are drafts stacked on
kvaishnavi/qwen-38-flash-run, so this commit is also carried as the first commit of the next PR (#2726) until this one merges. The stack: #2726 (CUDA data plane library) -> #2727 (model type and device engine) -> #2728 (Engine hosting) -> #2729 (qualification tools).Checklist
session_optionsyet)