|WARNING| [v3,3/3] test/mempool: add list walk race test

dpdklab at iol.unh.edu dpdklab at iol.unh.edu
Mon Nov 9 16:55:05 CET 2026


Test-Label: ai-code-review
Test-Status: WARNING
https://dpdk.org/patch/172748

_AI Code Review_

=== Patch Review: series.patch (via Claude) ===
Review date: 2026-11-09

I'll review this DPDK patch series against the AGENTS.md guidelines, focusing on correctness bugs, C coding style, API requirements, and other guideline violations.

---

## PATCH 1/3: mempool: fix race between list walk and free

### ERRORS

None.

### WARNINGS

None.

### INFO

None.

---

## PATCH 2/3: mempool: fix dump of unpopulated pool

### ERRORS

**Error: Missing error check on unchecked return value**

Line: `rte_mempool_ops_get_info(mp, &info);` in `rte_mempool.c`

This function call is now wrapped in `if (created)`, but the return value is still not checked. `rte_mempool_ops_get_info()` can fail and return an error code. The previous code left `info` uninitialized when the call failed; now it's zero-initialized, which is better, but the error is still ignored.

Suggested fix:
```c
memset(&info, 0, sizeof(info));
if (created) {
	if (rte_mempool_ops_get_info(mp, &info) < 0) {
		/* handle error or log warning */
	}
}
```

### WARNINGS

**Warning: New public API function missing `RTE_EXPORT_*` macro in wrong location**

Line: `RTE_EXPORT_SYMBOL(rte_mempool_is_created)` appears on its own line before the function definition.

The export macro should be placed immediately before the function definition on the same line as shown in the guidelines, or directly above without a blank line. The current placement with a blank line between the macro and the function is non-standard.

Current:
```c
RTE_EXPORT_SYMBOL(rte_mempool_is_created)
bool
rte_mempool_is_created(const struct rte_mempool *mp)
```

Should be:
```c
RTE_EXPORT_SYMBOL(rte_mempool_is_created)
bool
rte_mempool_is_created(const struct rte_mempool *mp)
```

Wait - re-reading the code, the placement appears acceptable. The macro is on the line immediately before the return type. This follows the pattern shown in the guidelines. Retracting this concern.

**Warning: New API function should be marked `__rte_experimental`**

The function `rte_mempool_is_created()` is a new public API function added to the header `rte_mempool.h` but is not marked as `__rte_experimental`. According to AGENTS.md:

> New API functions must be marked as `__rte_experimental`

The function declaration in `rte_mempool.h` should have:
```c
__rte_experimental
bool rte_mempool_is_created(const struct rte_mempool *mp);
```

And the export macro should use `RTE_EXPORT_EXPERIMENTAL_SYMBOL`:
```c
RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_mempool_is_created, 26.11)
```

### INFO

None.

---

## PATCH 3/3: test/mempool: add list walk race test

### ERRORS

**Error: Resource leak on error path**

Line: In `test_mempool_list_race_phase()`, if `rte_eal_remote_launch()` fails for any worker lcore, the function sets `ret = -1` but continues launching on remaining lcores. If a subsequent launch succeeds, those launched threads will continue running because `list_race_stop` was set to 0 at the start of the function. The function then waits for all workers, but the error path doesn't set `list_race_stop = 1` before waiting, so successfully launched threads may run longer than intended.

```c
RTE_LCORE_FOREACH_WORKER(lcore_id) {
	lcore_function_t *func = i++ < nb_creators ?
		test_mempool_list_race_create :
		test_mempool_list_race_walk;

	if (rte_eal_remote_launch(func, NULL, lcore_id) != 0)
		ret = -1;  /* ERROR: continues loop without cleanup */
}
```

Suggested fix:
```c
RTE_LCORE_FOREACH_WORKER(lcore_id) {
	lcore_function_t *func = i++ < nb_creators ?
		test_mempool_list_race_create :
		test_mempool_list_race_walk;

	if (rte_eal_remote_launch(func, NULL, lcore_id) != 0) {
		ret = -1;
		rte_atomic_store_explicit(&list_race_stop, 1,
			rte_memory_order_relaxed);
		break;
	}
}
```

### WARNINGS

**Warning: File descriptor leak on error path**

Line: In `test_mempool_list_race()`, if `fopen()` succeeds but `test_mempool_list_race_phase()` fails, the file is still closed. However, if `fopen()` itself fails (returns NULL), the code continues to call `test_mempool_list_race_phase(1, f)` with a NULL file pointer, which could cause issues if the phase function tries to use it.

Current code:
```c
f = fopen("/dev/null", "w");
ret = test_mempool_list_race_phase(1, f);
if (f != NULL)
	fclose(f);
```

The pattern is actually safe because `/dev/null` writes are no-ops and `list_race_dump` is checked before use in the walk callback. However, it would be clearer to check the fopen result:

```c
f = fopen("/dev/null", "w");
if (f == NULL)
	return -1;  /* or log and continue with f = NULL */
ret = test_mempool_list_race_phase(1, f);
fclose(f);
```

Actually, reviewing the code more carefully: in `test_mempool_list_race_walk_cb()`, there is a check `if (list_race_dump != NULL)` before calling `rte_mempool_dump()`, so passing NULL is safe. The current code is acceptable. Retracting this warning.

### INFO

None.

---

## SUMMARY

The patch series addresses important race conditions in the mempool library. The primary correctness issue found is:

1. **Patch 2/3**: Missing error check on `rte_mempool_ops_get_info()` return value
2. **Patch 2/3**: New public API not marked as `__rte_experimental` (API requirement violation)
3. **Patch 3/3**: Error path in `test_mempool_list_race_phase()` doesn't stop launched threads before returning

The atomic operations for flag checking use appropriate acquire/release ordering, which correctly addresses the visibility concerns documented in the commit messages.

Review-Result: ERROR


More information about the test-report mailing list