Bug 208860 - [net80211]: ieee80211_waitfor_parent() will hang forever if something is enqueued into the taskqueue
Summary: [net80211]: ieee80211_waitfor_parent() will hang forever if something is enqu...
Status: New
Alias: None
Product: Base System
Classification: Unclassified
Component: wireless (show other bugs)
Version: CURRENT
Hardware: Any Any
: --- Affects Only Me
Assignee: freebsd-wireless (Nobody)
Depends on:
Reported: 2016-04-17 16:52 UTC by Andriy Voskoboinyk
Modified: 2016-04-17 18:51 UTC (History)
1 user (show)

See Also:


Note You need to log in before you can comment on or make changes to this bug.
Description Andriy Voskoboinyk freebsd_committer 2016-04-17 16:52:29 UTC
Manual tracing (wlan0 and wlan2 are monitor mode vaps on wpi0):

wlan0: ieee80211_ioctl: before ieee80211_start_locked()
wlan0: start running, 0 vaps running
wlan0: ieee80211_start_locked: up parent wpi0
wlan0: ieee80211_ioctl: before ieee80211_waitfor_parent(), wait=1
wlan0: ieee80211_waitfor_parent: before taskqueue_block()
wlan0: ieee80211_waitfor_parent: ieee80211_draintask(ic, &ic->ic_parent_task);
<<< hangs here

wlan2: ieee80211_ioctl: before ieee80211_start_locked()
wlan2: start running, 1 vaps running
wlan2: ieee80211_new_state_locked: INIT -> RUN (nrunning 0 nscanning 0)
wlan2: ieee80211_ioctl: before ieee80211_waitfor_parent(), wait=0
<<< no progress too

Since the manpage for taskqueue(9) states

> The taskqueue_block() function blocks the taskqueue.  It prevents any
> enqueued but  not running tasks from being executed.


> Note that if taskqueue_drain() is called on a task that is enqueued on a
> taskqueue that is blocked by taskqueue_block(), then taskqueue_drain()
> can not return until the taskqueue is unblocked.

this function will never work as expected (probably, it should set a flag for ieee80211_runtask() + call taskqueue_drain_all() instead).
Comment 1 Adrian Chadd freebsd_committer 2016-04-17 18:51:48 UTC
Yeah, the whole drain/block/cancel thing really irks me with our taskqueue implementation.

If we want to use the taskqueue for driver related things, then we need some way to actually cancel/drain all in a sane way. Otherwise we end up only being able to waitfor_parent on the net80211 tasks, not the driver tasks.

It's also unclear whether we should be waiting for the driver taskqueue calls to drain/complete with waitfor_parent.

This requires a bunch more thought and planning. I'm open to ideas!