The problem is, as has been stated, with upstart - but not upstart per-se. The problem is the upstart configuration packaged with TVHeadend.
The existing configuration uses an "expect fork" stanza incorrectly. As per upstart documentation, "expect fork" or "expect daemon" should only be used if the starting process invokes fork() exactly once (expect fork) or twice (expect daemon). Otherwise, it should not be used AT ALL. TVH does neither when using the -f parameter, and thus should not use this stanza. Instead, run it in the foreground and let upstart manage the process.
This immediately puts a chink in the armor because now the user which TVHeadend will run as will no longer be configurable without modifying the upstart configuration file directly (specifically, the setuid stanza and the "~hts" portion of the configuration directory).
I've managed to resolve this issue by using the following configuration file:
# tvheadend - DVB/IPTV streaming server
#
# Tvheadend is a TV streaming server for Linux supporting DVB, ATSC, IPTV,
# and Analog video (V4L) as input sources.
description "Tvheadend DVB/IPTV streaming server"
author "Adam Sutton <dev@adamsutton.me.uk>"
start on (local-filesystems and net-device-up and started udev-finish)
stop on starting shutdown
setuid hts
setgid video
respawn
script
[ -r /etc/default/tvheadend ] && . /etc/default/tvheadend
if [ "$TVH_ENABLED" != "1" ] ; then
stop
exit 0
fi
CONF="$(readlink -f ~hts/.hts/tvheadend)"
[ -n "$TVH_CONF_DIR" ] && CONF="-c $TVH_CONF_DIR"
ARGS="-c ${CONF}"
[ -z "$TVH_ADAPTERS" ] || ARGS="$ARGS -a $TVH_ADAPTERS"
[ "$TVH_IPV6" = "1" ] && ARGS="$ARGS -6"
[ -z "$TVH_HTTP_PORT" ] || ARGS="$ARGS --http_port $TVH_HTTP_PORT"
[ -z "$TVH_HTTP_ROOT" ] || ARGS="$ARGS --http_root $TVH_HTTP_ROOT"
[ -z "$TVH_HTSP_PORT" ] || ARGS="$ARGS --htsp_port $TVH_HTSP_PORT"
[ "$TVH_DEBUG" = "1" ] && ARGS="$ARGS -s"
[ ! -z "$TVH_DELAY" ] && sleep $TVH_DELAY
exec tvheadend $ARGS $TVH_ARGS
end script
This corrects the start/stop delay problem, and allows upstart to properly manage the TVHeadend process. However, if there is a need to change the user that TVH runs as (like XBMCbuntu does), then the init configuration will have to be edited as the setuid/setgid stanzas are not dynamic and can't be configured based on a variable.
This fixed the problems 100% for me. However, it requires that your Linux install have upstart 1.4 or newer installed (for setuid/setgid support).
Hope this helps!