Files
pip/3rd/pocketfft/pr-description.md
andrey ba897e0911 Add pending upstream pocketfft patch: POCKETFFT_NO_EXCEPTIONS option
PocketFFT (3rd/pocketfft, vendored 2018 version) cannot be compiled with
-fno-exceptions, which PIP uses on all non-Windows/non-Android targets.
This adds the proposed upstream patch adding a POCKETFFT_NO_EXCEPTIONS
option (error paths abort with a diagnostic instead of throwing), plus
the PR description for submission to mreineck/pocketfft.

Verified: PIP builds with current upstream master + this patch and
'-fno-exceptions -DPOCKETFFT_NO_EXCEPTIONS -DPOCKETFFT_NO_MULTITHREADING'
and passes the FFT functional test suite.

After the upstream PR is merged, bump the vendored header and drop the
local workarounds.
2026-10-18 18:46:59 +00:00

99 lines
3.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PR: Add `POCKETFFT_NO_EXCEPTIONS` option for builds without exception handling
Repo: https://github.com/mreineck/pocketfft
Branch base: `cpp` (upstream master)
---
## Motivation
pocketfft currently reports all errors via C++ exceptions (invalid arguments,
allocation failures, internal consistency checks). This makes the header
unusable in projects that are compiled without exception handling, e.g. with
GCC/Clang `-fno-exceptions` — a common setting in embedded,
safety-focused and performance-oriented code bases.
With `-fno-exceptions` the header fails to compile at every `throw` site:
```
pocketfft_hdronly.h: In function 'void* pocketfft::detail::aligned_alloc(...)':
error: exception handling disabled, use '-fexceptions' to enable
```
and additionally at the `catch` clauses in the thread pool (GCC rejects
`catch` under `-fno-exceptions` even with an empty body).
The only workaround today is to sed-patch the vendored header in every
downstream project. This PR adds an opt-in upstream option instead.
## What the PR adds
A new configuration macro `POCKETFFT_NO_EXCEPTIONS`, following the existing
`POCKETFFT_NO_VECTORS` / `POCKETFFT_NO_MULTITHREADING` naming convention:
```cpp
#define POCKETFFT_NO_EXCEPTIONS // optionally + POCKETFFT_NO_MULTITHREADING
#include "pocketfft_hdronly.h"
// build with -fno-exceptions as usual
```
Semantics: error conditions that would normally throw an exception instead
print a diagnostic to stderr and call `abort()`:
```
pocketfft: bad axis number
Aborted (core dumped)
```
## Design
- Every `throw std::...;` site (26 of them) is wrapped in a
`POCKETFFT_THROW(exception)` macro:
- **undefined (default):** expands to `throw exception` — behavior is
100% unchanged, exceptions are still catchable as before;
- **defined:** calls `POCKETFFT_NAMESPACE::detail::handle_fatal_error(e)`,
which prints `pocketfft: <what()>` to stderr and `std::abort()`.
- The two `try/catch` regions of the thread pool are `#if`-guarded, since
`catch` itself is a compile error under `-fno-exceptions`:
- `thread_pool::create_threads()`: without exception handling the worker
thread is created directly — a failing `std::thread` constructor already
results in `std::terminate()` per the standard, so nothing is lost;
- `threading::thread_map()`: the worker lambda simply calls `f()` without
the exception-capture plumbing.
- Why `abort()`: all error sites are unrecoverable (programmer errors such as
invalid size/stride/axis, or OOM). In a no-exception program there is no
meaningful recovery path, and abort-with-diagnostic is the customary
behavior. A user-configurable fatal handler could be a follow-up if
desired.
## Verification
`pocketfft_demo.cc` was built and run with GCC 15 and Clang (latest) in the
following configurations, with identical numerical output in all of them:
1. default (exceptions enabled) — unchanged behavior; additionally verified
that an out-of-range axis still throws a catchable `std::invalid_argument`;
2. `-DPOCKETFFT_NO_EXCEPTIONS` with exceptions enabled (mixed mode);
3. `-fno-exceptions -DPOCKETFFT_NO_EXCEPTIONS -DPOCKETFFT_NO_MULTITHREADING`;
4. `-fno-exceptions -DPOCKETFFT_NO_EXCEPTIONS` (thread pool compiled in).
Error-path check: with the macro defined (configurations 2–4), requesting a
transform with an out-of-range axis prints `pocketfft: bad axis number` and
aborts with SIGABRT.
Multithreaded check: with the macro defined and the thread pool enabled, a
1024-point transform with `nthreads=4` is bit-identical to the
single-threaded reference, across repeated pool runs.
## Files changed
- `pocketfft_hdronly.h` — the option (macro + `handle_fatal_error`, guarded
thread pool code);
- `README.md` — documentation entry in "Configuration options".
## Note for downstream users
This is what allows downstream projects that vendor the header and build with
`-fno-exceptions` (e.g. the PIP library) to drop their local header patches
and/or move to a current upstream release.