Signed-off-by: Darren Stahl <darst@microsoft.com>
| ... | ... |
@@ -260,6 +260,9 @@ func (cli *DaemonCli) start(opts daemonOptions) (err error) {
|
| 260 | 260 |
<-stopc // wait for daemonCli.start() to return |
| 261 | 261 |
}) |
| 262 | 262 |
|
| 263 |
+ // Notify that the API is active, but before daemon is set up. |
|
| 264 |
+ preNotifySystem() |
|
| 265 |
+ |
|
| 263 | 266 |
d, err := daemon.NewDaemon(cli.Config, registryService, containerdRemote) |
| 264 | 267 |
if err != nil {
|
| 265 | 268 |
return fmt.Errorf("Error starting daemon: %v", err)
|
| ... | ... |
@@ -4,6 +4,10 @@ package main |
| 4 | 4 |
|
| 5 | 5 |
import systemdDaemon "github.com/coreos/go-systemd/daemon" |
| 6 | 6 |
|
| 7 |
+// preNotifySystem sends a message to the host when the API is active, but before the daemon is |
|
| 8 |
+func preNotifySystem() {
|
|
| 9 |
+} |
|
| 10 |
+ |
|
| 7 | 11 |
// notifySystem sends a message to the host when the server is ready to be used |
| 8 | 12 |
func notifySystem() {
|
| 9 | 13 |
// Tell the init daemon we are accepting requests |
| ... | ... |
@@ -46,6 +46,10 @@ func getDaemonConfDir(_ string) string {
|
| 46 | 46 |
func (cli *DaemonCli) setupConfigReloadTrap() {
|
| 47 | 47 |
} |
| 48 | 48 |
|
| 49 |
+// preNotifySystem sends a message to the host when the API is active, but before the daemon is |
|
| 50 |
+func preNotifySystem() {
|
|
| 51 |
+} |
|
| 52 |
+ |
|
| 49 | 53 |
// notifySystem sends a message to the host when the server is ready to be used |
| 50 | 54 |
func notifySystem() {
|
| 51 | 55 |
} |
| ... | ... |
@@ -29,8 +29,10 @@ func getDaemonConfDir(root string) string {
|
| 29 | 29 |
return filepath.Join(root, `\config`) |
| 30 | 30 |
} |
| 31 | 31 |
|
| 32 |
-// notifySystem sends a message to the host when the server is ready to be used |
|
| 33 |
-func notifySystem() {
|
|
| 32 |
+// preNotifySystem sends a message to the host when the API is active, but before the daemon is |
|
| 33 |
+func preNotifySystem() {
|
|
| 34 |
+ // start the service now to prevent timeouts waiting for daemon to start |
|
| 35 |
+ // but still (eventually) complete all requests that are sent after this |
|
| 34 | 36 |
if service != nil {
|
| 35 | 37 |
err := service.started() |
| 36 | 38 |
if err != nil {
|
| ... | ... |
@@ -39,6 +41,10 @@ func notifySystem() {
|
| 39 | 39 |
} |
| 40 | 40 |
} |
| 41 | 41 |
|
| 42 |
+// notifySystem sends a message to the host when the server is ready to be used |
|
| 43 |
+func notifySystem() {
|
|
| 44 |
+} |
|
| 45 |
+ |
|
| 42 | 46 |
// notifyShutdown is called after the daemon shuts down but before the process exits. |
| 43 | 47 |
func notifyShutdown(err error) {
|
| 44 | 48 |
if service != nil {
|
| ... | ... |
@@ -4,6 +4,8 @@ import ( |
| 4 | 4 |
"fmt" |
| 5 | 5 |
"os" |
| 6 | 6 |
"strings" |
| 7 |
+ "syscall" |
|
| 8 |
+ "unsafe" |
|
| 7 | 9 |
|
| 8 | 10 |
"github.com/Microsoft/hcsshim" |
| 9 | 11 |
"github.com/Sirupsen/logrus" |
| ... | ... |
@@ -35,6 +37,8 @@ const ( |
| 35 | 35 |
windowsMinCPUPercent = 1 |
| 36 | 36 |
windowsMaxCPUPercent = 100 |
| 37 | 37 |
windowsMinCPUCount = 1 |
| 38 |
+ |
|
| 39 |
+ errInvalidState = syscall.Errno(0x139F) |
|
| 38 | 40 |
) |
| 39 | 41 |
|
| 40 | 42 |
func getBlkioWeightDevices(config *containertypes.HostConfig) ([]blkiodev.WeightDevice, error) {
|
| ... | ... |
@@ -229,7 +233,8 @@ func checkSystem() error {
|
| 229 | 229 |
if vmcompute.Load() != nil {
|
| 230 | 230 |
return fmt.Errorf("Failed to load vmcompute.dll. Ensure that the Containers role is installed.")
|
| 231 | 231 |
} |
| 232 |
- return nil |
|
| 232 |
+ |
|
| 233 |
+ return waitOOBEComplete() |
|
| 233 | 234 |
} |
| 234 | 235 |
|
| 235 | 236 |
// configureKernelSecuritySupport configures and validate security support for the kernel |
| ... | ... |
@@ -601,3 +606,35 @@ func (daemon *Daemon) verifyVolumesInfo(container *container.Container) error {
|
| 601 | 601 |
func (daemon *Daemon) setupSeccompProfile() error {
|
| 602 | 602 |
return nil |
| 603 | 603 |
} |
| 604 |
+ |
|
| 605 |
+func waitOOBEComplete() error {
|
|
| 606 |
+ kernel32 := windows.NewLazySystemDLL("kernel32.dll")
|
|
| 607 |
+ registerWaitUntilOOBECompleted := kernel32.NewProc("RegisterWaitUntilOOBECompleted")
|
|
| 608 |
+ unregisterWaitUntilOOBECompleted := kernel32.NewProc("UnregisterWaitUntilOOBECompleted")
|
|
| 609 |
+ |
|
| 610 |
+ callbackChan := make(chan struct{})
|
|
| 611 |
+ callbackFunc := func(uintptr) uintptr {
|
|
| 612 |
+ close(callbackChan) |
|
| 613 |
+ return 0 |
|
| 614 |
+ } |
|
| 615 |
+ callbackFuncPtr := syscall.NewCallback(callbackFunc) |
|
| 616 |
+ |
|
| 617 |
+ var callbackHandle syscall.Handle |
|
| 618 |
+ ret, _, err := registerWaitUntilOOBECompleted.Call(callbackFuncPtr, 0, uintptr(unsafe.Pointer(&callbackHandle))) |
|
| 619 |
+ if ret == 0 {
|
|
| 620 |
+ if err == errInvalidState {
|
|
| 621 |
+ return nil |
|
| 622 |
+ } |
|
| 623 |
+ return fmt.Errorf("failed to register OOBEComplete callback. Error: %v", err)
|
|
| 624 |
+ } |
|
| 625 |
+ |
|
| 626 |
+ // Wait for the callback when OOBE is finished |
|
| 627 |
+ <-callbackChan |
|
| 628 |
+ |
|
| 629 |
+ ret, _, err = unregisterWaitUntilOOBECompleted.Call(uintptr(callbackHandle)) |
|
| 630 |
+ if ret == 0 {
|
|
| 631 |
+ return fmt.Errorf("failed to unregister OOBEComplete callback. Error: %v", err)
|
|
| 632 |
+ } |
|
| 633 |
+ |
|
| 634 |
+ return nil |
|
| 635 |
+} |