mirror of
https://github.com/containers/podman.git
synced 2025-12-11 01:11:30 +08:00
Pull in updates made to the filters code for images. Filters now perform an AND operation except for th reference filter which does an OR operation for positive case but an AND operation for negative cases. Signed-off-by: Urvashi Mohnani <umohnani@redhat.com>
115 lines
3.8 KiB
Go
115 lines
3.8 KiB
Go
//go:build windows
|
|
|
|
package jobobject
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"sync"
|
|
"unsafe"
|
|
|
|
"github.com/Microsoft/hcsshim/internal/log"
|
|
"github.com/Microsoft/hcsshim/internal/queue"
|
|
"github.com/Microsoft/hcsshim/internal/winapi"
|
|
"github.com/sirupsen/logrus"
|
|
"golang.org/x/sys/windows"
|
|
)
|
|
|
|
var (
|
|
ioInitOnce sync.Once
|
|
initIOErr error
|
|
// Global iocp handle that will be re-used for every job object
|
|
ioCompletionPort windows.Handle
|
|
// Mapping of job handle to queue to place notifications in.
|
|
jobMap sync.Map
|
|
)
|
|
|
|
// MsgAllProcessesExited is a type representing a message that every process in a job has exited.
|
|
type MsgAllProcessesExited struct{}
|
|
|
|
// MsgUnimplemented represents a message that we are aware of, but that isn't implemented currently.
|
|
// This should not be treated as an error.
|
|
type MsgUnimplemented struct{}
|
|
|
|
// pollIOCP polls the io completion port forever.
|
|
func pollIOCP(ctx context.Context, iocpHandle windows.Handle) {
|
|
var (
|
|
overlapped uintptr
|
|
code uint32
|
|
key uintptr
|
|
)
|
|
|
|
for {
|
|
err := windows.GetQueuedCompletionStatus(iocpHandle, &code, &key, (**windows.Overlapped)(unsafe.Pointer(&overlapped)), windows.INFINITE)
|
|
if err != nil {
|
|
log.G(ctx).WithError(err).Error("failed to poll for job object message")
|
|
continue
|
|
}
|
|
if val, ok := jobMap.Load(key); ok {
|
|
msq, ok := val.(*queue.MessageQueue)
|
|
if !ok {
|
|
log.G(ctx).WithField("value", msq).Warn("encountered non queue type in job map")
|
|
continue
|
|
}
|
|
notification, err := parseMessage(code, overlapped)
|
|
if err != nil {
|
|
log.G(ctx).WithFields(logrus.Fields{
|
|
"code": code,
|
|
"overlapped": overlapped,
|
|
}).Warn("failed to parse job object message")
|
|
continue
|
|
}
|
|
if err := msq.Enqueue(notification); errors.Is(err, queue.ErrQueueClosed) {
|
|
// Write will only return an error when the queue is closed.
|
|
// The only time a queue would ever be closed is when we call `Close` on
|
|
// the job it belongs to which also removes it from the jobMap, so something
|
|
// went wrong here. We can't return as this is reading messages for all jobs
|
|
// so just log it and move on.
|
|
log.G(ctx).WithFields(logrus.Fields{
|
|
"code": code,
|
|
"overlapped": overlapped,
|
|
}).Warn("tried to write to a closed queue")
|
|
continue
|
|
}
|
|
} else {
|
|
log.G(ctx).Warn("received a message for a job not present in the mapping")
|
|
}
|
|
}
|
|
}
|
|
|
|
func parseMessage(code uint32, overlapped uintptr) (interface{}, error) {
|
|
// Check code and parse out relevant information related to that notification
|
|
// that we care about. For now all we handle is the message that all processes
|
|
// in the job have exited.
|
|
switch code {
|
|
case winapi.JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO:
|
|
return MsgAllProcessesExited{}, nil
|
|
// Other messages for completeness and a check to make sure that if we fall
|
|
// into the default case that this is a code we don't know how to handle.
|
|
case winapi.JOB_OBJECT_MSG_END_OF_JOB_TIME:
|
|
case winapi.JOB_OBJECT_MSG_END_OF_PROCESS_TIME:
|
|
case winapi.JOB_OBJECT_MSG_ACTIVE_PROCESS_LIMIT:
|
|
case winapi.JOB_OBJECT_MSG_NEW_PROCESS:
|
|
case winapi.JOB_OBJECT_MSG_EXIT_PROCESS:
|
|
case winapi.JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS:
|
|
case winapi.JOB_OBJECT_MSG_PROCESS_MEMORY_LIMIT:
|
|
case winapi.JOB_OBJECT_MSG_JOB_MEMORY_LIMIT:
|
|
case winapi.JOB_OBJECT_MSG_NOTIFICATION_LIMIT:
|
|
default:
|
|
return nil, fmt.Errorf("unknown job notification type: %d", code)
|
|
}
|
|
return MsgUnimplemented{}, nil
|
|
}
|
|
|
|
// Assigns an IO completion port to get notified of events for the registered job
|
|
// object.
|
|
func attachIOCP(job windows.Handle, iocp windows.Handle) error {
|
|
info := winapi.JOBOBJECT_ASSOCIATE_COMPLETION_PORT{
|
|
CompletionKey: job,
|
|
CompletionPort: iocp,
|
|
}
|
|
_, err := windows.SetInformationJobObject(job, windows.JobObjectAssociateCompletionPortInformation, uintptr(unsafe.Pointer(&info)), uint32(unsafe.Sizeof(info)))
|
|
return err
|
|
}
|