Dear bug 555296 subscribers,

Recently, I ran into this bug, where a host system cannot resume from
hibernate-to-disk when a VirtualBox VM was running while VT-X is
enabled.  It's fairly common [0].

So, I decided to patch it.  This patch allows the system to successfully
suspend while VMs are running.  It's been deployed on my machine for
around a week now (10 - 20 successfull suspend-resume cycles, without
needing to restart).

On to the details.  The patch:

- Iterates through each user on the system.
- Saves the state of each user's running VMs, safely stopping them.
- The system then continues hibernating, safely.

Shortcomings of this script folks might want to address include:

- Not disablable through configuration settings (not really sure what
  config file to use).

Enabling this script in Squeeze involves linking it to:

    /etc/pm/sleep.d/01_virtualbox-vm-control

I hope this helps somebody,
Nick

#! /bin/sh

### BEGIN INIT INFO
# Provides:          Suspends all local virtual machines.
# Required-Start:    $local_fs $remote_fs
# Required-Stop:
# Default-Start:     
# Default-Stop:      S 0 1 6
### END INIT INFO

# inspired by: http://ubuntuforums.org/showthread.php?t=405038

N=/etc/init.d/virtualbox_vm_control

set -e

users=`who | cut -f1 -d " " | sort -u`
vmCount="pgrep -c VirtualBox"
runningVms="vboxmanage list runningvms | tail -n +5 - | sed -e 's/{.*$//1' -e 
's/\\\"//g'"
perUserVms="su \$user -c \"$runningVms\""

wait_for() {
    # usage: wait_for seconds
    I=0
    while [ `eval $perUserVms` ] && [ $I -lt $1 ]
    do
        sleep 1
        I=$(($I + 1))
        echo -n "."
    done
}

case "$1" in
    stop|hibernate)
        for user in $users
        do
            echo "Stopping Virtualbox VMs for ${user}:"

            if [ -z `eval $perUserVms` ]
            then
                echo "    No running VMs."

            else
            # nicely ask the VMs to stop.
                echo -n "    Telling VMs to save state..."

                for vm in `eval $perUserVms`
                do
                    su $user -c "vboxmanage controlvm ${vm} savestate > 
/dev/null" &
                done
                echo " done."

                echo -n "    Waiting for VMs to die..."
                wait_for 60

                if [ -z `eval $perUserVms` ]
                then
                    echo " done."

                else
                # the VMs didn't stop.
                    echo " NOT DONE."
                    echo -n "    Killing VMs..."

                    killall VirtualBox &> /dev/null
                    wait_for 10
                    
                # the VMs still didn't stop.  slaughter them.
                    if [ -n `eval $perUserVms` ]
                    then
                        killall -s 9 VirtualBox &> /dev/null
                        wait_for 5
                    fi
                    
                    echo " done."
                fi
            fi
        done

        # and sleep for a few seconds to let the disks flush.
        sleep 5
        ;;
    start|reload|restart|force-reload)
        ;;
    *)
        echo "Usage: $N stop" >&2
        exit 1
        ;;
esac
exit 0
-- 
GPG: 0x4C682009 | 084E D805 31D8 5391 1D27  0DE1 9780 FD4D 4C68 2009

Reply via email to