diff --git a/man/sd_event_add_io.xml b/man/sd_event_add_io.xml index 4201c68f0d..d5495732a7 100644 --- a/man/sd_event_add_io.xml +++ b/man/sd_event_add_io.xml @@ -100,22 +100,21 @@ Description - sd_event_add_io() adds a new I/O event - source to an event loop. The event loop object is specified in the - event parameter, the event source object is - returned in the source parameter. The - fd parameter takes the UNIX file descriptor - to watch, which may refer to a socket, a FIFO, a message queue, a - serial connection, a character device, or any other file descriptor - compatible with Linux - epoll7. The - events parameter takes a bit mask of events - to watch for, a combination of the following event flags: - EPOLLIN, EPOLLOUT, - EPOLLRDHUP, EPOLLPRI, - and EPOLLET, see - epoll_ctl2 - for details. + sd_event_add_io() adds a new I/O event source to an event loop. The event loop + object is specified in the event parameter, the event source object is returned in + the source parameter. The fd parameter takes the UNIX file + descriptor to watch, which may refer to a socket, a FIFO, a message queue, a serial connection, a + character device, or any other file descriptor compatible with Linux epoll7. The + events parameter takes a bit mask of events to watch for, a combination of the + following event flags: EPOLLIN, EPOLLOUT, + EPOLLRDHUP, EPOLLPRI, and EPOLLET, see + epoll_ctl2 for + details. Note that not all file descriptors are compatible with epoll, for example regular file or + directories are not. If this function is called with a file descriptor that does not support epoll, + -EPERM is returned (also see below). In most cases such file descriptors may be + treated as always-readable or always-writable, so that IO event watching is unnecessary. The handler is a function to call when the event source is triggered or NULL. The userdata pointer will be passed to the handler @@ -278,6 +277,16 @@ The passed event source is not an I/O event source. + + + -EPERM + + The passed file descriptor does not support the epoll7 + API, for example because it is a regular file or directory. See epoll_ctl2 + for details. + diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 24b973a204..0e21f89da1 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -2310,7 +2310,6 @@ static int on_signal(sd_event_source *s, const struct signalfd_siginfo *si, void static int setup_event(Context *c, int fd, sd_event **ret) { _cleanup_(sd_event_unrefp) sd_event *e = NULL; - struct stat st; int r; assert(arg_follow); @@ -2329,15 +2328,15 @@ static int setup_event(Context *c, int fd, sd_event **ret) { if (r < 0) return log_error_errno(r, "Failed to add io event source for journal: %m"); - if (fstat(STDOUT_FILENO, &st) < 0) - return log_error_errno(errno, "Failed to stat stdout: %m"); - - if (IN_SET(st.st_mode & S_IFMT, S_IFCHR, S_IFIFO, S_IFSOCK)) { - /* Also keeps an eye on STDOUT, and exits as soon as we see a POLLHUP on that, i.e. when it is closed. */ - r = sd_event_add_io(e, NULL, STDOUT_FILENO, EPOLLHUP|EPOLLERR, NULL, INT_TO_PTR(-ECANCELED)); - if (r < 0) - return log_error_errno(r, "Failed to add io event source for stdout: %m"); - } + /* Also keeps an eye on STDOUT, and exits as soon as we see a POLLHUP on that, i.e. when it is closed. */ + r = sd_event_add_io(e, NULL, STDOUT_FILENO, EPOLLHUP|EPOLLERR, NULL, INT_TO_PTR(-ECANCELED)); + if (r == -EPERM) + /* Installing an epoll watch on a regular file doesn't work and fails with EPERM. Which is + * totally OK, handle it gracefully. epoll_ctl() documents EPERM as the error returned when + * the specified fd doesn't support epoll, hence it's safe to check for that. */ + log_debug_errno(r, "Unable to install EPOLLHUP watch on stderr, not watching for hangups."); + else if (r < 0) + return log_error_errno(r, "Failed to add io event source for stdout: %m"); if (arg_lines != 0 || arg_since_set) { r = sd_event_add_defer(e, NULL, on_first_event, c);