Skip to content

Commit

Permalink
implement method to wait for logger exit
Browse files Browse the repository at this point in the history
Signed-off-by: Mrudul Harwani <mharwani@amazon.com>
  • Loading branch information
mharwani committed Jul 31, 2023
1 parent 72f418a commit 23b24a6
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 5 deletions.
7 changes: 4 additions & 3 deletions pkg/cmd/container/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"os"
"os/signal"
"syscall"
"time"

"github.com/containerd/containerd"
"github.com/containerd/containerd/errdefs"
Expand Down Expand Up @@ -91,8 +90,10 @@ func Logs(ctx context.Context, client *containerd.Client, container string, opti
// Setup goroutine to send stop event if container task finishes:
go func() {
<-waitCh
// wait 100ms to let logViewer process data sent after container exit, if any
time.Sleep(100 * time.Millisecond)
// Wait for logger to process remaining logs after container exit
if err = logging.WaitForLogger(dataStore, l[labels.Namespace], found.Container.ID()); err != nil {
logrus.WithError(err).Error("failed to wait for logger shutdown")
}
logrus.Debugf("container task has finished, sending kill signal to log viewer")
stopChannel <- os.Interrupt
}()
Expand Down
29 changes: 27 additions & 2 deletions pkg/logging/logging.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/containerd/containerd"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/runtime/v2/logging"
"github.com/containerd/nerdctl/pkg/lockutil"
"github.com/sirupsen/logrus"
)

Expand Down Expand Up @@ -142,6 +143,17 @@ func LoadLogConfig(dataStore, ns, id string) (LogConfig, error) {
return logConfig, nil
}

func getLockPath(dataStore, ns, id string) string {
return filepath.Join(dataStore, "containers", ns, id, "logger-lock")
}

// WaitForLogger waits until the logger has finished executing and processing container logs
func WaitForLogger(dataStore, ns, id string) error {
return lockutil.WithDirLock(getLockPath(dataStore, ns, id), func() error {
return nil
})
}

// getContainerWait loads the container from ID and returns its wait channel
func getContainerWait(ctx context.Context, hostAddress string, config *logging.Config) (<-chan containerd.ExitStatus, error) {
client, err := containerd.New(hostAddress, containerd.WithDefaultNamespace(config.Namespace))
Expand Down Expand Up @@ -234,11 +246,24 @@ func loggerFunc(dataStore string) (logging.LoggerFunc, error) {
if err != nil {
return err
}
if err := ready(); err != nil {

lockFile := getLockPath(dataStore, config.Namespace, config.ID)
f, err := os.Create(lockFile)
if err != nil {
return err
}
defer f.Close()

// the logger will obtain an exclusive lock on a file until the container is
// stopped and the driver has finished processing all output,
// so that waiting log viewers can be signalled when the process is complete.
return lockutil.WithDirLock(lockFile, func() error {
if err := ready(); err != nil {
return err
}

return loggingProcessAdapter(ctx, driver, dataStore, logConfig.HostAddress, config)
return loggingProcessAdapter(ctx, driver, dataStore, logConfig.HostAddress, config)
})
} else if !errors.Is(err, os.ErrNotExist) {
// the file does not exist if the container was created with nerdctl < 0.20
return err
Expand Down

0 comments on commit 23b24a6

Please sign in to comment.