I believe I found the problem here, after much poking around. Turns out the issue does not appear to be in the halt source code, but in the /etc/init.d/halt file.
The /etc/init.d/halt file does some checking to see what the contents of the /etc/default/halt file is (halt or poweroff). If it's the standard "poweroff" then /etc/initd/halt behaves properly, setting the necessary flags to kill the power. However, when /etc/init.d/halt is set to "halt" then the /etc/init.d/halt script does not handle this properly. Or, more specifically, it looks like the script does not correctly figure out whether the user has passed in any of our own special parameters. This might be easier with some examples. When /etc/default/halt is set to "halt" then here is how the /etc/init.d/halt script works: 1. Running plain "halt" results in "halt" being called and we get the correct behaviour. The system stops, but does not power off. 2. Running "halt -p" results in "halt" being called as just "halt". The user's special "-p" flag is not appended to the command. The halt command stops the system, but does not power off. I believe the solution here is to update /etc/init.d/halt and have it call the "halt" command with any parameters the user specifies, appended to the command line. Otherwise it only reads the default value and ignores command line parameters. I manually modified my copy of the script to put "-p" on the end of "halt", regardless of the default, and it correctly shutdown the system and powered off. So the issue here seems to be the script not passing user parameters rather than an issue with the halt.c code. Though I'm open to ways we can better manage parameters to make writing/updating the halt init.d script easier. - Jesse (upstream dev)