mirror of
				https://github.com/containers/podman.git
				synced 2025-10-31 18:08:51 +08:00 
			
		
		
		
	Bump to Buildah v1.11.5
Bump to Buildah v1.11.5. Most notably changes to the podman build `--pull` functionality. `--pull=true` and `--pull=false` now work as Docker does, `--pull-never` added to supply the functionality of the old `--pull=false`. Signed-off-by: TomSweeneyRedHat <tsweeney@redhat.com>
This commit is contained in:
		
							
								
								
									
										419
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										419
									
								
								vendor/github.com/Microsoft/hcsshim/internal/hcs/process.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @ -1,48 +1,45 @@ | ||||
| package hcs | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"encoding/json" | ||||
| 	"io" | ||||
| 	"sync" | ||||
| 	"syscall" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/Microsoft/hcsshim/internal/guestrequest" | ||||
| 	"github.com/Microsoft/hcsshim/internal/interop" | ||||
| 	"github.com/Microsoft/hcsshim/internal/logfields" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"github.com/Microsoft/hcsshim/internal/log" | ||||
| 	"github.com/Microsoft/hcsshim/internal/oc" | ||||
| 	"github.com/Microsoft/hcsshim/internal/vmcompute" | ||||
| 	"go.opencensus.io/trace" | ||||
| ) | ||||
|  | ||||
| // ContainerError is an error encountered in HCS | ||||
| type Process struct { | ||||
| 	handleLock     sync.RWMutex | ||||
| 	handle         hcsProcess | ||||
| 	handle         vmcompute.HcsProcess | ||||
| 	processID      int | ||||
| 	system         *System | ||||
| 	cachedPipes    *cachedPipes | ||||
| 	stdin          io.WriteCloser | ||||
| 	stdout         io.ReadCloser | ||||
| 	stderr         io.ReadCloser | ||||
| 	callbackNumber uintptr | ||||
|  | ||||
| 	logctx logrus.Fields | ||||
| 	closedWaitOnce sync.Once | ||||
| 	waitBlock      chan struct{} | ||||
| 	exitCode       int | ||||
| 	waitError      error | ||||
| } | ||||
|  | ||||
| func newProcess(process hcsProcess, processID int, computeSystem *System) *Process { | ||||
| func newProcess(process vmcompute.HcsProcess, processID int, computeSystem *System) *Process { | ||||
| 	return &Process{ | ||||
| 		handle:    process, | ||||
| 		processID: processID, | ||||
| 		system:    computeSystem, | ||||
| 		logctx: logrus.Fields{ | ||||
| 			logfields.ContainerID: computeSystem.ID(), | ||||
| 			logfields.ProcessID:   processID, | ||||
| 		}, | ||||
| 		waitBlock: make(chan struct{}), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type cachedPipes struct { | ||||
| 	stdIn  syscall.Handle | ||||
| 	stdOut syscall.Handle | ||||
| 	stdErr syscall.Handle | ||||
| } | ||||
|  | ||||
| type processModifyRequest struct { | ||||
| 	Operation   string | ||||
| 	ConsoleSize *consoleSize `json:",omitempty"` | ||||
| @ -58,7 +55,7 @@ type closeHandle struct { | ||||
| 	Handle string | ||||
| } | ||||
|  | ||||
| type ProcessStatus struct { | ||||
| type processStatus struct { | ||||
| 	ProcessID      uint32 | ||||
| 	Exited         bool | ||||
| 	ExitCode       uint32 | ||||
| @ -86,120 +83,153 @@ func (process *Process) SystemID() string { | ||||
| 	return process.system.ID() | ||||
| } | ||||
|  | ||||
| func (process *Process) logOperationBegin(operation string) { | ||||
| 	logOperationBegin( | ||||
| 		process.logctx, | ||||
| 		operation+" - Begin Operation") | ||||
| } | ||||
|  | ||||
| func (process *Process) logOperationEnd(operation string, err error) { | ||||
| 	var result string | ||||
| 	if err == nil { | ||||
| 		result = "Success" | ||||
| 	} else { | ||||
| 		result = "Error" | ||||
| func (process *Process) processSignalResult(ctx context.Context, err error) (bool, error) { | ||||
| 	switch err { | ||||
| 	case nil: | ||||
| 		return true, nil | ||||
| 	case ErrVmcomputeOperationInvalidState, ErrComputeSystemDoesNotExist, ErrElementNotFound: | ||||
| 		select { | ||||
| 		case <-process.waitBlock: | ||||
| 			// The process exit notification has already arrived. | ||||
| 		default: | ||||
| 			// The process should be gone, but we have not received the notification. | ||||
| 			// After a second, force unblock the process wait to work around a possible | ||||
| 			// deadlock in the HCS. | ||||
| 			go func() { | ||||
| 				time.Sleep(time.Second) | ||||
| 				process.closedWaitOnce.Do(func() { | ||||
| 					log.G(ctx).WithError(err).Warn("force unblocking process waits") | ||||
| 					process.exitCode = -1 | ||||
| 					process.waitError = err | ||||
| 					close(process.waitBlock) | ||||
| 				}) | ||||
| 			}() | ||||
| 		} | ||||
| 		return false, nil | ||||
| 	default: | ||||
| 		return false, err | ||||
| 	} | ||||
|  | ||||
| 	logOperationEnd( | ||||
| 		process.logctx, | ||||
| 		operation+" - End Operation - "+result, | ||||
| 		err) | ||||
| } | ||||
|  | ||||
| // Signal signals the process with `options`. | ||||
| func (process *Process) Signal(options guestrequest.SignalProcessOptions) (err error) { | ||||
| // | ||||
| // For LCOW `guestrequest.SignalProcessOptionsLCOW`. | ||||
| // | ||||
| // For WCOW `guestrequest.SignalProcessOptionsWCOW`. | ||||
| func (process *Process) Signal(ctx context.Context, options interface{}) (bool, error) { | ||||
| 	process.handleLock.RLock() | ||||
| 	defer process.handleLock.RUnlock() | ||||
|  | ||||
| 	operation := "hcsshim::Process::Signal" | ||||
| 	process.logOperationBegin(operation) | ||||
| 	defer func() { process.logOperationEnd(operation, err) }() | ||||
|  | ||||
| 	if process.handle == 0 { | ||||
| 		return makeProcessError(process, operation, ErrAlreadyClosed, nil) | ||||
| 		return false, makeProcessError(process, operation, ErrAlreadyClosed, nil) | ||||
| 	} | ||||
|  | ||||
| 	optionsb, err := json.Marshal(options) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 		return false, err | ||||
| 	} | ||||
|  | ||||
| 	optionsStr := string(optionsb) | ||||
|  | ||||
| 	var resultp *uint16 | ||||
| 	syscallWatcher(process.logctx, func() { | ||||
| 		err = hcsSignalProcess(process.handle, optionsStr, &resultp) | ||||
| 	}) | ||||
| 	events := processHcsResult(resultp) | ||||
| 	resultJSON, err := vmcompute.HcsSignalProcess(ctx, process.handle, string(optionsb)) | ||||
| 	events := processHcsResult(ctx, resultJSON) | ||||
| 	delivered, err := process.processSignalResult(ctx, err) | ||||
| 	if err != nil { | ||||
| 		return makeProcessError(process, operation, err, events) | ||||
| 		err = makeProcessError(process, operation, err, events) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| 	return delivered, err | ||||
| } | ||||
|  | ||||
| // Kill signals the process to terminate but does not wait for it to finish terminating. | ||||
| func (process *Process) Kill() (err error) { | ||||
| func (process *Process) Kill(ctx context.Context) (bool, error) { | ||||
| 	process.handleLock.RLock() | ||||
| 	defer process.handleLock.RUnlock() | ||||
|  | ||||
| 	operation := "hcsshim::Process::Kill" | ||||
| 	process.logOperationBegin(operation) | ||||
| 	defer func() { process.logOperationEnd(operation, err) }() | ||||
|  | ||||
| 	if process.handle == 0 { | ||||
| 		return makeProcessError(process, operation, ErrAlreadyClosed, nil) | ||||
| 		return false, makeProcessError(process, operation, ErrAlreadyClosed, nil) | ||||
| 	} | ||||
|  | ||||
| 	var resultp *uint16 | ||||
| 	syscallWatcher(process.logctx, func() { | ||||
| 		err = hcsTerminateProcess(process.handle, &resultp) | ||||
| 	resultJSON, err := vmcompute.HcsTerminateProcess(ctx, process.handle) | ||||
| 	events := processHcsResult(ctx, resultJSON) | ||||
| 	delivered, err := process.processSignalResult(ctx, err) | ||||
| 	if err != nil { | ||||
| 		err = makeProcessError(process, operation, err, events) | ||||
| 	} | ||||
| 	return delivered, err | ||||
| } | ||||
|  | ||||
| // waitBackground waits for the process exit notification. Once received sets | ||||
| // `process.waitError` (if any) and unblocks all `Wait` calls. | ||||
| // | ||||
| // This MUST be called exactly once per `process.handle` but `Wait` is safe to | ||||
| // call multiple times. | ||||
| func (process *Process) waitBackground() { | ||||
| 	operation := "hcsshim::Process::waitBackground" | ||||
| 	ctx, span := trace.StartSpan(context.Background(), operation) | ||||
| 	defer span.End() | ||||
| 	span.AddAttributes( | ||||
| 		trace.StringAttribute("cid", process.SystemID()), | ||||
| 		trace.Int64Attribute("pid", int64(process.processID))) | ||||
|  | ||||
| 	var ( | ||||
| 		err      error | ||||
| 		exitCode = -1 | ||||
| 	) | ||||
|  | ||||
| 	err = waitForNotification(ctx, process.callbackNumber, hcsNotificationProcessExited, nil) | ||||
| 	if err != nil { | ||||
| 		err = makeProcessError(process, operation, err, nil) | ||||
| 		log.G(ctx).WithError(err).Error("failed wait") | ||||
| 	} else { | ||||
| 		process.handleLock.RLock() | ||||
| 		defer process.handleLock.RUnlock() | ||||
|  | ||||
| 		// Make sure we didnt race with Close() here | ||||
| 		if process.handle != 0 { | ||||
| 			propertiesJSON, resultJSON, err := vmcompute.HcsGetProcessProperties(ctx, process.handle) | ||||
| 			events := processHcsResult(ctx, resultJSON) | ||||
| 			if err != nil { | ||||
| 				err = makeProcessError(process, operation, err, events) | ||||
| 			} else { | ||||
| 				properties := &processStatus{} | ||||
| 				err = json.Unmarshal([]byte(propertiesJSON), properties) | ||||
| 				if err != nil { | ||||
| 					err = makeProcessError(process, operation, err, nil) | ||||
| 				} else { | ||||
| 					if properties.LastWaitResult != 0 { | ||||
| 						log.G(ctx).WithField("wait-result", properties.LastWaitResult).Warning("non-zero last wait result") | ||||
| 					} else { | ||||
| 						exitCode = int(properties.ExitCode) | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	log.G(ctx).WithField("exitCode", exitCode).Debug("process exited") | ||||
|  | ||||
| 	process.closedWaitOnce.Do(func() { | ||||
| 		process.exitCode = exitCode | ||||
| 		process.waitError = err | ||||
| 		close(process.waitBlock) | ||||
| 	}) | ||||
| 	events := processHcsResult(resultp) | ||||
| 	if err != nil { | ||||
| 		return makeProcessError(process, operation, err, events) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| 	oc.SetSpanStatus(span, err) | ||||
| } | ||||
|  | ||||
| // Wait waits for the process to exit. | ||||
| func (process *Process) Wait() (err error) { | ||||
| 	operation := "hcsshim::Process::Wait" | ||||
| 	process.logOperationBegin(operation) | ||||
| 	defer func() { process.logOperationEnd(operation, err) }() | ||||
|  | ||||
| 	err = waitForNotification(process.callbackNumber, hcsNotificationProcessExited, nil) | ||||
| 	if err != nil { | ||||
| 		return makeProcessError(process, operation, err, nil) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // WaitTimeout waits for the process to exit or the duration to elapse. It returns | ||||
| // false if timeout occurs. | ||||
| func (process *Process) WaitTimeout(timeout time.Duration) (err error) { | ||||
| 	operation := "hcssshim::Process::WaitTimeout" | ||||
| 	process.logOperationBegin(operation) | ||||
| 	defer func() { process.logOperationEnd(operation, err) }() | ||||
|  | ||||
| 	err = waitForNotification(process.callbackNumber, hcsNotificationProcessExited, &timeout) | ||||
| 	if err != nil { | ||||
| 		return makeProcessError(process, operation, err, nil) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| // Wait waits for the process to exit. If the process has already exited returns | ||||
| // the pervious error (if any). | ||||
| func (process *Process) Wait() error { | ||||
| 	<-process.waitBlock | ||||
| 	return process.waitError | ||||
| } | ||||
|  | ||||
| // ResizeConsole resizes the console of the process. | ||||
| func (process *Process) ResizeConsole(width, height uint16) (err error) { | ||||
| func (process *Process) ResizeConsole(ctx context.Context, width, height uint16) error { | ||||
| 	process.handleLock.RLock() | ||||
| 	defer process.handleLock.RUnlock() | ||||
|  | ||||
| 	operation := "hcsshim::Process::ResizeConsole" | ||||
| 	process.logOperationBegin(operation) | ||||
| 	defer func() { process.logOperationEnd(operation, err) }() | ||||
|  | ||||
| 	if process.handle == 0 { | ||||
| 		return makeProcessError(process, operation, ErrAlreadyClosed, nil) | ||||
| @ -218,11 +248,8 @@ func (process *Process) ResizeConsole(width, height uint16) (err error) { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	modifyRequestStr := string(modifyRequestb) | ||||
|  | ||||
| 	var resultp *uint16 | ||||
| 	err = hcsModifyProcess(process.handle, modifyRequestStr, &resultp) | ||||
| 	events := processHcsResult(resultp) | ||||
| 	resultJSON, err := vmcompute.HcsModifyProcess(ctx, process.handle, string(modifyRequestb)) | ||||
| 	events := processHcsResult(ctx, resultJSON) | ||||
| 	if err != nil { | ||||
| 		return makeProcessError(process, operation, err, events) | ||||
| 	} | ||||
| @ -230,104 +257,46 @@ func (process *Process) ResizeConsole(width, height uint16) (err error) { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (process *Process) Properties() (_ *ProcessStatus, err error) { | ||||
| 	process.handleLock.RLock() | ||||
| 	defer process.handleLock.RUnlock() | ||||
|  | ||||
| 	operation := "hcsshim::Process::Properties" | ||||
| 	process.logOperationBegin(operation) | ||||
| 	defer func() { process.logOperationEnd(operation, err) }() | ||||
|  | ||||
| 	if process.handle == 0 { | ||||
| 		return nil, makeProcessError(process, operation, ErrAlreadyClosed, nil) | ||||
| 	} | ||||
|  | ||||
| 	var ( | ||||
| 		resultp     *uint16 | ||||
| 		propertiesp *uint16 | ||||
| 	) | ||||
| 	syscallWatcher(process.logctx, func() { | ||||
| 		err = hcsGetProcessProperties(process.handle, &propertiesp, &resultp) | ||||
| 	}) | ||||
| 	events := processHcsResult(resultp) | ||||
| 	if err != nil { | ||||
| 		return nil, makeProcessError(process, operation, err, events) | ||||
| 	} | ||||
|  | ||||
| 	if propertiesp == nil { | ||||
| 		return nil, ErrUnexpectedValue | ||||
| 	} | ||||
| 	propertiesRaw := interop.ConvertAndFreeCoTaskMemBytes(propertiesp) | ||||
|  | ||||
| 	properties := &ProcessStatus{} | ||||
| 	if err := json.Unmarshal(propertiesRaw, properties); err != nil { | ||||
| 		return nil, makeProcessError(process, operation, err, nil) | ||||
| 	} | ||||
|  | ||||
| 	return properties, nil | ||||
| } | ||||
|  | ||||
| // ExitCode returns the exit code of the process. The process must have | ||||
| // already terminated. | ||||
| func (process *Process) ExitCode() (_ int, err error) { | ||||
| 	operation := "hcsshim::Process::ExitCode" | ||||
| 	process.logOperationBegin(operation) | ||||
| 	defer func() { process.logOperationEnd(operation, err) }() | ||||
|  | ||||
| 	properties, err := process.Properties() | ||||
| 	if err != nil { | ||||
| 		return 0, makeProcessError(process, operation, err, nil) | ||||
| func (process *Process) ExitCode() (int, error) { | ||||
| 	select { | ||||
| 	case <-process.waitBlock: | ||||
| 		if process.waitError != nil { | ||||
| 			return -1, process.waitError | ||||
| 		} | ||||
| 		return process.exitCode, nil | ||||
| 	default: | ||||
| 		return -1, makeProcessError(process, "hcsshim::Process::ExitCode", ErrInvalidProcessState, nil) | ||||
| 	} | ||||
|  | ||||
| 	if properties.Exited == false { | ||||
| 		return 0, makeProcessError(process, operation, ErrInvalidProcessState, nil) | ||||
| 	} | ||||
|  | ||||
| 	if properties.LastWaitResult != 0 { | ||||
| 		return 0, makeProcessError(process, operation, syscall.Errno(properties.LastWaitResult), nil) | ||||
| 	} | ||||
|  | ||||
| 	return int(properties.ExitCode), nil | ||||
| } | ||||
|  | ||||
| // Stdio returns the stdin, stdout, and stderr pipes, respectively. Closing | ||||
| // these pipes does not close the underlying pipes; it should be possible to | ||||
| // call this multiple times to get multiple interfaces. | ||||
| func (process *Process) Stdio() (_ io.WriteCloser, _ io.ReadCloser, _ io.ReadCloser, err error) { | ||||
| // StdioLegacy returns the stdin, stdout, and stderr pipes, respectively. Closing | ||||
| // these pipes does not close the underlying pipes; but this function can only | ||||
| // be called once on each Process. | ||||
| func (process *Process) StdioLegacy() (_ io.WriteCloser, _ io.ReadCloser, _ io.ReadCloser, err error) { | ||||
| 	operation := "hcsshim::Process::StdioLegacy" | ||||
| 	ctx, span := trace.StartSpan(context.Background(), operation) | ||||
| 	defer span.End() | ||||
| 	defer func() { oc.SetSpanStatus(span, err) }() | ||||
| 	span.AddAttributes( | ||||
| 		trace.StringAttribute("cid", process.SystemID()), | ||||
| 		trace.Int64Attribute("pid", int64(process.processID))) | ||||
|  | ||||
| 	process.handleLock.RLock() | ||||
| 	defer process.handleLock.RUnlock() | ||||
|  | ||||
| 	operation := "hcsshim::Process::Stdio" | ||||
| 	process.logOperationBegin(operation) | ||||
| 	defer func() { process.logOperationEnd(operation, err) }() | ||||
|  | ||||
| 	if process.handle == 0 { | ||||
| 		return nil, nil, nil, makeProcessError(process, operation, ErrAlreadyClosed, nil) | ||||
| 	} | ||||
|  | ||||
| 	var stdIn, stdOut, stdErr syscall.Handle | ||||
|  | ||||
| 	if process.cachedPipes == nil { | ||||
| 		var ( | ||||
| 			processInfo hcsProcessInformation | ||||
| 			resultp     *uint16 | ||||
| 		) | ||||
| 		err = hcsGetProcessInfo(process.handle, &processInfo, &resultp) | ||||
| 		events := processHcsResult(resultp) | ||||
| 		if err != nil { | ||||
| 			return nil, nil, nil, makeProcessError(process, operation, err, events) | ||||
| 		} | ||||
|  | ||||
| 		stdIn, stdOut, stdErr = processInfo.StdInput, processInfo.StdOutput, processInfo.StdError | ||||
| 	} else { | ||||
| 		// Use cached pipes | ||||
| 		stdIn, stdOut, stdErr = process.cachedPipes.stdIn, process.cachedPipes.stdOut, process.cachedPipes.stdErr | ||||
|  | ||||
| 		// Invalidate the cache | ||||
| 		process.cachedPipes = nil | ||||
| 	processInfo, resultJSON, err := vmcompute.HcsGetProcessInfo(ctx, process.handle) | ||||
| 	events := processHcsResult(ctx, resultJSON) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, nil, makeProcessError(process, operation, err, events) | ||||
| 	} | ||||
|  | ||||
| 	pipes, err := makeOpenFiles([]syscall.Handle{stdIn, stdOut, stdErr}) | ||||
| 	pipes, err := makeOpenFiles([]syscall.Handle{processInfo.StdInput, processInfo.StdOutput, processInfo.StdError}) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, nil, makeProcessError(process, operation, err, nil) | ||||
| 	} | ||||
| @ -335,15 +304,19 @@ func (process *Process) Stdio() (_ io.WriteCloser, _ io.ReadCloser, _ io.ReadClo | ||||
| 	return pipes[0], pipes[1], pipes[2], nil | ||||
| } | ||||
|  | ||||
| // Stdio returns the stdin, stdout, and stderr pipes, respectively. | ||||
| // To close them, close the process handle. | ||||
| func (process *Process) Stdio() (stdin io.Writer, stdout, stderr io.Reader) { | ||||
| 	return process.stdin, process.stdout, process.stderr | ||||
| } | ||||
|  | ||||
| // CloseStdin closes the write side of the stdin pipe so that the process is | ||||
| // notified on the read side that there is no more data in stdin. | ||||
| func (process *Process) CloseStdin() (err error) { | ||||
| func (process *Process) CloseStdin(ctx context.Context) error { | ||||
| 	process.handleLock.RLock() | ||||
| 	defer process.handleLock.RUnlock() | ||||
|  | ||||
| 	operation := "hcsshim::Process::CloseStdin" | ||||
| 	process.logOperationBegin(operation) | ||||
| 	defer func() { process.logOperationEnd(operation, err) }() | ||||
|  | ||||
| 	if process.handle == 0 { | ||||
| 		return makeProcessError(process, operation, ErrAlreadyClosed, nil) | ||||
| @ -361,96 +334,116 @@ func (process *Process) CloseStdin() (err error) { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	modifyRequestStr := string(modifyRequestb) | ||||
|  | ||||
| 	var resultp *uint16 | ||||
| 	err = hcsModifyProcess(process.handle, modifyRequestStr, &resultp) | ||||
| 	events := processHcsResult(resultp) | ||||
| 	resultJSON, err := vmcompute.HcsModifyProcess(ctx, process.handle, string(modifyRequestb)) | ||||
| 	events := processHcsResult(ctx, resultJSON) | ||||
| 	if err != nil { | ||||
| 		return makeProcessError(process, operation, err, events) | ||||
| 	} | ||||
|  | ||||
| 	if process.stdin != nil { | ||||
| 		process.stdin.Close() | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Close cleans up any state associated with the process but does not kill | ||||
| // or wait on it. | ||||
| func (process *Process) Close() (err error) { | ||||
| 	operation := "hcsshim::Process::Close" | ||||
| 	ctx, span := trace.StartSpan(context.Background(), operation) | ||||
| 	defer span.End() | ||||
| 	defer func() { oc.SetSpanStatus(span, err) }() | ||||
| 	span.AddAttributes( | ||||
| 		trace.StringAttribute("cid", process.SystemID()), | ||||
| 		trace.Int64Attribute("pid", int64(process.processID))) | ||||
|  | ||||
| 	process.handleLock.Lock() | ||||
| 	defer process.handleLock.Unlock() | ||||
|  | ||||
| 	operation := "hcsshim::Process::Close" | ||||
| 	process.logOperationBegin(operation) | ||||
| 	defer func() { process.logOperationEnd(operation, err) }() | ||||
|  | ||||
| 	// Don't double free this | ||||
| 	if process.handle == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	if err = process.unregisterCallback(); err != nil { | ||||
| 	if process.stdin != nil { | ||||
| 		process.stdin.Close() | ||||
| 	} | ||||
| 	if process.stdout != nil { | ||||
| 		process.stdout.Close() | ||||
| 	} | ||||
| 	if process.stderr != nil { | ||||
| 		process.stderr.Close() | ||||
| 	} | ||||
|  | ||||
| 	if err = process.unregisterCallback(ctx); err != nil { | ||||
| 		return makeProcessError(process, operation, err, nil) | ||||
| 	} | ||||
|  | ||||
| 	if err = hcsCloseProcess(process.handle); err != nil { | ||||
| 	if err = vmcompute.HcsCloseProcess(ctx, process.handle); err != nil { | ||||
| 		return makeProcessError(process, operation, err, nil) | ||||
| 	} | ||||
|  | ||||
| 	process.handle = 0 | ||||
| 	process.closedWaitOnce.Do(func() { | ||||
| 		process.exitCode = -1 | ||||
| 		process.waitError = ErrAlreadyClosed | ||||
| 		close(process.waitBlock) | ||||
| 	}) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (process *Process) registerCallback() error { | ||||
| 	context := ¬ifcationWatcherContext{ | ||||
| 		channels: newChannels(), | ||||
| func (process *Process) registerCallback(ctx context.Context) error { | ||||
| 	callbackContext := ¬ifcationWatcherContext{ | ||||
| 		channels:  newProcessChannels(), | ||||
| 		systemID:  process.SystemID(), | ||||
| 		processID: process.processID, | ||||
| 	} | ||||
|  | ||||
| 	callbackMapLock.Lock() | ||||
| 	callbackNumber := nextCallback | ||||
| 	nextCallback++ | ||||
| 	callbackMap[callbackNumber] = context | ||||
| 	callbackMap[callbackNumber] = callbackContext | ||||
| 	callbackMapLock.Unlock() | ||||
|  | ||||
| 	var callbackHandle hcsCallback | ||||
| 	err := hcsRegisterProcessCallback(process.handle, notificationWatcherCallback, callbackNumber, &callbackHandle) | ||||
| 	callbackHandle, err := vmcompute.HcsRegisterProcessCallback(ctx, process.handle, notificationWatcherCallback, callbackNumber) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	context.handle = callbackHandle | ||||
| 	callbackContext.handle = callbackHandle | ||||
| 	process.callbackNumber = callbackNumber | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (process *Process) unregisterCallback() error { | ||||
| func (process *Process) unregisterCallback(ctx context.Context) error { | ||||
| 	callbackNumber := process.callbackNumber | ||||
|  | ||||
| 	callbackMapLock.RLock() | ||||
| 	context := callbackMap[callbackNumber] | ||||
| 	callbackContext := callbackMap[callbackNumber] | ||||
| 	callbackMapLock.RUnlock() | ||||
|  | ||||
| 	if context == nil { | ||||
| 	if callbackContext == nil { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	handle := context.handle | ||||
| 	handle := callbackContext.handle | ||||
|  | ||||
| 	if handle == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	// hcsUnregisterProcessCallback has its own syncronization | ||||
| 	// to wait for all callbacks to complete. We must NOT hold the callbackMapLock. | ||||
| 	err := hcsUnregisterProcessCallback(handle) | ||||
| 	// vmcompute.HcsUnregisterProcessCallback has its own synchronization to | ||||
| 	// wait for all callbacks to complete. We must NOT hold the callbackMapLock. | ||||
| 	err := vmcompute.HcsUnregisterProcessCallback(ctx, handle) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	closeChannels(context.channels) | ||||
| 	closeChannels(callbackContext.channels) | ||||
|  | ||||
| 	callbackMapLock.Lock() | ||||
| 	callbackMap[callbackNumber] = nil | ||||
| 	delete(callbackMap, callbackNumber) | ||||
| 	callbackMapLock.Unlock() | ||||
|  | ||||
| 	handle = 0 | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 TomSweeneyRedHat
					TomSweeneyRedHat