summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrei Vagin <avagin@google.com>2019-05-23 23:20:11 -0700
committerShentubot <shentubot@google.com>2019-05-23 23:21:13 -0700
commita949133c4b22a87c79310b2d825f2899028d6088 (patch)
tree439e03ccfff0c8bfe64cdef3e5191d39015b957c
parent409e8eea60f096b34c9005b302dc821f38ac19ed (diff)
gvisor: interrupt the sendfile system call if a task has been interrupted
sendfile can be called for a big range and it can require significant amount of time to process it, so we need to handle task interrupts in this system call. PiperOrigin-RevId: 249781023 Change-Id: Ifc2ec505d74c06f5ee76f93b8d30d518ec2d4015
-rw-r--r--pkg/amutex/amutex.go6
-rw-r--r--pkg/amutex/amutex_test.go4
-rw-r--r--pkg/sentry/fs/file.go6
-rw-r--r--pkg/sentry/kernel/pipe/node_test.go4
-rw-r--r--pkg/sentry/kernel/task_block.go5
5 files changed, 25 insertions, 0 deletions
diff --git a/pkg/amutex/amutex.go b/pkg/amutex/amutex.go
index 85e819304..4f7759b87 100644
--- a/pkg/amutex/amutex.go
+++ b/pkg/amutex/amutex.go
@@ -33,6 +33,9 @@ type Sleeper interface {
// SleepFinish is called by AbortableMutex.Lock() once a contended mutex
// is acquired or the wait is aborted.
SleepFinish(success bool)
+
+ // Interrupted returns true if the wait is aborted.
+ Interrupted() bool
}
// NoopSleeper is a stateless no-op implementation of Sleeper for anonymous
@@ -47,6 +50,9 @@ func (NoopSleeper) SleepStart() <-chan struct{} {
// SleepFinish implements Sleeper.SleepFinish.
func (NoopSleeper) SleepFinish(success bool) {}
+// Interrupted implements Sleeper.Interrupted.
+func (NoopSleeper) Interrupted() bool { return false }
+
// AbortableMutex is an abortable mutex. It allows Lock() to be aborted while it
// waits to acquire the mutex.
type AbortableMutex struct {
diff --git a/pkg/amutex/amutex_test.go b/pkg/amutex/amutex_test.go
index 6a0af006e..211bdda4b 100644
--- a/pkg/amutex/amutex_test.go
+++ b/pkg/amutex/amutex_test.go
@@ -31,6 +31,10 @@ func (s *sleeper) SleepStart() <-chan struct{} {
func (*sleeper) SleepFinish(bool) {
}
+func (s *sleeper) Interrupted() bool {
+ return len(s.ch) != 0
+}
+
func TestMutualExclusion(t *testing.T) {
var m AbortableMutex
m.Init()
diff --git a/pkg/sentry/fs/file.go b/pkg/sentry/fs/file.go
index 8f1baca23..8c1307235 100644
--- a/pkg/sentry/fs/file.go
+++ b/pkg/sentry/fs/file.go
@@ -516,12 +516,18 @@ type lockedReader struct {
// Read implements io.Reader.Read.
func (r *lockedReader) Read(buf []byte) (int, error) {
+ if r.Ctx.Interrupted() {
+ return 0, syserror.ErrInterrupted
+ }
n, err := r.File.FileOperations.Read(r.Ctx, r.File, usermem.BytesIOSequence(buf), r.File.offset)
return int(n), err
}
// ReadAt implements io.Reader.ReadAt.
func (r *lockedReader) ReadAt(buf []byte, offset int64) (int, error) {
+ if r.Ctx.Interrupted() {
+ return 0, syserror.ErrInterrupted
+ }
n, err := r.File.FileOperations.Read(r.Ctx, r.File, usermem.BytesIOSequence(buf), offset)
return int(n), err
}
diff --git a/pkg/sentry/kernel/pipe/node_test.go b/pkg/sentry/kernel/pipe/node_test.go
index 7ddecdad8..31d9b0443 100644
--- a/pkg/sentry/kernel/pipe/node_test.go
+++ b/pkg/sentry/kernel/pipe/node_test.go
@@ -48,6 +48,10 @@ func (s *sleeper) Cancel() {
s.ch <- struct{}{}
}
+func (s *sleeper) Interrupted() bool {
+ return len(s.ch) != 0
+}
+
type openResult struct {
*fs.File
error
diff --git a/pkg/sentry/kernel/task_block.go b/pkg/sentry/kernel/task_block.go
index 30a7f6b1e..1c76c4d84 100644
--- a/pkg/sentry/kernel/task_block.go
+++ b/pkg/sentry/kernel/task_block.go
@@ -158,6 +158,11 @@ func (t *Task) SleepFinish(success bool) {
t.Activate()
}
+// Interrupted implements amutex.Sleeper.Interrupted
+func (t *Task) Interrupted() bool {
+ return len(t.interruptChan) != 0
+}
+
// UninterruptibleSleepStart implements context.Context.UninterruptibleSleepStart.
func (t *Task) UninterruptibleSleepStart(deactivate bool) {
if deactivate {