Skip to content

fix: suppress ORT native stderr, fix HANDLE bug, clean up warnings#709

Merged
DingmaomaoBJTU merged 23 commits into
mainfrom
qiowu/build_demo_without_warning
May 26, 2026
Merged

fix: suppress ORT native stderr, fix HANDLE bug, clean up warnings#709
DingmaomaoBJTU merged 23 commits into
mainfrom
qiowu/build_demo_without_warning

Conversation

@DingmaomaoBJTU
Copy link
Copy Markdown
Collaborator

@DingmaomaoBJTU DingmaomaoBJTU commented May 22, 2026

Summary

  • ORT's pybind module writes Init provider bridge failed. directly to native stderr (fd 2 / Win32 STD_ERROR_HANDLE), bypassing Python's logging/warnings systems entirely
  • Added utils/native_stderr.py — a dedicated module for capturing and replaying native stderr output from ORT/QNN
    • suppress_ep_registration_stderr() context manager redirects fd 2 via pipe, re-emits captured lines through Python logging
    • replay_ort_startup_logs() public API for deferred replay after logging is configured
  • Fixed 64-bit HANDLE truncation bug: set proper argtypes/restype via ctypes.wintypes for GetStdHandle and SetStdHandle
  • Fixed dup2 restore ordering: UCRT's dup2 for fds 0-2 internally calls SetStdHandle, so GetStdHandle must be captured before dup2 and restored after
  • Platform-gated: no-op on non-Windows — Linux/macOS CI gets a plain import onnxruntime with zero fd overhead
  • constants.py restored to leaf-level constants-only module
  • Downgraded HF/optimum/transformers logging noise to appropriate levels
  • Added 10 unit tests covering fd capture, ANSI strip, Win32 HANDLE restore, and replay API

Reference: #477

ORT's pybind module writes "Init provider bridge failed." directly to
native stderr (fd 2 / Win32 STD_ERROR_HANDLE), bypassing Python's
logging/warnings systems so standard filters have no effect.

Add _suppress_ep_registration_stderr() in utils/constants.py — the
earliest point in the import chain where onnxruntime is first imported
(via sysinfo → device.py → constants.py). The context manager redirects
fd 2 to /dev/null and also updates Win32 STD_ERROR_HANDLE so both the
CRT and Win32 API layers are silenced for the duration.

Also applied in session.py around register_to_ort() to cover EP DLL
registration warnings on subsequent WinMLSession initialization.
@DingmaomaoBJTU DingmaomaoBJTU requested a review from a team as a code owner May 22, 2026 06:27
Replace /dev/null redirect with a pipe so ORT native messages are
captured rather than dropped. Each line is re-emitted via
logger.debug('[ORT] ...') with ANSI escape codes stripped.

Because the first onnxruntime import fires during module initialisation
(before any logging handler is registered), messages are also buffered
in _ort_startup_logs. sysinfo() flushes the buffer immediately after
configuring its Rich handler, making the ORT lines visible under
--verbose / --debug.
- HF symlinks UserWarning: INFO → DEBUG (cosmetic, cache still works)
- optimum TasksManager architecture-mismatch WARNING → DEBUG (expected
  behaviour for WinML models, not actionable)
- tqdm download progress bars: set HF_HUB_DISABLE_PROGRESS_BARS=1 by
  default (tqdm writes directly to stderr, cannot be routed through
  Python logging; override with HF_HUB_DISABLE_PROGRESS_BARS=0)

Update test_downgrade_to_info → test_downgrade_to_debug to match.
timenick

This comment was marked as spam.

timenick

This comment was marked as outdated.

timenick

This comment was marked as outdated.

Copy link
Copy Markdown
Collaborator

@timenick timenick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the ORT stderr suppression. The intent is good, but I want to flag one real correctness bug (HANDLE truncation) plus four substantive design/coverage issues before this lands.

Comment thread src/winml/modelkit/utils/constants.py Outdated
Comment thread src/winml/modelkit/utils/constants.py Outdated
Comment thread src/winml/modelkit/utils/constants.py
Comment thread src/winml/modelkit/commands/sys.py Outdated
Comment thread src/winml/modelkit/utils/constants.py Outdated
DingmaomaoBJTU and others added 9 commits May 22, 2026 15:05
Python logging filters on a parent logger are NOT applied to records
propagated from child loggers (callHandlers bypasses parent.handle()).
Change filter target from 'optimum' to 'optimum.exporters.tasks',
the actual logger that emits the TasksManager message.
Header and summary were gated by verbose=True, making them invisible
in normal (non -v) mode. self.console is always a valid Rich Console
regardless of verbose, so removing the guard makes both sections
always visible. Step-by-step progress output (ConsoleWriter) remains
verbose-only.
- HF symlinks UserWarning: WARNING → INFO (cosmetic, not actionable)
- optimum TasksManager mismatch: WARNING → INFO (expected behaviour)
- transformers 'weights not used': WARNING → INFO (expected for
  checkpoint loading, e.g. pooler dropped in sequence classifiers)

