That is an issue of obsolete dhclient that is still implemented in all Linux distributions.
The dhclient script have to deal with Lease Timeout.
When you access a wireless network, and run dhclient, it binds an IP address and Subnet mask, DNS server and some other options to your wireless interface (wlan0).
The DHCP server leases that IP to your interface for a limited time (lease time).
When you turn off the computer, or the dhclient script crashes by any reason, the client lease time counter stops.
And then you boot up the computer, or run dhclient again.
Then, dhclient finds a Prebind configuration, that refers to old lease, and it doesn't know if that lease still valid, or not.
There comes the issue. The way that dhclient solve this problem is to binding interface with Prebind, and trying to ping the router (gateway). If ping success, the Prebind is valid and is applied to wireless interface (wlan0). Else, the Prebind isn't valid, and it discarded.
This explains the reason of the sleep ("dhclient stalls for ages"), it is waiting for a DHCP server response. And if it doesn't happens, after aprox 2 minutes, it tries assuming Prebind configuration and pings the old router ("PING 192.168.1.254").
I had the same issue in my Slackware, and found all information at dhclient-script man page.
The DHCP client has been unable to contact any DHCP servers. However, an old lease has been identified, and its parameters have been passed in as with BOUND. The
client configuration script should test these parameters and, if it has reason to believe they are valid, should exit with a value of zero. If not, it should exit
with a nonzero value.
The usual way to test a lease is to set up the network as with REBIND (since this may be called to test more than one lease) and then ping the first router defined in
$routers. If a response is received, the lease must be valid for the network to which the interface is currently connected. It would be more complete to try to ping
all of the routers listed in $new_routers, as well as those listed in $new_static_routes, but current scripts do not do this.