devd executing ´kldload -n uhid´ shortly before shutdown

obsigna

Profile disabled
At the very final stage of the shutdown sequence, devd wants to conditionally load the uhid kernel module:
Code:
...
Apr 13 13:23:52 server shutdown: reboot by root:
Apr 13 13:23:52 server ProjectStore[1147]: Received SIGTERM signal.
Apr 13 13:23:54 server kernel: .
Apr 13 13:23:54 server cnid_metad[1136]: shutting down on SIGTERM
Apr 13 13:23:54 server afpd[1135]: AFP Server shutting down
Apr 13 13:23:54 server netatalk[1112]: Netatalk AFP server exiting
Apr 13 13:23:54 server kernel: .
Apr 13 13:23:55 server kernel: .
Apr 13 13:23:55 server dhclient[370]: send_packet: No route to host
Apr 13 13:23:58 server squid[992]: Squid Parent: (squid-1) process 994 exited with status 0
Apr 13 13:23:58 server kernel: .
Apr 13 13:23:58 server ntpd[951]: ntpd exiting on signal 15
Apr 13 13:23:59 server kernel: .
Apr 13 13:24:02 server apcupsd[907]: apcupsd exiting, signal 15
Apr 13 13:24:02 server kernel: .
Apr 13 13:24:03 server apcupsd[907]: apcupsd shutdown succeeded
Apr 13 13:24:03 server devd: Executing 'kldload -n uhid'
Apr 13 13:24:03 server kernel: .
Apr 13 13:24:03 server kernel: .
Apr 13 13:24:03 server syslogd: exiting on signal 15
I am on FreeBSD 10.1-RELEASE-p9. I saw this the first time with -p8 (perhaps -p7). Doesn’t this look strange that a system is asked to load another kernel module just a millisecond before it wants to shutdown, does it? For what is devd useful anyway? Perhaps I may deactivate it again, like the last time when it came into my way, when it disabled the network stack after a VPN connection was shut down.
 
Do you run an UPS that might use device uhid? It's just an idea.
It is an APC ES600 connected via USB, however, I cannot tell if this makes use of the uhid device. At system startup, I see the following in the messages:
Code:
...
Apr 13 17:35:59 server kernel: ugen1.2: <APC> at usbus1
Apr 13 17:36:01 server apcupsd[717]: apcupsd 3.14.13 (02 February 2015) freebsd startup succeeded
...
Even if the issue is related to the UPS, this wouldn’t explain too much, since in this case one would expect devd to load the respective kernel module in the first millisecond of the system being up and running and not in the last millsecond during its final breath, when apcupsd was shutdown already. This doesn’t make sense, does it?
 
devd is a daemon which allows the system to react to hardware events, like usb devices being plugged in for example. How the system reacts when devices appear/disappear is controlled by rules specified in /etc/devd.conf, or one of the additional files in /etc/devd (You can also create your own rule files in /usr/local/etc/devd). It's now become one of the primary ways for FreeBSD to handle device changes and you'll see a lot of entries in the configuration even on a standard install. It's not something you really want to switch off unless absolutely necessary.

For instance, this rule looks for network interfaces coming up, and runs /etc/rc.d/dhclient, which will check if DHCP is configured on that interface then automatically run the DHCP client. So if you plug a cable into a network port that you have configured for DHCP, the system should magically go and request an IP address, as most people would expect.
Code:
notify 0 {
        match "system"          "IFNET";
        match "type"            "LINK_UP";
        media-type              "ethernet";
        action "/etc/rc.d/dhclient quietstart $subsystem";
};
If it's running that kldload command on shutdown, then it seems that FreeBSD is finding a new USB device during shutdown. That could be something to do with the UPS (maybe apcupsd shutting down causes the UPS to re-appear as a new device?) or could be a bug.

I can only find two devd rules that run kldload -n uhid, but I'm not sure exactly what device they are looking for. (This is from /etc/devd/usb.conf and it looks like this file might be auto-generated by something)

Code:
nomatch 32 {
  match "bus" "uhub[0-9]+";
  match "mode" "host";
  match "intclass" "0xff";
  match "intsubclass" "0x5d";
  match "intprotocol" "0x01";
  action "kldload -n uhid";
};

nomatch 32 {
  match "bus" "uhub[0-9]+";
  match "mode" "host";
  match "intclass" "0x03";
  action "kldload -n uhid";
};
For a minute I thought maybe nomatch might be matching devices that were disappearing from the system, but the man page says that these rules should only run when a new device is found.
nomatch Specifies various matching criteria and actions to perform when
no device driver currently loaded in the kernel claims a (new)
device.
So basically, devices that match the criteria above should probably be supported by the uhid driver (according to whoever created those devd rules). If nothing attaches to the device when it is inserted, it might be because the uhid driver isn't loaded, so the devd rule tries to load it (hopefully making that device start working).

You could try commenting out any rules in the devd config files that run that command and see if it stops doing it.
 
usdmatt, many thanks for your well elaborated reply. For a quick check, I disabled the apcupsd daemon, while leaving the UPS connected to the USB port, and I restarted twice. On the second shutdown, no command kldload -n uhid had been issued by devd. So you are most probably right, that in a regular shutdown on my system, apcupsd goes down and releases the USB device which triggers devd to kldload another one.

I guess a sustainable solution of this issue would be to shutdown devd more early in the whole shutdown sequence. It seems that I can’t control the shutdown sequence myself, can I?

My system is a headless server that is mostly unattended. Sometimes, I plug in a USB drive for which devd is not needed, since I always want to mount it at special locations myself. Your example of triggering the dhclient is anyway not working well in the one and only case that would be useful here, i.e. when the cable modem goes south and sometime later comes back again, devd notices nothing. So for the time being I solved MY issue by adding devd_enable="NO" to /etc/rc.conf.
 
This is good example of why FreeBSD desperately needs new init(8) and rc(8) frameworks so that the users don't have to constantly keep tinkering with the system internals to use even the most mundane pieces of hardware. For example, it is not possible to control or customize the rcorder(8) order of startup scripts without editing the /etc/rc.d/* files directly. The same applies to expressing dependencies between rc(8) scripts and devd(8) configurations as seen in this thread.
 
Back
Top