42 lines
1.3 KiB
Go
42 lines
1.3 KiB
Go
package hcs
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/Microsoft/hcsshim/internal/logfields"
|
|
"github.com/Microsoft/hcsshim/internal/timeout"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// syscallWatcher is used as a very simple goroutine around calls into
|
|
// the platform. In some cases, we have seen HCS APIs not returning due to
|
|
// various bugs, and the goroutine making the syscall ends up not returning,
|
|
// prior to its async callback. By spinning up a syscallWatcher, it allows
|
|
// us to at least log a warning if a syscall doesn't complete in a reasonable
|
|
// amount of time.
|
|
//
|
|
// Usage is:
|
|
//
|
|
// syscallWatcher(logContext, func() {
|
|
// err = <syscall>(args...)
|
|
// })
|
|
//
|
|
|
|
func syscallWatcher(logContext logrus.Fields, syscallLambda func()) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), timeout.SyscallWatcher)
|
|
defer cancel()
|
|
go watchFunc(ctx, logContext)
|
|
syscallLambda()
|
|
}
|
|
|
|
func watchFunc(ctx context.Context, logContext logrus.Fields) {
|
|
select {
|
|
case <-ctx.Done():
|
|
if ctx.Err() != context.Canceled {
|
|
logrus.WithFields(logContext).
|
|
WithField(logfields.Timeout, timeout.SyscallWatcher).
|
|
Warning("Syscall did not complete within operation timeout. This may indicate a platform issue. If it appears to be making no forward progress, obtain the stacks and see if there is a syscall stuck in the platform API for a significant length of time.")
|
|
}
|
|
}
|
|
}
|