Merge pull request #31054 from darrenstahlmsft/WaitOOBE

Windows: Wait for OOBE to prevent crashing during host update
This commit is contained in:
Brian Goff 2017-02-16 11:18:25 -05:00 committed by GitHub
commit 7f0b833621
6 changed files with 61 additions and 3 deletions

View file

@ -261,6 +261,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

@ -5,6 +5,8 @@ import (
"os"
"path/filepath"
"strings"
"syscall"
"unsafe"
"github.com/Microsoft/hcsshim"
"github.com/Sirupsen/logrus"
@ -37,6 +39,8 @@ const (
windowsMinCPUPercent = 1
windowsMaxCPUPercent = 100
windowsMinCPUCount = 1
errInvalidState = syscall.Errno(0x139F)
)
// Windows has no concept of an execution state directory. So use config.Root here.
@ -236,7 +240,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
@ -608,3 +613,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
}