memoryEventNonBlockFD returns a non-blocking inotify file descriptor monitoring memory.events. NOTE: Block FD is expensive because unix.Read will block that thread once there is available data to read. In high scale scenarios, it will create a lot of threads.
()
| 808 | // NOTE: Block FD is expensive because unix.Read will block that thread once there is |
| 809 | // available data to read. In high scale scenarios, it will create a lot of threads. |
| 810 | func (c *Manager) memoryEventNonBlockFD() (_ *os.File, retErr error) { |
| 811 | |
| 812 | rawFd, err := unix.InotifyInit1(unix.IN_CLOEXEC | unix.IN_NONBLOCK) |
| 813 | if err != nil { |
| 814 | return nil, fmt.Errorf("failed to create inotify fd: %w", err) |
| 815 | } |
| 816 | |
| 817 | fd := os.NewFile(uintptr(rawFd), "inotifyfd") |
| 818 | defer func() { |
| 819 | if retErr != nil { |
| 820 | fd.Close() |
| 821 | } |
| 822 | }() |
| 823 | |
| 824 | fpath := filepath.Join(c.path, "memory.events") |
| 825 | if _, err := unix.InotifyAddWatch(rawFd, fpath, unix.IN_MODIFY); err != nil { |
| 826 | return nil, fmt.Errorf("failed to add inotify watch for %q: %w", fpath, err) |
| 827 | } |
| 828 | |
| 829 | // monitor to detect process exit/cgroup deletion |
| 830 | evpath := filepath.Join(c.path, "cgroup.events") |
| 831 | if _, err = unix.InotifyAddWatch(rawFd, evpath, unix.IN_MODIFY); err != nil { |
| 832 | return nil, fmt.Errorf("failed to add inotify watch for %q: %w", evpath, err) |
| 833 | } |
| 834 | return fd, nil |
| 835 | } |
| 836 | |
| 837 | func (c *Manager) EventChan() (<-chan Event, <-chan error) { |
| 838 | ec := make(chan Event, 1) |