notify_linux.go
func notifyOnOOM(paths map[string]string) (<-chan struct{}, error) {
	dir := paths[oomCgroupName]
	if dir == "" {
		return nil, fmt.Errorf("There is no path for %q in state", oomCgroupName)
	}
	oomControl, err := os.Open(filepath.Join(dir, "memory.oom_control"))
	if err != nil {
		return nil, err
	}
	fd, _, syserr := syscall.RawSyscall(syscall.SYS_EVENTFD2, 0, syscall.FD_CLOEXEC, 0)
	if syserr != 0 {
		oomControl.Close()
		return nil, syserr
	}

	eventfd := os.NewFile(fd, "eventfd")

	eventControlPath := filepath.Join(dir, "cgroup.event_control")
	data := fmt.Sprintf("%d %d", eventfd.Fd(), oomControl.Fd())
	if err := ioutil.WriteFile(eventControlPath, []byte(data), 0700); err != nil {
		eventfd.Close()
		oomControl.Close()
		return nil, err
	}
	ch := make(chan struct{})
	go func() {
		defer func() {
			close(ch)
			eventfd.Close()
			oomControl.Close()
		}()
		buf := make([]byte, 8)
		for {
			if _, err := eventfd.Read(buf); err != nil {
				return
			}
			// When a cgroup is destroyed, an event is sent to eventfd.
			// So if the control path is gone, return instead of notifying.
			if _, err := os.Lstat(eventControlPath); os.IsNotExist(err) {
				return
			}
			ch <- struct{}{}
		}
	}()
	return ch, nil
}
func notifyOnOOM(paths map[string]string) (<-chan struct{}, error) {
	dir := paths[oomCgroupName]
	if dir == "" {
		return nil, fmt.Errorf("There is no path for %q in state", oomCgroupName)
	}
	oomControl, err := os.Open(filepath.Join(dir, "memory.oom_control"))
	if err != nil {
		return nil, err
	}
	fd, _, syserr := syscall.RawSyscall(syscall.SYS_EVENTFD2, 0, syscall.FD_CLOEXEC, 0)
	if syserr != 0 {
		oomControl.Close()
		return nil, syserr
	}

	eventfd := os.NewFile(fd, "eventfd")

	eventControlPath := filepath.Join(dir, "cgroup.event_control")
	data := fmt.Sprintf("%d %d", eventfd.Fd(), oomControl.Fd())
	if err := ioutil.WriteFile(eventControlPath, []byte(data), 0700); err != nil {
		eventfd.Close()
		oomControl.Close()
		return nil, err
	}
	ch := make(chan struct{})
	go func() {
		defer func() {
			close(ch)
			eventfd.Close()
			oomControl.Close()
		}()
		buf := make([]byte, 8)
		for {
			if _, err := eventfd.Read(buf); err != nil {
				return
			}
			// When a cgroup is destroyed, an event is sent to eventfd.
			// So if the control path is gone, return instead of notifying.
			if _, err := os.Lstat(eventControlPath); os.IsNotExist(err) {
				return
			}
			ch <- struct{}{}
		}
	}()
	return ch, nil
}
func notifyOnOOM ( paths map [ string ] string ) ( <- chan struct { } , error ) { dir := paths [ oomCgroupName ] if dir == " " { return nil , fmt . Errorf ( " " , oomCgroupName ) } oomControl , err := os . Open ( filepath . Join ( dir , " " ) ) if err != nil { return nil , err } fd , _ , syserr := syscall . RawSyscall ( syscall . SYS_EVENTFD2 , 0 , syscall . FD_CLOEXEC , 0 ) if syserr != 0 { oomControl . Close ( ) return nil , syserr } eventfd := os . NewFile ( fd , " " ) eventControlPath := filepath . Join ( dir , " " ) data := fmt . Sprintf ( " " , eventfd . Fd ( ) , oomControl . Fd ( ) ) if err := ioutil . WriteFile ( eventControlPath , [ ] byte ( data ) , 0700 ) ; err != nil { eventfd . Close ( ) oomControl . Close ( ) return nil , err } ch := make ( chan struct { } ) go func ( ) { defer func ( ) { close ( ch ) eventfd . Close ( ) oomControl . Close ( ) } ( ) buf := make ( [ ] byte , 8 ) for { if _ , err := eventfd . Read ( buf ) ; err != nil { return } // When a cgroup is destroyed, an event is sent to eventfd. // So if the control path is gone, return instead of notifying. if _ , err := os . Lstat ( eventControlPath ) ; os . IsNotExist ( err ) { return } ch <- struct { } { } } } ( ) return ch , nil }
// notifyOnOOM returns channel on which you can expect event about OOM,
// if process died without OOM this channel will be closed.
// s is current *libcontainer.State for container.
notifyOnOOM returns channel on which you can expect event about OOM if process died without OOM this channel will be closed . s is current * libcontainer . State for container .