|WARNING| [13/13] examples/eventdev_pipeline: make signal handler safe
dpdklab at iol.unh.edu
dpdklab at iol.unh.edu
Mon Sep 7 01:45:58 CEST 2026
Test-Label: ai-code-review
Test-Status: WARNING
https://dpdk.org/patch/169134
_AI Code Review_
=== Patch Review: series.patch (via Claude) ===
Review date: 2026-09-06
# DPDK Patch Review
## Summary
This series removes async-signal-unsafe operations from signal handlers across multiple DPDK examples and applications. The patches generally set a flag in the handler and defer work to main context, which is the correct pattern.
---
## Patch 01/13: graph: do not call printf in signal
**No issues found.**
---
## Patch 02/13: examples: remove printf from signal handler
**No issues found.**
---
## Patch 03/13: examples/vmdq: do not print from signal handler
**Error: Unsafe shared variable access**
`stats_requested` is written from signal context and read from main lcore, but is declared `volatile sig_atomic_t`. While `sig_atomic_t` guarantees atomic access, `volatile` does not provide memory ordering between threads (main lcore vs signal delivery on potentially different lcore).
Correct fix:
```c
static _Atomic sig_atomic_t stats_requested;
/* In handler */
atomic_store_explicit(&stats_requested, 1, memory_order_relaxed);
/* In lcore_main */
if (atomic_load_explicit(&stats_requested, memory_order_relaxed) && ...) {
atomic_store_explicit(&stats_requested, 0, memory_order_relaxed);
print_stats();
}
```
Note: `sig_atomic_t` is for signal-to-same-thread communication. For signal-to-different-thread, use `rte_atomic_*_explicit()` wrappers around `_Atomic sig_atomic_t`.
---
## Patch 04/13: examples/symmetric_mp: do not print or exit in handler
**Error: Missing volatile on shared flag**
`quit` is a plain `int` set by signal handler and read by worker loops on other lcores. Without `volatile`, the compiler can hoist the load out of the loop, preventing the workers from ever seeing the change.
Correct fix:
```c
static volatile sig_atomic_t quit;
```
The patch declared it `volatile sig_atomic_t` in the handler but not where it's used in `lcore_main()`. The declaration must be in the shared location visible to both (file scope).
---
## Patch 05/13: examples/vdpa: make signal handler safe
**No issues found.**
---
## Patch 06/13: examples/vhost: make signal handler safe
**No issues found.**
---
## Patch 07/13: examples/vhost_blk: do not tear down from signal handler
**No issues found.**
---
## Patch 08/13: examples/ntb: do not print and re-raise from signal handler
**Warning: Unsafe shared variable access**
`conf->stopped` is marked `volatile uint8_t` which is correct for signal-to-same-thread, but the signal may be delivered to any lcore. If the signal arrives on lcore A and sets `stopped` for lcore B's streams, lcore B reads it without memory ordering.
This is a gray area: if the signal is always delivered to a specific lcore, `volatile` suffices. But DPDK signal handling doesn't guarantee delivery lcore, so strictly speaking this should be:
```c
volatile _Atomic uint8_t stopped;
```
with `rte_atomic_store_explicit(..., memory_order_relaxed)` in the handler.
Severity: **Warning** (depends on signal delivery behavior, which is unspecified for multi-threaded DPDK apps).
---
## Patch 09/13: examples/ipsecgw: do not print from signal handler
**No issues found.**
---
## Patch 10/13: examples/l2fwd-macsec: remove print in signal handler
**No issues found.**
---
## Patch 11/13: examples/ethtool: fix exit flag and unchecked cmdline
**Error: Missing volatile on shared flag**
The patch changes `exit_now` to `volatile int`, which is correct for the signal-handler case but insufficient if `exit_now` is set on one lcore and read on another (the patch doesn't show the full context, but `worker_main()` polling it suggests multi-lcore access).
If `exit_now` is only set by main and read by workers after fork/launch, `volatile` suffices. If it can be set by any lcore, should be `volatile _Atomic int` with `rte_atomic_*_explicit()`.
Assuming signal-only writes: the patch is correct. If there are non-signal writes from other lcores, add atomics.
The `cmdline_stdin_new()` check is good.
---
## Patch 12/13: examples/vmdq_dcb: allow exit on signal
**Error: Missing volatile on shared flag**
`quit` is declared `volatile sig_atomic_t`, which is correct for signal writes. However, the patch does not show where `quit` is declared; if it's at file scope, it must be visible to both `signal_handler` and `lcore_main`. Assuming the declaration is correct, no issue.
Actually, re-reading: the patch declares `quit` at file scope before `signal_handler()`, which is correct. **No issue.**
---
## Patch 13/13: examples/eventdev_pipeline: make signal handler safe
**Warning: Potential race on `fdata->done`**
The handler reads `fdata->done` (first `if` checks it, then second `if` sets it). `fdata->done` is not shown in the patch but is presumably a plain `int` in a shared structure. If another thread is concurrently writing `fdata->done`, the handler's read races.
The pattern:
```c
if (fdata->done)
_exit(1);
fdata->done = 1;
```
is safe only if `fdata->done` is `volatile sig_atomic_t` or `_Atomic`. Without seeing the declaration of `fdata`, cannot confirm this is safe. If `fdata->done` is a plain `int`, this is a data race.
The change to `cdata.dump_dev_signal` from `int` to `volatile sig_atomic_t` is correct.
**Recommendation:** Ensure `fdata->done` is `volatile sig_atomic_t` or `_Atomic int`.
---
## Summary of Findings
### Errors
1. **Patch 03/13** (`examples/vmdq`): `stats_requested` written from signal and read from different lcore without atomic operations. Use `_Atomic sig_atomic_t` with `rte_atomic_*_explicit()`.
2. **Patch 04/13** (`examples/symmetric_mp`): `quit` must be `volatile sig_atomic_t` at file scope visible to both handler and `lcore_main()`. Patch declares it in handler only.
3. **Patch 11/13** (`examples/ethtool`): Insufficient information to confirm `exit_now` is only signal-written. If non-signal writes exist, needs atomics. Likely okay as-is, but flag for review.
### Warnings
4. **Patch 08/13** (`examples/ntb`): `conf->stopped` is `volatile uint8_t`, which is correct for same-thread signal handling but may race if signal is delivered to a different lcore than the one reading. Recommend `_Atomic uint8_t` with relaxed ordering.
5. **Patch 13/13** (`examples/eventdev_pipeline`): `fdata->done` must be `volatile sig_atomic_t` or `_Atomic` for the handler's read/write to be safe. Cannot confirm from patch; flag for verification.
---
## Style and Process
All patches follow DPDK coding style. No forbidden tokens, no formatting issues. The approach--set flag, defer work to main--is the correct pattern for making signal handlers safe.
No release notes needed (all are test/example changes, not public API).
---
## Overall Assessment
The series makes significant safety improvements. The primary issue is **incomplete use of atomics for cross-lcore flag access**. Patches 03, 04, and possibly 08/13 need atomics, not just `volatile`, because the flag is written by a signal handler and read by a different lcore. Patches 11 and 13 need verification of the shared variable's type.
More information about the test-report
mailing list