...

Source file src/github.com/Microsoft/hcsshim/internal/hcs/callback.go

Documentation: github.com/Microsoft/hcsshim/internal/hcs

     1  //go:build windows
     2  
     3  package hcs
     4  
     5  import (
     6  	"fmt"
     7  	"sync"
     8  	"syscall"
     9  
    10  	"github.com/Microsoft/hcsshim/internal/interop"
    11  	"github.com/Microsoft/hcsshim/internal/logfields"
    12  	"github.com/Microsoft/hcsshim/internal/vmcompute"
    13  	"github.com/sirupsen/logrus"
    14  )
    15  
    16  var (
    17  	nextCallback    uintptr
    18  	callbackMap     = map[uintptr]*notificationWatcherContext{}
    19  	callbackMapLock = sync.RWMutex{}
    20  
    21  	notificationWatcherCallback = syscall.NewCallback(notificationWatcher)
    22  
    23  	// Notifications for HCS_SYSTEM handles
    24  	hcsNotificationSystemExited                      hcsNotification = 0x00000001
    25  	hcsNotificationSystemCreateCompleted             hcsNotification = 0x00000002
    26  	hcsNotificationSystemStartCompleted              hcsNotification = 0x00000003
    27  	hcsNotificationSystemPauseCompleted              hcsNotification = 0x00000004
    28  	hcsNotificationSystemResumeCompleted             hcsNotification = 0x00000005
    29  	hcsNotificationSystemCrashReport                 hcsNotification = 0x00000006
    30  	hcsNotificationSystemSiloJobCreated              hcsNotification = 0x00000007
    31  	hcsNotificationSystemSaveCompleted               hcsNotification = 0x00000008
    32  	hcsNotificationSystemRdpEnhancedModeStateChanged hcsNotification = 0x00000009
    33  	hcsNotificationSystemShutdownFailed              hcsNotification = 0x0000000A
    34  	hcsNotificationSystemGetPropertiesCompleted      hcsNotification = 0x0000000B
    35  	hcsNotificationSystemModifyCompleted             hcsNotification = 0x0000000C
    36  	hcsNotificationSystemCrashInitiated              hcsNotification = 0x0000000D
    37  	hcsNotificationSystemGuestConnectionClosed       hcsNotification = 0x0000000E
    38  
    39  	// Notifications for HCS_PROCESS handles
    40  	hcsNotificationProcessExited hcsNotification = 0x00010000
    41  
    42  	// Common notifications
    43  	hcsNotificationInvalid           hcsNotification = 0x00000000
    44  	hcsNotificationServiceDisconnect hcsNotification = 0x01000000
    45  )
    46  
    47  type hcsNotification uint32
    48  
    49  func (hn hcsNotification) String() string {
    50  	switch hn {
    51  	case hcsNotificationSystemExited:
    52  		return "SystemExited"
    53  	case hcsNotificationSystemCreateCompleted:
    54  		return "SystemCreateCompleted"
    55  	case hcsNotificationSystemStartCompleted:
    56  		return "SystemStartCompleted"
    57  	case hcsNotificationSystemPauseCompleted:
    58  		return "SystemPauseCompleted"
    59  	case hcsNotificationSystemResumeCompleted:
    60  		return "SystemResumeCompleted"
    61  	case hcsNotificationSystemCrashReport:
    62  		return "SystemCrashReport"
    63  	case hcsNotificationSystemSiloJobCreated:
    64  		return "SystemSiloJobCreated"
    65  	case hcsNotificationSystemSaveCompleted:
    66  		return "SystemSaveCompleted"
    67  	case hcsNotificationSystemRdpEnhancedModeStateChanged:
    68  		return "SystemRdpEnhancedModeStateChanged"
    69  	case hcsNotificationSystemShutdownFailed:
    70  		return "SystemShutdownFailed"
    71  	case hcsNotificationSystemGetPropertiesCompleted:
    72  		return "SystemGetPropertiesCompleted"
    73  	case hcsNotificationSystemModifyCompleted:
    74  		return "SystemModifyCompleted"
    75  	case hcsNotificationSystemCrashInitiated:
    76  		return "SystemCrashInitiated"
    77  	case hcsNotificationSystemGuestConnectionClosed:
    78  		return "SystemGuestConnectionClosed"
    79  	case hcsNotificationProcessExited:
    80  		return "ProcessExited"
    81  	case hcsNotificationInvalid:
    82  		return "Invalid"
    83  	case hcsNotificationServiceDisconnect:
    84  		return "ServiceDisconnect"
    85  	default:
    86  		return fmt.Sprintf("Unknown: %d", hn)
    87  	}
    88  }
    89  
    90  type notificationChannel chan error
    91  
    92  type notificationWatcherContext struct {
    93  	channels notificationChannels
    94  	handle   vmcompute.HcsCallback
    95  
    96  	systemID  string
    97  	processID int
    98  }
    99  
   100  type notificationChannels map[hcsNotification]notificationChannel
   101  
   102  func newSystemChannels() notificationChannels {
   103  	channels := make(notificationChannels)
   104  	for _, notif := range []hcsNotification{
   105  		hcsNotificationServiceDisconnect,
   106  		hcsNotificationSystemExited,
   107  		hcsNotificationSystemCreateCompleted,
   108  		hcsNotificationSystemStartCompleted,
   109  		hcsNotificationSystemPauseCompleted,
   110  		hcsNotificationSystemResumeCompleted,
   111  		hcsNotificationSystemSaveCompleted,
   112  	} {
   113  		channels[notif] = make(notificationChannel, 1)
   114  	}
   115  	return channels
   116  }
   117  
   118  func newProcessChannels() notificationChannels {
   119  	channels := make(notificationChannels)
   120  	for _, notif := range []hcsNotification{
   121  		hcsNotificationServiceDisconnect,
   122  		hcsNotificationProcessExited,
   123  	} {
   124  		channels[notif] = make(notificationChannel, 1)
   125  	}
   126  	return channels
   127  }
   128  
   129  func closeChannels(channels notificationChannels) {
   130  	for _, c := range channels {
   131  		close(c)
   132  	}
   133  }
   134  
   135  func notificationWatcher(notificationType hcsNotification, callbackNumber uintptr, notificationStatus uintptr, notificationData *uint16) uintptr {
   136  	var result error
   137  	if int32(notificationStatus) < 0 {
   138  		result = interop.Win32FromHresult(notificationStatus)
   139  	}
   140  
   141  	callbackMapLock.RLock()
   142  	context := callbackMap[callbackNumber]
   143  	callbackMapLock.RUnlock()
   144  
   145  	if context == nil {
   146  		return 0
   147  	}
   148  
   149  	log := logrus.WithFields(logrus.Fields{
   150  		"notification-type": notificationType.String(),
   151  		"system-id":         context.systemID,
   152  	})
   153  	if context.processID != 0 {
   154  		log.Data[logfields.ProcessID] = context.processID
   155  	}
   156  	log.Debug("HCS notification")
   157  
   158  	if channel, ok := context.channels[notificationType]; ok {
   159  		channel <- result
   160  	}
   161  
   162  	return 0
   163  }
   164  

View as plain text