k3s/vendor/github.com/Microsoft/hcsshim/internal/hcs/callback.go

161 lines
4.9 KiB
Go
Raw Normal View History

2019-01-12 04:58:27 +00:00
package hcs
import (
2019-09-30 23:25:17 +00:00
"fmt"
2019-01-12 04:58:27 +00:00
"sync"
"syscall"
"github.com/Microsoft/hcsshim/internal/interop"
2019-09-30 23:25:17 +00:00
"github.com/Microsoft/hcsshim/internal/logfields"
"github.com/Microsoft/hcsshim/internal/vmcompute"
2019-01-12 04:58:27 +00:00
"github.com/sirupsen/logrus"
)
var (
nextCallback uintptr
callbackMap = map[uintptr]*notifcationWatcherContext{}
callbackMapLock = sync.RWMutex{}
notificationWatcherCallback = syscall.NewCallback(notificationWatcher)
// Notifications for HCS_SYSTEM handles
2019-07-10 00:29:38 +00:00
hcsNotificationSystemExited hcsNotification = 0x00000001
hcsNotificationSystemCreateCompleted hcsNotification = 0x00000002
hcsNotificationSystemStartCompleted hcsNotification = 0x00000003
hcsNotificationSystemPauseCompleted hcsNotification = 0x00000004
hcsNotificationSystemResumeCompleted hcsNotification = 0x00000005
hcsNotificationSystemCrashReport hcsNotification = 0x00000006
hcsNotificationSystemSiloJobCreated hcsNotification = 0x00000007
hcsNotificationSystemSaveCompleted hcsNotification = 0x00000008
hcsNotificationSystemRdpEnhancedModeStateChanged hcsNotification = 0x00000009
hcsNotificationSystemShutdownFailed hcsNotification = 0x0000000A
hcsNotificationSystemGetPropertiesCompleted hcsNotification = 0x0000000B
hcsNotificationSystemModifyCompleted hcsNotification = 0x0000000C
hcsNotificationSystemCrashInitiated hcsNotification = 0x0000000D
hcsNotificationSystemGuestConnectionClosed hcsNotification = 0x0000000E
2019-01-12 04:58:27 +00:00
// Notifications for HCS_PROCESS handles
hcsNotificationProcessExited hcsNotification = 0x00010000
// Common notifications
hcsNotificationInvalid hcsNotification = 0x00000000
hcsNotificationServiceDisconnect hcsNotification = 0x01000000
)
type hcsNotification uint32
2019-09-30 23:25:17 +00:00
func (hn hcsNotification) String() string {
switch hn {
case hcsNotificationSystemExited:
return "SystemExited"
case hcsNotificationSystemCreateCompleted:
return "SystemCreateCompleted"
case hcsNotificationSystemStartCompleted:
return "SystemStartCompleted"
case hcsNotificationSystemPauseCompleted:
return "SystemPauseCompleted"
case hcsNotificationSystemResumeCompleted:
return "SystemResumeCompleted"
case hcsNotificationSystemCrashReport:
return "SystemCrashReport"
case hcsNotificationSystemSiloJobCreated:
return "SystemSiloJobCreated"
case hcsNotificationSystemSaveCompleted:
return "SystemSaveCompleted"
case hcsNotificationSystemRdpEnhancedModeStateChanged:
return "SystemRdpEnhancedModeStateChanged"
case hcsNotificationSystemShutdownFailed:
return "SystemShutdownFailed"
case hcsNotificationSystemGetPropertiesCompleted:
return "SystemGetPropertiesCompleted"
case hcsNotificationSystemModifyCompleted:
return "SystemModifyCompleted"
case hcsNotificationSystemCrashInitiated:
return "SystemCrashInitiated"
case hcsNotificationSystemGuestConnectionClosed:
return "SystemGuestConnectionClosed"
case hcsNotificationProcessExited:
return "ProcessExited"
case hcsNotificationInvalid:
return "Invalid"
case hcsNotificationServiceDisconnect:
return "ServiceDisconnect"
default:
return fmt.Sprintf("Unknown: %d", hn)
}
}
2019-01-12 04:58:27 +00:00
type notificationChannel chan error
type notifcationWatcherContext struct {
channels notificationChannels
2019-09-30 23:25:17 +00:00
handle vmcompute.HcsCallback
systemID string
processID int
2019-01-12 04:58:27 +00:00
}
type notificationChannels map[hcsNotification]notificationChannel
2019-09-30 23:25:17 +00:00
func newSystemChannels() notificationChannels {
2019-01-12 04:58:27 +00:00
channels := make(notificationChannels)
2019-09-30 23:25:17 +00:00
for _, notif := range []hcsNotification{
hcsNotificationServiceDisconnect,
hcsNotificationSystemExited,
hcsNotificationSystemCreateCompleted,
hcsNotificationSystemStartCompleted,
hcsNotificationSystemPauseCompleted,
hcsNotificationSystemResumeCompleted,
} {
channels[notif] = make(notificationChannel, 1)
}
return channels
}
2019-01-12 04:58:27 +00:00
2019-09-30 23:25:17 +00:00
func newProcessChannels() notificationChannels {
channels := make(notificationChannels)
for _, notif := range []hcsNotification{
hcsNotificationServiceDisconnect,
hcsNotificationProcessExited,
} {
channels[notif] = make(notificationChannel, 1)
}
2019-01-12 04:58:27 +00:00
return channels
}
2019-07-10 00:29:38 +00:00
2019-01-12 04:58:27 +00:00
func closeChannels(channels notificationChannels) {
2019-07-10 00:29:38 +00:00
for _, c := range channels {
close(c)
}
2019-01-12 04:58:27 +00:00
}
func notificationWatcher(notificationType hcsNotification, callbackNumber uintptr, notificationStatus uintptr, notificationData *uint16) uintptr {
var result error
if int32(notificationStatus) < 0 {
result = interop.Win32FromHresult(notificationStatus)
}
callbackMapLock.RLock()
context := callbackMap[callbackNumber]
callbackMapLock.RUnlock()
if context == nil {
return 0
}
2019-09-30 23:25:17 +00:00
log := logrus.WithFields(logrus.Fields{
"notification-type": notificationType.String(),
"system-id": context.systemID,
})
if context.processID != 0 {
log.Data[logfields.ProcessID] = context.processID
}
log.Debug("HCS notification")
2019-01-12 04:58:27 +00:00
if channel, ok := context.channels[notificationType]; ok {
channel <- result
}
return 0
}