# DF-4025 — re_stop(TRUE) deadlocks against re_tick (callout_stop AB-BA under the driver serializer): permanently wedged threads + CPU-wide callout starvation

**File:** `sys/dev/netif/re/if_re.c` (pass 2)
**Class:** CWE-667 improper locking → deadlock/DoS
**Family:** DF-3715 (em(4) instance) — the identical callout/serializer
protocol; `re(4)` instance is new (pass 1 filed only DF-1336 against this
file).

## Root cause

* `re_attach` arms an MP callout: `callout_init_mp(&sc->re_timer)`
  (if_re.c:604); `re_init` schedules it every second
  (`callout_reset(&sc->re_timer, hz, re_tick, sc)`, if_re.c:1881).
* The callback blocks on the driver serializer **by hand**:
  `re_tick` (if_re.c:1354-1361) → `lwkt_serialize_enter(ifp->if_serializer)`
  (:1358) → `re_tick_serialized` re-arms itself *under* the serializer
  (:1371-1380).
* `re_stop(sc, TRUE)` runs with the serializer **held** (every caller holds
  it: `re_detach` :909-911, `re_suspend` :2045-2047, `re_shutdown`
  :2116-2118, `re_ioctl` SIOCSIFFLAGS-down :1918, `re_init` :1871) and at
  :2000 issues `callout_stop(&sc->re_timer)` — clearing `IFF_RUNNING` only
  afterwards (:2001).
* DragonFly `callout_stop()` is **synchronous**: kern_timeout.c:1091 →
  `_callout_cancel_or_stop(..., sync=1)`; it `ssleep`s on `"costp"`
  (kern_timeout.c:923) until an INPROG callback completes.

AB-BA: a `re_tick` dequeued on another CPU that parks in
`lwkt_serialize_enter` can never finish while the stopper holds the
serializer; the stopper sleeps in `callout_stop` waiting for exactly that
callback. Both threads wedge permanently, `if_serializer` is never
released (every later ioctl/if_start on `re0` blocks), and the parked CPU's
softclock thread stops delivering **all** callouts for that CPU.

## Triggers (on re hardware)

`ifconfig reX down` / any `re_init` (SIOCSIFFLAGS up, SIOCSIFCAP), driver
detach, suspend/resume, reboot — racing the 1 Hz `re_tick`. Narrow
per-tick window but repeatable; same proven mechanism as DF-3715.

## Verification (mechanism PROVEN on this guest)

The guest has no Realtek NIC (virtio-net only — `env.txt`), so the
driver-specific path cannot run. Per family convention a **protocol
replica** (`rereplica.ko`) reproduces re's exact protocol: one MP callout
whose handler does a blocking `lwkt_serialize_enter` + under-lock self
re-arm (`re_tick` shape), torn down by `callout_stop()` while the
serializer is held (`re_stop(TRUE)` shape, same call order: stop → clear
"running" flag). Result (`run.log`): the stop sysctl prints its
pre-`callout_stop` marker and then **never returns**; the writer thread is
stuck `D3`/wchan `costp` (the exact DF-3715 signature) and the armed
softclock thread is wedged inside the parked callback. The replica
therefore proves the re-shaped protocol deadlocks on this kernel
(DFly 6.5-DEVELOPMENT, kern_timeout.c:859-932/1091).

Driver-specific runtime remains hardware-gated → final status
`inconclusive` per family convention (DF-3715 did the same).

## Fix

Make `re_tick` non-blocking: `lwkt_serialize_try()` + 1-tick
`callout_reset` retry when the serializer is busy (the exact shape the
em fix proposes for `em_timer`; see `fix.diff`).

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
