Created
September 20, 2015 13:29
-
-
Save jsipprell/cd150cd88614befc20c4 to your computer and use it in GitHub Desktop.
cgroup deletion race test (based on libcontainer from docker 1.7)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// cgroup eventfd oom event_control tester | |
// To build: go build -o cgroupoom cgroupoom.go | |
package main | |
import ( | |
"fmt" | |
"io/ioutil" | |
"log" | |
"os" | |
"path/filepath" | |
"sync" | |
"syscall" | |
) | |
const ( | |
cgroupMemory = "memory" | |
monitorNode = "cgroup.event_control" | |
oomNode = "memory.oom_control" | |
) | |
var ( | |
cgroupRoot string | |
debug bool | |
) | |
func init() { | |
if os.Getenv("CGROUP_ROOT") == "" { | |
os.Setenv("CGROUP_ROOT", "/cgroup") | |
} | |
switch os.Getenv("DEBUG") { | |
case "0", "FALSE", "false", "NO", "no", "": | |
default: | |
debug = true | |
} | |
} | |
func monitorcgroup(cgroup string) (<-chan struct{}, error) { | |
cgRoot := filepath.Join(cgroupRoot, cgroupMemory, cgroup) | |
oomControl, err := os.Open(filepath.Join(cgRoot, oomNode)) | |
if err != nil { | |
return nil, err | |
} | |
fd, _, syserr := syscall.RawSyscall(syscall.SYS_EVENTFD2, 0, syscall.FD_CLOEXEC, 0) | |
if syserr != 0 { | |
defer oomControl.Close() | |
return nil, syserr | |
} | |
eventfd := os.NewFile(fd, "eventfd") | |
data := fmt.Sprintf("%d %d", eventfd.Fd(), oomControl.Fd()) | |
eventControlPath := filepath.Join(cgRoot, monitorNode) | |
if err = ioutil.WriteFile(eventControlPath, []byte(data), 0777); err != nil { | |
defer oomControl.Close() | |
defer eventfd.Close() | |
return nil, err | |
} | |
ch := make(chan struct{}) | |
go func() { | |
var ( | |
i int | |
err error | |
) | |
defer close(ch) | |
defer eventfd.Close() | |
defer oomControl.Close() | |
buf := make([]byte, 8) | |
for { | |
if i, err = eventfd.Read(buf); err != nil { | |
log.Printf("%d bytes, err=%v", i, err) | |
return | |
} | |
if st, err := os.Lstat(eventControlPath); os.IsNotExist(err) { | |
if debug { | |
log.Println(err) | |
} | |
return | |
} else if err != nil { | |
log.Fatal(err) | |
} else if debug { | |
log.Printf("%v: %#v", eventControlPath, st) | |
} | |
if debug { | |
log.Printf("%d bytes: %v", i, buf[:i]) | |
} | |
ch <- struct{}{} | |
} | |
}() | |
return ch, nil | |
} | |
func main() { | |
var wg sync.WaitGroup | |
cgroupRoot = os.ExpandEnv("$CGROUP_ROOT") | |
if len(os.Args) < 2 { | |
fmt.Println("usage: cgroupoom <memory-cgroup-name/or-path>") | |
os.Exit(1) | |
} | |
for _, a := range os.Args[1:] { | |
wg.Add(1) | |
go func(cgroup string) { | |
defer wg.Done() | |
ch, err := monitorcgroup(cgroup) | |
if err != nil { | |
log.Fatalf("monitoring cgroup %q: %v", cgroup, err) | |
} | |
log.Printf("monitoring cgroup %q", cgroup) | |
ok := true | |
for ok { | |
_, ok = <-ch | |
if ok { | |
log.Printf("cgroup %q: OOM!", cgroup) | |
} | |
} | |
log.Printf("cgroup %q destroyed", cgroup) | |
}(a) | |
} | |
wg.Wait() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment