Windows: Wait for OOBE to prevent crashing during host update

Signed-off-by: Darren Stahl <darst@microsoft.com>
This commit is contained in:
Darren Stahl 2017-02-01 10:52:16 -08:00
parent dc78b3a1d4
commit e128a65685
6 changed files with 61 additions and 3 deletions

View File

@ -260,6 +260,9 @@ func (cli *DaemonCli) start(opts daemonOptions) (err error) {
<-stopc // wait for daemonCli.start() to return
})
// Notify that the API is active, but before daemon is set up.
preNotifySystem()
d, err := daemon.NewDaemon(cli.Config, registryService, containerdRemote)
if err != nil {
return fmt.Errorf("Error starting daemon: %v", err)

View File

@ -1,5 +1,9 @@
package main
// preNotifySystem sends a message to the host when the API is active, but before the daemon is
func preNotifySystem() {
}
// notifySystem sends a message to the host when the server is ready to be used
func notifySystem() {
}

View File

@ -4,6 +4,10 @@ package main
import systemdDaemon "github.com/coreos/go-systemd/daemon"
// preNotifySystem sends a message to the host when the API is active, but before the daemon is
func preNotifySystem() {
}
// notifySystem sends a message to the host when the server is ready to be used
func notifySystem() {
// Tell the init daemon we are accepting requests

View File

@ -46,6 +46,10 @@ func getDaemonConfDir(_ string) string {
func (cli *DaemonCli) setupConfigReloadTrap() {
}
// preNotifySystem sends a message to the host when the API is active, but before the daemon is
func preNotifySystem() {
}
// notifySystem sends a message to the host when the server is ready to be used
func notifySystem() {
}

View File

@ -29,8 +29,10 @@ func getDaemonConfDir(root string) string {
return filepath.Join(root, `\config`)
}
// notifySystem sends a message to the host when the server is ready to be used
func notifySystem() {
// preNotifySystem sends a message to the host when the API is active, but before the daemon is
func preNotifySystem() {
// start the service now to prevent timeouts waiting for daemon to start
// but still (eventually) complete all requests that are sent after this
if service != nil {
err := service.started()
if err != nil {
@ -39,6 +41,10 @@ func notifySystem() {
}
}
// notifySystem sends a message to the host when the server is ready to be used
func notifySystem() {
}
// notifyShutdown is called after the daemon shuts down but before the process exits.
func notifyShutdown(err error) {
if service != nil {

View File

@ -4,6 +4,8 @@ import (
"fmt"
"os"
"strings"
"syscall"
"unsafe"
"github.com/Microsoft/hcsshim"
"github.com/Sirupsen/logrus"
@ -35,6 +37,8 @@ const (
windowsMinCPUPercent = 1
windowsMaxCPUPercent = 100
windowsMinCPUCount = 1
errInvalidState = syscall.Errno(0x139F)
)
func getBlkioWeightDevices(config *containertypes.HostConfig) ([]blkiodev.WeightDevice, error) {
@ -229,7 +233,8 @@ func checkSystem() error {
if vmcompute.Load() != nil {
return fmt.Errorf("Failed to load vmcompute.dll. Ensure that the Containers role is installed.")
}
return nil
return waitOOBEComplete()
}
// configureKernelSecuritySupport configures and validate security support for the kernel
@ -601,3 +606,35 @@ func (daemon *Daemon) verifyVolumesInfo(container *container.Container) error {
func (daemon *Daemon) setupSeccompProfile() error {
return nil
}
func waitOOBEComplete() error {
kernel32 := windows.NewLazySystemDLL("kernel32.dll")
registerWaitUntilOOBECompleted := kernel32.NewProc("RegisterWaitUntilOOBECompleted")
unregisterWaitUntilOOBECompleted := kernel32.NewProc("UnregisterWaitUntilOOBECompleted")
callbackChan := make(chan struct{})
callbackFunc := func(uintptr) uintptr {
close(callbackChan)
return 0
}
callbackFuncPtr := syscall.NewCallback(callbackFunc)
var callbackHandle syscall.Handle
ret, _, err := registerWaitUntilOOBECompleted.Call(callbackFuncPtr, 0, uintptr(unsafe.Pointer(&callbackHandle)))
if ret == 0 {
if err == errInvalidState {
return nil
}
return fmt.Errorf("failed to register OOBEComplete callback. Error: %v", err)
}
// Wait for the callback when OOBE is finished
<-callbackChan
ret, _, err = unregisterWaitUntilOOBECompleted.Call(uintptr(callbackHandle))
if ret == 0 {
return fmt.Errorf("failed to unregister OOBEComplete callback. Error: %v", err)
}
return nil
}