microsoft / microsoft/onnxruntime
XNNPACK EP on Android arm64 aborts the process (Abort message: 'terminating') instead of returning an error — Resize with empty scales, still in 1.26.0
- Dominant language
- C++
- Stars
- 21.9k
- Forks
- 4.2k
- Avg merge
- 4d 11h
- Merged PRs (30d)
- 184
Description
### Describe the issue
Creating an `InferenceSession` with the XNNPACK EP on Android arm64 **aborts the whole process** (`SIGABRT`, `Abort message: 'terminating'`) instead of returning an error. Because the C++ exception escapes through `std::terminate`, a managed `try/catch` around session creation cannot intercept it, so an application has no way to probe for XNNPACK support and fall back to CPU.
This is the same failure mode reported in #23826 (closed as a documentation issue). That reporter tracked the root cause down to `Resize` nodes whose `scales` input is an **empty tensor**, and worked around it by patching their own copy of the XNNPACK wrapper. The underlying crash is still present in **1.26.0**, and it reproduces with a widely used public model.
Two separable problems:
1. XNNPACK cannot handle `Resize` with an empty `roi`/`scales` initializer (opset 11 style, produced by `tf2onnx`).
2. Regardless of (1) — an unsupported node should not terminate the process. Session creation should fail with a catchable status so callers can fall back to the CPU EP.
### To reproduce
**Model:** MoveNet SinglePose Lightning v4, `tf2onnx` conversion — public and directly downloadable:
```
https://raw.githubusercontent.com/Kazuhito00/MoveNet-Python-Example/515743a113e49b4f31677b1f6252c0041f237e30/onnx/movenet_singlepose_lightning_4.onnx
```
Input `1x192x192x3` int32 NHWC, output `1x1x17x3`, `opset_import: ai.onnx v11`.
The model contains three `Resize` nodes, each with `roi` and `scales` bound to the same zero-length initializer:
```
Resize__347 inputs = [ ...conv2d/BiasAdd:0, const_empty_float__341, const_empty_float__341, Concat__346:0 ]
Resize__368 inputs = [ ...re_lu/Relu:0, const_empty_float__341, const_empty_float__341, Concat__367:0 ]
Resize__389 inputs = [ ...re_lu_1/Relu:0, const_empty_float__341, const_empty_float__341, Concat__388:0 ]
const_empty_float__341: initializer, dims = [0] # empty tensor
```
**Code** (C#, `Microsoft.ML.OnnxRuntime` 1.26.0, .NET 10 Android):
```csharp
using var options = new SessionOptions();
options.AppendExecutionProvider(
"XNNPACK",
new Dictionary { ["intra_op_num_threads"] = "2" });
// Never returns. The process aborts here; the surrounding try/catch never runs.
using var session = new InferenceSession(modelBytes, options);
```
The same model loads and runs correctly with default session options (CPU EP) on the same device.
### Urgency
Not blocking — we fall back to the CPU EP. But it costs us the ability to even *probe* for XNNPACK at runtime: a process-level abort cannot be guarded, so the only safe option is never to request the EP at all.
### Platform
Android
### OS Version
Android 15 (`realme/RMX3771RU/RE58B8L1:15/AP3A.240617.008`), arm64-v8a, MediaTek Dimensity 7050
### ONNX Runtime Installation
Released Package
### ONNX Runtime Version or Commit ID
1.26.0 (`Microsoft.ML.OnnxRuntime` NuGet; native library from `runtimes/android/native/onnxruntime.aar`, `jni/arm64-v8a/libonnxruntime.so`)
### ONNX Runtime API
C#
### Architecture
ARM64
### Execution Provider
Other / Unknown (XNNPACK)
### Execution Provider Library Version
XNNPACK as shipped inside the 1.26.0 Android AAR (`XnnpackExecutionProvider` symbols are present in `jni/arm64-v8a/libonnxruntime.so`, so the EP is compiled in).
### Actual behaviour
```
F libc : Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 32022 (.NET TP Worker)
F DEBUG : Build fingerprint: 'realme/RMX3771RU/RE58B8L1:15/AP3A.240617.008/T.231124a_d5daf:user/release-keys'
F DEBUG : ABI: 'arm64'
F DEBUG : pid: 31996, tid: 32022, name: .NET TP Worker
F DEBUG : signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr --------
F DEBUG : Abort message: 'terminating'
F DEBUG : backtrace:
F DEBUG : #00 pc 0000000000093dc8 /apex/com.android.runtime/lib64/bionic/libc.so (abort+168)
F DEBUG : #01 pc 00000000009c32a8 /lib/arm64/libonnxruntime.so
F DEBUG : #02 pc 00000000009c2d04 /lib/arm64/libonnxruntime.so
F DEBUG : #03 pc 00000000009c2ca0 /lib/arm64/libonnxruntime.so
F DEBUG : #04 pc 00000000009c2c64 /lib/arm64/libonnxruntime.so
F DEBUG : #05 pc 00000000009ff2a8 /lib/arm64/libonnxruntime.so
F DEBUG : #06 pc 0000000000b6ace4 /lib/arm64/libonnxruntime.so
F DEBUG : #07 pc 0000000000b79f04 /lib/arm64/libonnxruntime.so
F DEBUG : #08 pc 0000000000b53d94 /lib/arm64/libonnxruntime.so
F DEBUG : #09 pc 00000000013d810c /lib/arm64/libonnxruntime.so
F DEBUG : #10 pc 00000000013dad94 /lib/arm64/libonnxruntime.so
F DEBUG : #11 pc 00000000013d85d4 /lib/arm64/libonnxruntime.so
F DEBUG : #12 pc 00000000013d49d8 /lib/arm64/libonnxruntime.so
F DEBUG : #13 pc 0000000000a2223c /lib/arm64/libonnxruntime.so
F DEBUG : #14 pc 0000000000a26d60 /lib/arm64/libonnxruntime.so
F DEBUG : #15 pc 0000000000acdd5c /lib/arm64/libonnxruntime.so
F DEBUG : #16 pc 00000000009e89f4 /lib/arm64/libonnxruntime.so
F DEBUG : #17 pc 00000000001abc08 /lib/arm64/libmonosgen-2.0.so
...
F DEBUG : #21 pc 000000000025acc8 /lib/arm64/libmonosgen-2.0.so (mono_runtime_invoke_checked+140)
```
(`libonnxruntime.so` BuildId `de83f9cb47b2efdf4d6ddb222f4ac169dec0542e`. The library is unstripped only to the extent shipped in the AAR, hence the bare addresses.)
### Expected behaviour
Session creation with an unsupported model should fail with an `OrtStatus` / `OnnxRuntimeException` that the caller can catch and handle — for example by falling back to the CPU EP — rather than calling `std::terminate` and taking the process down.
Additionally, `Resize` with an empty `roi`/`scales` initializer is valid ONNX (both inputs are optional and this is what `tf2onnx` emits for opset 11); XNNPACK should either handle it or decline to take the node during partitioning.
Contributor guide
Research direction
Start with the C# InferenceSession reproduction using the MoveNet model and the XNNPACK execution provider, then trace the Resize nodes with empty roi/scales inputs through the native XNNPACK path. Done means unsupported models return a catchable OrtStatus or OnnxRuntimeException without terminating the Android process, and valid empty Resize inputs are handled or declined during partitioning.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- android, cpp, csharp
- Domain
- machine-learning, mobile-dev
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100