| 308 | } |
| 309 | |
| 310 | void Process::async_read() noexcept { |
| 311 | if(data.id <= 0 || (!stdout_fd && !stderr_fd)) |
| 312 | return; |
| 313 | |
| 314 | stdout_stderr_thread = std::thread([this] { |
| 315 | std::vector<pollfd> pollfds; |
| 316 | std::bitset<2> fd_is_stdout; |
| 317 | if(stdout_fd) { |
| 318 | fd_is_stdout.set(pollfds.size()); |
| 319 | pollfds.emplace_back(); |
| 320 | pollfds.back().fd = fcntl(*stdout_fd, F_SETFL, fcntl(*stdout_fd, F_GETFL) | O_NONBLOCK) == 0 ? *stdout_fd : -1; |
| 321 | pollfds.back().events = POLLIN; |
| 322 | } |
| 323 | if(stderr_fd) { |
| 324 | pollfds.emplace_back(); |
| 325 | pollfds.back().fd = fcntl(*stderr_fd, F_SETFL, fcntl(*stderr_fd, F_GETFL) | O_NONBLOCK) == 0 ? *stderr_fd : -1; |
| 326 | pollfds.back().events = POLLIN; |
| 327 | } |
| 328 | auto buffer = std::unique_ptr<char[]>(new char[config.buffer_size]); |
| 329 | bool any_open = !pollfds.empty(); |
| 330 | while(any_open && (poll(pollfds.data(), static_cast<nfds_t>(pollfds.size()), -1) > 0 || errno == EINTR)) { |
| 331 | any_open = false; |
| 332 | for(size_t i = 0; i < pollfds.size(); ++i) { |
| 333 | if(pollfds[i].fd >= 0) { |
| 334 | if(pollfds[i].revents & POLLIN) { |
| 335 | const ssize_t n = read(pollfds[i].fd, buffer.get(), config.buffer_size); |
| 336 | if(n > 0) { |
| 337 | if(fd_is_stdout[i]) |
| 338 | read_stdout(buffer.get(), static_cast<size_t>(n)); |
| 339 | else |
| 340 | read_stderr(buffer.get(), static_cast<size_t>(n)); |
| 341 | } |
| 342 | else if(n == 0 || (n < 0 && errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK)) { |
| 343 | if(fd_is_stdout[i]) { |
| 344 | if(config.on_stdout_close) |
| 345 | config.on_stdout_close(); |
| 346 | } |
| 347 | else { |
| 348 | if(config.on_stderr_close) |
| 349 | config.on_stderr_close(); |
| 350 | } |
| 351 | pollfds[i].fd = -1; |
| 352 | continue; |
| 353 | } |
| 354 | } |
| 355 | else if(pollfds[i].revents & (POLLERR | POLLHUP | POLLNVAL)) { |
| 356 | if(fd_is_stdout[i]) { |
| 357 | if(config.on_stdout_close) |
| 358 | config.on_stdout_close(); |
| 359 | } |
| 360 | else { |
| 361 | if(config.on_stderr_close) |
| 362 | config.on_stderr_close(); |
| 363 | } |
| 364 | pollfds[i].fd = -1; |
| 365 | continue; |
| 366 | } |
| 367 | any_open = true; |