doc: od --strings: clarify operation
[coreutils.git] / src / iopoll.c
blob321a1245e21e8c903ff0328d8ebbca0aebae308f
1 /* iopoll.c -- broken pipe detection / non blocking output handling
2 Copyright (C) 2022 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>.
17 Written by Carl Edquist in collaboration with Arsen Arsenović. */
19 #include <config.h>
21 #include <assert.h>
23 /* poll(2) is needed on AIX (where 'select' gives a readable
24 event immediately) and Solaris (where 'select' never gave
25 a readable event). Also use poll(2) on systems we know work
26 and/or are already using poll (linux). */
28 #if defined _AIX || defined __sun || defined __APPLE__ || \
29 defined __linux__ || defined __ANDROID__
30 # define IOPOLL_USES_POLL 1
31 /* Check we've not enabled gnulib's poll module
32 as that will emulate poll() in a way not
33 currently compatible with our usage. */
34 # if defined HAVE_POLL
35 # error "gnulib's poll() replacement is currently incompatible"
36 # endif
37 #endif
39 #if IOPOLL_USES_POLL
40 # include <poll.h>
41 #else
42 # include <sys/select.h>
43 #endif
45 #include "system.h"
46 #include "iopoll.h"
47 #include "isapipe.h"
50 /* BROKEN_OUTPUT selects the mode of operation of this function.
51 If BROKEN_OUTPUT, wait for FDIN to become ready for reading
52 or FDOUT to become a broken pipe.
53 If !BROKEN_OUTPUT, wait for FDIN or FDOUT to become ready for writing.
54 If either of those are -1, then they're not checked. Set BLOCK to true
55 to wait for an event, otherwise return the status immediately.
56 Return 0 if not BLOCKing and there is no event on the requested descriptors.
57 Return 0 if FDIN can be read() without blocking, or IOPOLL_BROKEN_OUTPUT if
58 FDOUT becomes a broken pipe. If !BROKEN_OUTPUT return 0 if FDOUT writeable.
59 Otherwise return IOPOLL_ERROR if there is a poll() or select() error. */
61 static int
62 iopoll_internal (int fdin, int fdout, bool block, bool broken_output)
64 assert (fdin != -1 || fdout != -1);
66 #if IOPOLL_USES_POLL
67 struct pollfd pfds[2] = { /* POLLRDBAND needed for illumos, macOS. */
68 { .fd = fdin, .events = POLLIN | POLLRDBAND, .revents = 0 },
69 { .fd = fdout, .events = POLLRDBAND, .revents = 0 },
71 int check_out_events = POLLERR | POLLHUP | POLLNVAL;
72 int ret = 0;
74 if (! broken_output)
76 pfds[0].events = pfds[1].events = POLLOUT;
77 check_out_events = POLLOUT;
80 while (0 <= ret || errno == EINTR)
82 ret = poll (pfds, 2, block ? -1 : 0);
84 if (ret < 0)
85 continue;
86 if (ret == 0 && ! block)
87 return 0;
88 assert (0 < ret);
89 if (pfds[0].revents) /* input available or pipe closed indicating EOF; */
90 return 0; /* should now be able to read() without blocking */
91 if (pfds[1].revents & check_out_events)
92 return broken_output ? IOPOLL_BROKEN_OUTPUT : 0;
95 #else /* fall back to select()-based implementation */
97 int nfds = (fdin > fdout ? fdin : fdout) + 1;
98 int ret = 0;
100 if (FD_SETSIZE < nfds)
102 errno = EINVAL;
103 ret = -1;
106 /* If fdout has an error condition (like a broken pipe) it will be seen
107 as ready for reading. Assumes fdout is not actually readable. */
108 while (0 <= ret || errno == EINTR)
110 fd_set fds;
111 FD_ZERO (&fds);
112 if (0 <= fdin)
113 FD_SET (fdin, &fds);
114 if (0 <= fdout)
115 FD_SET (fdout, &fds);
117 struct timeval delay = { .tv_sec = 0, .tv_usec = 0 };
118 ret = select (nfds,
119 broken_output ? &fds : NULL,
120 broken_output ? NULL : &fds,
121 NULL, block ? NULL : &delay);
123 if (ret < 0)
124 continue;
125 if (ret == 0 && ! block)
126 return 0;
127 assert (0 < ret);
128 if (0 <= fdin && FD_ISSET (fdin, &fds)) /* input available or EOF; */
129 return 0; /* should now be able to read() without blocking */
130 if (0 <= fdout && FD_ISSET (fdout, &fds)) /* equiv to POLLERR */
131 return broken_output ? IOPOLL_BROKEN_OUTPUT : 0;
134 #endif
135 return IOPOLL_ERROR;
138 extern int
139 iopoll (int fdin, int fdout, bool block)
141 return iopoll_internal (fdin, fdout, block, true);
146 /* Return true if fdin is relevant for iopoll().
147 An fd is not relevant for iopoll() if it is always ready for reading,
148 which is the case for a regular file or block device. */
150 extern bool
151 iopoll_input_ok (int fdin)
153 struct stat st;
154 bool always_ready = fstat (fdin, &st) == 0
155 && (S_ISREG (st.st_mode)
156 || S_ISBLK (st.st_mode));
157 return ! always_ready;
160 /* Return true if fdout is suitable for iopoll().
161 Namely, fdout refers to a pipe. */
163 extern bool
164 iopoll_output_ok (int fdout)
166 return isapipe (fdout) > 0;
169 #ifdef EWOULDBLOCK
170 # define IS_EAGAIN(errcode) ((errcode) == EAGAIN || (errcode) == EWOULDBLOCK)
171 #else
172 # define IS_EAGAIN(errcode) ((errcode) == EAGAIN)
173 #endif
175 /* Inspect the errno of the previous syscall.
176 On EAGAIN, wait for the underlying file descriptor to become writable.
177 Return true, if EAGAIN has been successfully handled. */
179 static bool
180 fwait_for_nonblocking_write (FILE *f)
182 if (! IS_EAGAIN (errno))
183 /* non-recoverable write error */
184 return false;
186 int fd = fileno (f);
187 if (fd == -1)
188 goto fail;
190 /* wait for the file descriptor to become writable */
191 if (iopoll_internal (-1, fd, true, false) != 0)
192 goto fail;
194 /* successfully waited for the descriptor to become writable */
195 clearerr (f);
196 return true;
198 fail:
199 errno = EAGAIN;
200 return false;
204 /* wrapper for fclose() that also waits for F if non blocking. */
206 extern bool
207 fclose_wait (FILE *f)
209 for (;;)
211 if (fflush (f) == 0)
212 break;
214 if (! fwait_for_nonblocking_write (f))
215 break;
218 return fclose (f) == 0;
222 /* wrapper for fwrite() that also waits for F if non blocking. */
224 extern bool
225 fwrite_wait (char const *buf, ssize_t size, FILE *f)
227 for (;;)
229 const size_t written = fwrite (buf, 1, size, f);
230 size -= written;
231 assert (size >= 0);
232 if (size <= 0) /* everything written */
233 return true;
235 if (! fwait_for_nonblocking_write (f))
236 return false;
238 buf += written;