Revert usage of ContainerWait, return to io.Copy blocking
Until https://github.com/moby/moby/issues/41827 is resolved this code causes chaos to unfold on machines and causes servers to be non-terminatable. This logic was intially changed to logical purposes, but this io.Copy logic works perfectly fine (even if not immediately intuitive).
This commit is contained in:
parent
6e74123c65
commit
c9d972d544
|
@ -26,6 +26,18 @@ type imagePullStatus struct {
|
||||||
Progress string `json:"progress"`
|
Progress string `json:"progress"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A custom console writer that allows us to keep a function blocked until the
|
||||||
|
// given stream is properly closed. This does nothing special, only exists to
|
||||||
|
// make a noop io.Writer.
|
||||||
|
type noopWriter struct{}
|
||||||
|
|
||||||
|
var _ io.Writer = noopWriter{}
|
||||||
|
|
||||||
|
// Implement the required Write function to satisfy the io.Writer interface.
|
||||||
|
func (nw noopWriter) Write(b []byte) (int, error) {
|
||||||
|
return len(b), nil
|
||||||
|
}
|
||||||
|
|
||||||
// Attaches to the docker container itself and ensures that we can pipe data in and out
|
// Attaches to the docker container itself and ensures that we can pipe data in and out
|
||||||
// of the process stream. This should not be used for reading console data as you *will*
|
// of the process stream. This should not be used for reading console data as you *will*
|
||||||
// miss important output at the beginning because of the time delay with attaching to the
|
// miss important output at the beginning because of the time delay with attaching to the
|
||||||
|
@ -60,8 +72,8 @@ func (e *Environment) Attach() error {
|
||||||
go func() {
|
go func() {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
defer e.stream.Close()
|
||||||
defer func() {
|
defer func() {
|
||||||
e.stream.Close()
|
|
||||||
e.SetState(environment.ProcessOfflineState)
|
e.SetState(environment.ProcessOfflineState)
|
||||||
e.SetStream(nil)
|
e.SetStream(nil)
|
||||||
}()
|
}()
|
||||||
|
@ -80,22 +92,16 @@ func (e *Environment) Attach() error {
|
||||||
// the pollResources function to run until it needs to be stopped. Because the container
|
// the pollResources function to run until it needs to be stopped. Because the container
|
||||||
// can be polled for resource usage, even when sropped, we need to have this logic present
|
// can be polled for resource usage, even when sropped, we need to have this logic present
|
||||||
// in order to cancel the context and therefore stop the routine that is spawned.
|
// in order to cancel the context and therefore stop the routine that is spawned.
|
||||||
ok, err := e.client.ContainerWait(ctx, e.Id, container.WaitConditionNotRunning)
|
//
|
||||||
select {
|
// For now, DO NOT use client#ContainerWait from the Docker package. There is a nasty
|
||||||
case <-ctx.Done():
|
// bug causing containers to hang on deletion and cause servers to lock up on the system.
|
||||||
// Do nothing, the context was canceled by a different process, there is no error
|
//
|
||||||
// to report at this point.
|
// This weird code isn't intuitive, but it keeps the function from ending until the container
|
||||||
e.log().Debug("terminating ContainerWait blocking process, context canceled")
|
// is stopped and therefore the stream reader ends up closed.
|
||||||
return
|
// @see https://github.com/moby/moby/issues/41827
|
||||||
case _ = <-err:
|
c := new(noopWriter)
|
||||||
// An error occurred with the ContainerWait call, report it here and then hope
|
if _, err := io.Copy(c, e.stream.Reader); err != nil {
|
||||||
// for the fucking best I guess?
|
e.log().WithField("error", err).Error("could not copy from environment stream to noop writer")
|
||||||
e.log().WithField("error", err).Error("error while blocking using ContainerWait")
|
|
||||||
return
|
|
||||||
case <-ok:
|
|
||||||
// Do nothing, everything is running as expected. This will allow us to keep
|
|
||||||
// blocking the termination of this function until the container stops at which
|
|
||||||
// point all of our deferred functions can run.
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user