2018-09-18 18:18:08 +00:00
package hcs
import (
2019-03-06 00:48:39 +00:00
"context"
2018-09-18 18:18:08 +00:00
2019-03-06 00:48:39 +00:00
"github.com/Microsoft/hcsshim/internal/logfields"
2018-09-18 18:18:08 +00:00
"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:
//
2019-03-06 00:48:39 +00:00
// syscallWatcher(logContext, func() {
// err = <syscall>(args...)
// })
2018-09-18 18:18:08 +00:00
//
2019-03-06 00:48:39 +00:00
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." )
}
2018-09-18 18:18:08 +00:00
}
}