whisper : NULL-guard CPU device lookup in make_buft_list (fix #3497)
Three call sites in `src/whisper.cpp` dereference the CPU backend device returned by GGML without checking for NULL. With GGML_BACKEND_DL=ON builds, the registry starts empty and an embedder that calls `whisper_init_*` or `whisper_vad_init_*` before any explicit `ggml_backend_load*()` invocation hits `GGML_ASSERT(device != NULL)` inside `ggml_backend_dev_backend_reg` and the process is killed with `__fastfail(7)` / `0xC0000409` on Windows. Reported in #3497 (Flutter Windows embedder, same symptom). Independently reproduced on a Windows GGML_BACKEND_DL=ON build that calls `whisper_vad_init_from_file_with_params` before the dynamic CPU backend DLL is registered. Sites patched (line numbers from current master): - `make_buft_list` (line 1388): `cpu_dev` from `ggml_backend_dev_by_type` can be NULL. Return an empty buft list so the caller surfaces a NULL context instead of aborting. - `ggml_graph_compute_helper` (line 173): `backend` from `ggml_backend_init_by_type(CPU)` can be NULL. Return false so the caller surfaces a typed graph compute failure. - `whisper_exp_compute_token_level_timestamps_dtw` (line 8960): same pattern; skip the DTW step for this segment rather than abort. All three log a clear WHISPER_LOG_ERROR message pointing embedders at `ggml_backend_load_all()` / `ggml_backend_load()` as the fix on their side. Mirrors the existing NULL-guard upstream already has at line 1352 in `whisper_backend_init`. Build verified locally on macOS (CMake configure + build of the `whisper` shared library target, 0 warnings).
This commit is contained in:
parent
afa2ea544f
commit
fbe7fa8c1a
|
|
@ -171,6 +171,13 @@ static bool ggml_graph_compute_helper(
|
|||
ggml_abort_callback abort_callback,
|
||||
void * abort_callback_data) {
|
||||
ggml_backend_ptr backend { ggml_backend_init_by_type(GGML_BACKEND_DEVICE_TYPE_CPU, nullptr) };
|
||||
if (!backend) {
|
||||
// No CPU backend registered (GGML_BACKEND_DL=ON without a prior
|
||||
// ggml_backend_load_all() call). Avoid the NULL deref a few lines
|
||||
// below and surface the failure instead of aborting.
|
||||
WHISPER_LOG_ERROR("%s: failed to initialize CPU backend\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto * reg = ggml_backend_dev_backend_reg(ggml_backend_get_device(backend.get()));
|
||||
|
||||
|
|
@ -1386,6 +1393,20 @@ static buft_list_t make_buft_list(whisper_context_params & params) {
|
|||
|
||||
// CPU Extra
|
||||
auto * cpu_dev = ggml_backend_dev_by_type(GGML_BACKEND_DEVICE_TYPE_CPU);
|
||||
if (cpu_dev == nullptr) {
|
||||
// No CPU backend registered in the GGML registry. This can happen with
|
||||
// GGML_BACKEND_DL=ON builds when the host process has not loaded any
|
||||
// CPU backend DLL via `ggml_backend_load*()` before reaching this code
|
||||
// path (e.g. `whisper_init_*` or `whisper_vad_init_*` called before any
|
||||
// explicit backend load). Without this guard, the next line aborts
|
||||
// the process via `GGML_ASSERT(device != NULL)`. Returning an empty
|
||||
// buft_list lets the caller surface a NULL whisper context instead.
|
||||
WHISPER_LOG_ERROR("%s: no CPU backend device registered; "
|
||||
"load a CPU backend with ggml_backend_load_all() or "
|
||||
"ggml_backend_load() before initializing the whisper context\n",
|
||||
__func__);
|
||||
return {};
|
||||
}
|
||||
auto * cpu_reg = ggml_backend_dev_backend_reg(cpu_dev);
|
||||
auto get_extra_bufts_fn = (ggml_backend_dev_get_extra_bufts_t)
|
||||
ggml_backend_reg_get_proc_address(cpu_reg, "ggml_backend_dev_get_extra_bufts");
|
||||
|
|
@ -8937,6 +8958,13 @@ static void whisper_exp_compute_token_level_timestamps_dtw(
|
|||
ggml_build_forward_expand(gf, w);
|
||||
|
||||
ggml_backend_ptr backend { ggml_backend_init_by_type(GGML_BACKEND_DEVICE_TYPE_CPU, nullptr) };
|
||||
if (!backend) {
|
||||
// No CPU backend registered (GGML_BACKEND_DL=ON without a prior
|
||||
// ggml_backend_load_all() call). Skip DTW alignment for this
|
||||
// segment instead of aborting the whole process.
|
||||
WHISPER_LOG_ERROR("%s: failed to initialize CPU backend for DTW; skipping token-level timestamps\n", __func__);
|
||||
return;
|
||||
}
|
||||
ggml_backend_graph_compute(backend.get(), gf);
|
||||
|
||||
ggml_tensor * alignment = dtw_and_backtrace(gctx, w);
|
||||
|
|
|
|||
Loading…
Reference in New Issue