Skip to content

Commit

Permalink
Merge pull request docker#123 from docker/oom
Browse files Browse the repository at this point in the history
Add oom support to events
  • Loading branch information
crosbymichael committed Mar 1, 2016
2 parents 70a8c1e + 500ca74 commit c63b541
Show file tree
Hide file tree
Showing 10 changed files with 201 additions and 256 deletions.
94 changes: 0 additions & 94 deletions chanotify/chanotify.go

This file was deleted.

117 changes: 0 additions & 117 deletions chanotify/chanotify_test.go

This file was deleted.

13 changes: 11 additions & 2 deletions runtime/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package runtime

import (
"encoding/json"
"io"
"io/ioutil"
"os"
"path/filepath"
Expand Down Expand Up @@ -46,7 +47,15 @@ type Container interface {
// Name or path of the OCI compliant runtime used to execute the container
Runtime() string
// OOM signals the channel if the container received an OOM notification
// OOM() (<-chan struct{}, error)
OOM() (OOM, error)
}

type OOM interface {
io.Closer
FD() int
ContainerID() string
Flush()
Removed() bool
}

type Stdio struct {
Expand Down Expand Up @@ -159,8 +168,8 @@ type container struct {
bundle string
runtime string
processes map[string]*process
stdio Stdio
labels []string
oomFds []int
}

func (c *container) ID() string {
Expand Down
87 changes: 87 additions & 0 deletions runtime/container_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package runtime

import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"os/exec"
Expand Down Expand Up @@ -240,6 +241,59 @@ func (c *container) Stats() (*Stat, error) {
}, nil
}

func (c *container) OOM() (OOM, error) {
container, err := c.getLibctContainer()
if err != nil {
if lerr, ok := err.(libcontainer.Error); ok {
// with oom registration sometimes the container can run, exit, and be destroyed
// faster than we can get the state back so we can just ignore this
if lerr.Code() == libcontainer.ContainerNotExists {
return nil, ErrContainerExited
}
}
return nil, err
}
state, err := container.State()
if err != nil {
return nil, err
}
memoryPath := state.CgroupPaths["memory"]
return c.getMemeoryEventFD(memoryPath)
}

func (c *container) getMemeoryEventFD(root string) (*oom, error) {
f, err := os.Open(filepath.Join(root, "memory.oom_control"))
if err != nil {
return nil, err
}
fd, _, serr := syscall.RawSyscall(syscall.SYS_EVENTFD2, 0, syscall.FD_CLOEXEC, 0)
if serr != 0 {
f.Close()
return nil, serr
}
if err := c.writeEventFD(root, int(f.Fd()), int(fd)); err != nil {
syscall.Close(int(fd))
f.Close()
return nil, err
}
return &oom{
root: root,
id: c.id,
eventfd: int(fd),
control: f,
}, nil
}

func (c *container) writeEventFD(root string, cfd, efd int) error {
f, err := os.OpenFile(filepath.Join(root, "cgroup.event_control"), os.O_WRONLY, 0)
if err != nil {
return err
}
defer f.Close()
_, err = f.WriteString(fmt.Sprintf("%d %d", efd, cfd))
return err
}

func waitForStart(p *process, cmd *exec.Cmd) error {
for i := 0; i < 50; i++ {
if _, err := p.getPidFromFile(); err != nil {
Expand Down Expand Up @@ -270,3 +324,36 @@ func isAlive(cmd *exec.Cmd) (bool, error) {
}
return true, nil
}

type oom struct {
id string
root string
control *os.File
eventfd int
}

func (o *oom) ContainerID() string {
return o.id
}

func (o *oom) FD() int {
return o.eventfd
}

func (o *oom) Flush() {
buf := make([]byte, 8)
syscall.Read(o.eventfd, buf)
}

func (o *oom) Removed() bool {
_, err := os.Lstat(filepath.Join(o.root, "cgroup.event_control"))
return os.IsNotExist(err)
}

func (o *oom) Close() error {
err := syscall.Close(o.eventfd)
if cerr := o.control.Close(); err == nil {
err = cerr
}
return err
}
4 changes: 4 additions & 0 deletions runtime/container_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,7 @@ func (c *container) Pids() ([]int, error) {
func (c *container) Stats() (*Stat, error) {
return nil, errors.New("Stats not yet implemented on Windows")
}

func (c *container) OOM() (OOM, error) {
return nil, errors.New("OOM not yet implemented on Windows")
}
Loading

0 comments on commit c63b541

Please sign in to comment.