Merge pull request #31054 from darrenstahlmsft/WaitOOBE
Windows: Wait for OOBE to prevent crashing during host update
This commit is contained in:
commit
7f0b833621
6 changed files with 61 additions and 3 deletions
|
@ -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)
|
||||
|
|
|
@ -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() {
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue