callback.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package hcs
  2. import (
  3. "sync"
  4. "syscall"
  5. "github.com/Microsoft/hcsshim/internal/interop"
  6. "github.com/sirupsen/logrus"
  7. )
  8. var (
  9. nextCallback uintptr
  10. callbackMap = map[uintptr]*notifcationWatcherContext{}
  11. callbackMapLock = sync.RWMutex{}
  12. notificationWatcherCallback = syscall.NewCallback(notificationWatcher)
  13. // Notifications for HCS_SYSTEM handles
  14. hcsNotificationSystemExited hcsNotification = 0x00000001
  15. hcsNotificationSystemCreateCompleted hcsNotification = 0x00000002
  16. hcsNotificationSystemStartCompleted hcsNotification = 0x00000003
  17. hcsNotificationSystemPauseCompleted hcsNotification = 0x00000004
  18. hcsNotificationSystemResumeCompleted hcsNotification = 0x00000005
  19. hcsNotificationSystemCrashReport hcsNotification = 0x00000006
  20. hcsNotificationSystemSiloJobCreated hcsNotification = 0x00000007
  21. hcsNotificationSystemSaveCompleted hcsNotification = 0x00000008
  22. hcsNotificationSystemRdpEnhancedModeStateChanged hcsNotification = 0x00000009
  23. hcsNotificationSystemShutdownFailed hcsNotification = 0x0000000A
  24. hcsNotificationSystemGetPropertiesCompleted hcsNotification = 0x0000000B
  25. hcsNotificationSystemModifyCompleted hcsNotification = 0x0000000C
  26. hcsNotificationSystemCrashInitiated hcsNotification = 0x0000000D
  27. hcsNotificationSystemGuestConnectionClosed hcsNotification = 0x0000000E
  28. // Notifications for HCS_PROCESS handles
  29. hcsNotificationProcessExited hcsNotification = 0x00010000
  30. // Common notifications
  31. hcsNotificationInvalid hcsNotification = 0x00000000
  32. hcsNotificationServiceDisconnect hcsNotification = 0x01000000
  33. )
  34. type hcsNotification uint32
  35. type notificationChannel chan error
  36. type notifcationWatcherContext struct {
  37. channels notificationChannels
  38. handle hcsCallback
  39. }
  40. type notificationChannels map[hcsNotification]notificationChannel
  41. func newChannels() notificationChannels {
  42. channels := make(notificationChannels)
  43. channels[hcsNotificationSystemExited] = make(notificationChannel, 1)
  44. channels[hcsNotificationSystemCreateCompleted] = make(notificationChannel, 1)
  45. channels[hcsNotificationSystemStartCompleted] = make(notificationChannel, 1)
  46. channels[hcsNotificationSystemPauseCompleted] = make(notificationChannel, 1)
  47. channels[hcsNotificationSystemResumeCompleted] = make(notificationChannel, 1)
  48. channels[hcsNotificationProcessExited] = make(notificationChannel, 1)
  49. channels[hcsNotificationServiceDisconnect] = make(notificationChannel, 1)
  50. channels[hcsNotificationSystemCrashReport] = make(notificationChannel, 1)
  51. channels[hcsNotificationSystemSiloJobCreated] = make(notificationChannel, 1)
  52. channels[hcsNotificationSystemSaveCompleted] = make(notificationChannel, 1)
  53. channels[hcsNotificationSystemRdpEnhancedModeStateChanged] = make(notificationChannel, 1)
  54. channels[hcsNotificationSystemShutdownFailed] = make(notificationChannel, 1)
  55. channels[hcsNotificationSystemGetPropertiesCompleted] = make(notificationChannel, 1)
  56. channels[hcsNotificationSystemModifyCompleted] = make(notificationChannel, 1)
  57. channels[hcsNotificationSystemCrashInitiated] = make(notificationChannel, 1)
  58. channels[hcsNotificationSystemGuestConnectionClosed] = make(notificationChannel, 1)
  59. return channels
  60. }
  61. func closeChannels(channels notificationChannels) {
  62. for _, c := range channels {
  63. close(c)
  64. }
  65. }
  66. func notificationWatcher(notificationType hcsNotification, callbackNumber uintptr, notificationStatus uintptr, notificationData *uint16) uintptr {
  67. var result error
  68. if int32(notificationStatus) < 0 {
  69. result = interop.Win32FromHresult(notificationStatus)
  70. }
  71. callbackMapLock.RLock()
  72. context := callbackMap[callbackNumber]
  73. callbackMapLock.RUnlock()
  74. if context == nil {
  75. return 0
  76. }
  77. if channel, ok := context.channels[notificationType]; ok {
  78. channel <- result
  79. } else {
  80. logrus.WithFields(logrus.Fields{
  81. "notification-type": notificationType,
  82. }).Warn("Received a callback of an unsupported type")
  83. }
  84. return 0
  85. }