Reverts previous DEBUG choice for symlinks/TasksManager.
…ged optim config (#702)

Fixes #697.

## Summary

- **EP/device selection** — replace the large mode-matrix branching with
a straightforward `eps × devices` construction filtered against
`EP_SUPPORTED_DEVICES`. When `device=auto and ep=auto`, restrict to
locally-available pairs; when only one of them is auto, keep all pairs
but warn about ones not supported in the local environment instead of
silently dropping them.
- **Op-check skipped table** — render a title-only "Skipped - no rule
data" table for EP/device pairs with no rule data, so the per-pair
output stays consistent.
- **Analysis summary** — fix a key-shape mismatch where
`ep_instance_counts` was being rewrapped with `"EP@DEVICE"` string keys
while the renderer looked them up by `(ep, device)` tuple, which always
missed and printed `0/0/0`. Pass the tuple-keyed dict directly.
- **Counts format** — always show four numbers `S/P/U/Unk` (Supported /
Partial / Unsupported / Unknown) in both the OP CHECK table column and
the ANALYSIS SUMMARY line. Update column header and legend.
- **Optimization config** — when multiple analysis pairs are selected,
merge their `get_optimization_config(ep=…)` outputs into a single config
(union of keys). On conflicting values for the same key, log a warning
naming each pair's value; the merged config keeps the first pair's
value.
- Drop the now-unused `pair_hints` plumbing and redundant local-vs-rule
hint lines.

---------

Co-authored-by: Yi Ren <reny@microsoft.com>
…706)

## Summary

- Added `WinMLSession._get_precision()` — a best-effort,
operator-schema-based precision estimator that runs over the
already-loaded `ModelProto` (no extra I/O, no model-name hardcoding).
Exposed through `io_config["precision"]`.
- Detection ladder, first match wins:
1. **QDQ** (`QuantizeLinear` / `DequantizeLinear`) — dominant
`zero_point` initializer bit width per side; weight-side when the source
tensor is an initializer. Returns `int{n}` or `w{w}a{a}`.
2. **Block-wise quant** (`MatMulNBits` / `GatherBlockQuantized`) —
schema `bits` attribute + dominant float bit width for activations →
`w{w}a{a}`.
3. **Dominant float dtype** among initializers → `fp32` / `fp16` /
`bf16`.
  4. No signal → `None`.
- `_print_model_info` in `commands/perf.py` now shows `Precision:`
between `Task:` and `Inputs:`; the line is suppressed when precision is
`None` so unknown cases produce no noise.
- 6 new unit tests in `tests/unit/session/test_winml_session.py` cover
fp32, fp16, int8 QDQ, mixed `w8a16` QDQ, `MatMulNBits` `w4a16`, and the
no-signal-returns-`None` path.

---------

Co-authored-by: hualxie <hualxie@microsoft.com>
Address PR #709 review comments:
- Extract fd/HANDLE manipulation from constants.py to utils/native_stderr.py
- Fix 64-bit HANDLE truncation: set proper argtypes/restype via ctypes.wintypes
- Fix restore ordering: capture GetStdHandle before dup2, restore after dup2
  (UCRT's dup2 for fds 0-2 internally calls SetStdHandle)
- Platform-gate: no-op on non-Windows (no pipe/dup2 overhead on Linux/macOS)
- Public replay_ort_startup_logs() replaces private _ort_startup_logs access
- Add unit tests for capture, ANSI strip, fd restore, Win32 HANDLE restore
@DingmaomaoBJTU DingmaomaoBJTU changed the title fix: suppress ORT "Init provider bridge failed" native stderr warning fix: suppress ORT native stderr, fix HANDLE bug, clean up warnings May 25, 2026
…out_warning

# Conflicts:
#	src/winml/modelkit/session/session.py
Comment thread src/winml/modelkit/utils/native_stderr.py Fixed
Comment thread tests/unit/utils/test_native_stderr.py Fixed
suppress_native_stderr - discards to devnull, for startup/EP noise
capture_native_stderr  - captures via pipe and re-logs, for compilation

Removes the startup buffer/replay mechanism (startup noise is discarded,
not captured) and the combined parameter interface.
Comment thread pyproject.toml Outdated
@DingmaomaoBJTU DingmaomaoBJTU enabled auto-merge (squash) May 26, 2026 01:56
@DingmaomaoBJTU DingmaomaoBJTU merged commit f12db93 into main May 26, 2026
9 checks passed
@DingmaomaoBJTU DingmaomaoBJTU deleted the qiowu/build_demo_without_warning branch May 26, 2026 01:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants