| 86 | } |
| 87 | |
| 88 | void PidFdWaiter::AddWait(PID pid) |
| 89 | { |
| 90 | int pid_fd = OpenPidFd(pid, 0); |
| 91 | if (pid_fd < 0) { |
| 92 | // check if the process is already terminated |
| 93 | if (errno == ESRCH) { |
| 94 | XDEBG("process %d is already terminated", pid); |
| 95 | callback_(pid); |
| 96 | return; |
| 97 | } |
| 98 | XERRO("fail to open pid fd for pid %d", pid); |
| 99 | } |
| 100 | |
| 101 | mtx_.lock(); |
| 102 | pid_fds_[pid] = pid_fd; |
| 103 | mtx_.unlock(); |
| 104 | |
| 105 | // According to the notes of linux man page of epoll_wait at |
| 106 | // https://www.man7.org/linux/man-pages/man2/epoll_wait.2.html |
| 107 | // "While one thread is blocked in a call to epoll_wait(), it is |
| 108 | // possible for another thread to add a file descriptor to the |
| 109 | // waited-upon epoll instance. If the new file descriptor becomes |
| 110 | // ready, it will cause the epoll_wait() call to unblock." |
| 111 | // So we can safely add the pid fd to epoll. |
| 112 | struct epoll_event ev; |
| 113 | ev.events = EPOLLIN; |
| 114 | ev.data.u64 = PackEventData(kEpollEventPid, pid); |
| 115 | XASSERT(!epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, pid_fd, &ev), |
| 116 | "fail to add pid fd to epoll"); |
| 117 | } |
| 118 | |
| 119 | void PidFdWaiter::WaitWorker() |
| 120 | { |
no test coverage detected