1*0a6a1f1dSLionel Sambuc //
2*0a6a1f1dSLionel Sambuc // Automated Testing Framework (atf)
3*0a6a1f1dSLionel Sambuc //
4*0a6a1f1dSLionel Sambuc // Copyright (c) 2007 The NetBSD Foundation, Inc.
5*0a6a1f1dSLionel Sambuc // All rights reserved.
6*0a6a1f1dSLionel Sambuc //
7*0a6a1f1dSLionel Sambuc // Redistribution and use in source and binary forms, with or without
8*0a6a1f1dSLionel Sambuc // modification, are permitted provided that the following conditions
9*0a6a1f1dSLionel Sambuc // are met:
10*0a6a1f1dSLionel Sambuc // 1. Redistributions of source code must retain the above copyright
11*0a6a1f1dSLionel Sambuc // notice, this list of conditions and the following disclaimer.
12*0a6a1f1dSLionel Sambuc // 2. Redistributions in binary form must reproduce the above copyright
13*0a6a1f1dSLionel Sambuc // notice, this list of conditions and the following disclaimer in the
14*0a6a1f1dSLionel Sambuc // documentation and/or other materials provided with the distribution.
15*0a6a1f1dSLionel Sambuc //
16*0a6a1f1dSLionel Sambuc // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17*0a6a1f1dSLionel Sambuc // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18*0a6a1f1dSLionel Sambuc // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19*0a6a1f1dSLionel Sambuc // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20*0a6a1f1dSLionel Sambuc // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21*0a6a1f1dSLionel Sambuc // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*0a6a1f1dSLionel Sambuc // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23*0a6a1f1dSLionel Sambuc // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*0a6a1f1dSLionel Sambuc // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25*0a6a1f1dSLionel Sambuc // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26*0a6a1f1dSLionel Sambuc // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27*0a6a1f1dSLionel Sambuc // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*0a6a1f1dSLionel Sambuc //
29*0a6a1f1dSLionel Sambuc
30*0a6a1f1dSLionel Sambuc extern "C" {
31*0a6a1f1dSLionel Sambuc #include <fcntl.h>
32*0a6a1f1dSLionel Sambuc #include <poll.h>
33*0a6a1f1dSLionel Sambuc #include <signal.h>
34*0a6a1f1dSLionel Sambuc #include <unistd.h>
35*0a6a1f1dSLionel Sambuc }
36*0a6a1f1dSLionel Sambuc
37*0a6a1f1dSLionel Sambuc #include <cassert>
38*0a6a1f1dSLionel Sambuc #include <cerrno>
39*0a6a1f1dSLionel Sambuc #include <cstring>
40*0a6a1f1dSLionel Sambuc
41*0a6a1f1dSLionel Sambuc #include "auto_array.hpp"
42*0a6a1f1dSLionel Sambuc #include "exceptions.hpp"
43*0a6a1f1dSLionel Sambuc #include "io.hpp"
44*0a6a1f1dSLionel Sambuc
45*0a6a1f1dSLionel Sambuc namespace impl = tools::io;
46*0a6a1f1dSLionel Sambuc #define IMPL_NAME "tools::io"
47*0a6a1f1dSLionel Sambuc
48*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
49*0a6a1f1dSLionel Sambuc // The "file_handle" class.
50*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
51*0a6a1f1dSLionel Sambuc
file_handle(void)52*0a6a1f1dSLionel Sambuc impl::file_handle::file_handle(void) :
53*0a6a1f1dSLionel Sambuc m_handle(invalid_value())
54*0a6a1f1dSLionel Sambuc {
55*0a6a1f1dSLionel Sambuc }
56*0a6a1f1dSLionel Sambuc
file_handle(handle_type h)57*0a6a1f1dSLionel Sambuc impl::file_handle::file_handle(handle_type h) :
58*0a6a1f1dSLionel Sambuc m_handle(h)
59*0a6a1f1dSLionel Sambuc {
60*0a6a1f1dSLionel Sambuc assert(m_handle != invalid_value());
61*0a6a1f1dSLionel Sambuc }
62*0a6a1f1dSLionel Sambuc
file_handle(const file_handle & fh)63*0a6a1f1dSLionel Sambuc impl::file_handle::file_handle(const file_handle& fh) :
64*0a6a1f1dSLionel Sambuc m_handle(fh.m_handle)
65*0a6a1f1dSLionel Sambuc {
66*0a6a1f1dSLionel Sambuc fh.m_handle = invalid_value();
67*0a6a1f1dSLionel Sambuc }
68*0a6a1f1dSLionel Sambuc
~file_handle(void)69*0a6a1f1dSLionel Sambuc impl::file_handle::~file_handle(void)
70*0a6a1f1dSLionel Sambuc {
71*0a6a1f1dSLionel Sambuc if (is_valid())
72*0a6a1f1dSLionel Sambuc close();
73*0a6a1f1dSLionel Sambuc }
74*0a6a1f1dSLionel Sambuc
75*0a6a1f1dSLionel Sambuc impl::file_handle&
operator =(const file_handle & fh)76*0a6a1f1dSLionel Sambuc impl::file_handle::operator=(const file_handle& fh)
77*0a6a1f1dSLionel Sambuc {
78*0a6a1f1dSLionel Sambuc m_handle = fh.m_handle;
79*0a6a1f1dSLionel Sambuc fh.m_handle = invalid_value();
80*0a6a1f1dSLionel Sambuc
81*0a6a1f1dSLionel Sambuc return *this;
82*0a6a1f1dSLionel Sambuc }
83*0a6a1f1dSLionel Sambuc
84*0a6a1f1dSLionel Sambuc bool
is_valid(void) const85*0a6a1f1dSLionel Sambuc impl::file_handle::is_valid(void)
86*0a6a1f1dSLionel Sambuc const
87*0a6a1f1dSLionel Sambuc {
88*0a6a1f1dSLionel Sambuc return m_handle != invalid_value();
89*0a6a1f1dSLionel Sambuc }
90*0a6a1f1dSLionel Sambuc
91*0a6a1f1dSLionel Sambuc void
close(void)92*0a6a1f1dSLionel Sambuc impl::file_handle::close(void)
93*0a6a1f1dSLionel Sambuc {
94*0a6a1f1dSLionel Sambuc assert(is_valid());
95*0a6a1f1dSLionel Sambuc
96*0a6a1f1dSLionel Sambuc ::close(m_handle);
97*0a6a1f1dSLionel Sambuc
98*0a6a1f1dSLionel Sambuc m_handle = invalid_value();
99*0a6a1f1dSLionel Sambuc }
100*0a6a1f1dSLionel Sambuc
101*0a6a1f1dSLionel Sambuc impl::file_handle::handle_type
disown(void)102*0a6a1f1dSLionel Sambuc impl::file_handle::disown(void)
103*0a6a1f1dSLionel Sambuc {
104*0a6a1f1dSLionel Sambuc assert(is_valid());
105*0a6a1f1dSLionel Sambuc
106*0a6a1f1dSLionel Sambuc handle_type h = m_handle;
107*0a6a1f1dSLionel Sambuc m_handle = invalid_value();
108*0a6a1f1dSLionel Sambuc return h;
109*0a6a1f1dSLionel Sambuc }
110*0a6a1f1dSLionel Sambuc
111*0a6a1f1dSLionel Sambuc impl::file_handle::handle_type
get(void) const112*0a6a1f1dSLionel Sambuc impl::file_handle::get(void)
113*0a6a1f1dSLionel Sambuc const
114*0a6a1f1dSLionel Sambuc {
115*0a6a1f1dSLionel Sambuc assert(is_valid());
116*0a6a1f1dSLionel Sambuc
117*0a6a1f1dSLionel Sambuc return m_handle;
118*0a6a1f1dSLionel Sambuc }
119*0a6a1f1dSLionel Sambuc
120*0a6a1f1dSLionel Sambuc void
posix_remap(handle_type h)121*0a6a1f1dSLionel Sambuc impl::file_handle::posix_remap(handle_type h)
122*0a6a1f1dSLionel Sambuc {
123*0a6a1f1dSLionel Sambuc assert(is_valid());
124*0a6a1f1dSLionel Sambuc
125*0a6a1f1dSLionel Sambuc if (m_handle == h)
126*0a6a1f1dSLionel Sambuc return;
127*0a6a1f1dSLionel Sambuc
128*0a6a1f1dSLionel Sambuc if (::dup2(m_handle, h) == -1)
129*0a6a1f1dSLionel Sambuc throw tools::system_error(IMPL_NAME "::file_handle::posix_remap",
130*0a6a1f1dSLionel Sambuc "dup2(2) failed", errno);
131*0a6a1f1dSLionel Sambuc
132*0a6a1f1dSLionel Sambuc if (::close(m_handle) == -1) {
133*0a6a1f1dSLionel Sambuc ::close(h);
134*0a6a1f1dSLionel Sambuc throw tools::system_error(IMPL_NAME "::file_handle::posix_remap",
135*0a6a1f1dSLionel Sambuc "close(2) failed", errno);
136*0a6a1f1dSLionel Sambuc }
137*0a6a1f1dSLionel Sambuc
138*0a6a1f1dSLionel Sambuc m_handle = h;
139*0a6a1f1dSLionel Sambuc }
140*0a6a1f1dSLionel Sambuc
141*0a6a1f1dSLionel Sambuc impl::file_handle::handle_type
invalid_value(void)142*0a6a1f1dSLionel Sambuc impl::file_handle::invalid_value(void)
143*0a6a1f1dSLionel Sambuc {
144*0a6a1f1dSLionel Sambuc return -1;
145*0a6a1f1dSLionel Sambuc }
146*0a6a1f1dSLionel Sambuc
147*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
148*0a6a1f1dSLionel Sambuc // The "systembuf" class.
149*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
150*0a6a1f1dSLionel Sambuc
systembuf(handle_type h,std::size_t bufsize)151*0a6a1f1dSLionel Sambuc impl::systembuf::systembuf(handle_type h, std::size_t bufsize) :
152*0a6a1f1dSLionel Sambuc m_handle(h),
153*0a6a1f1dSLionel Sambuc m_bufsize(bufsize),
154*0a6a1f1dSLionel Sambuc m_read_buf(NULL),
155*0a6a1f1dSLionel Sambuc m_write_buf(NULL)
156*0a6a1f1dSLionel Sambuc {
157*0a6a1f1dSLionel Sambuc assert(m_handle >= 0);
158*0a6a1f1dSLionel Sambuc assert(m_bufsize > 0);
159*0a6a1f1dSLionel Sambuc
160*0a6a1f1dSLionel Sambuc try {
161*0a6a1f1dSLionel Sambuc m_read_buf = new char[bufsize];
162*0a6a1f1dSLionel Sambuc m_write_buf = new char[bufsize];
163*0a6a1f1dSLionel Sambuc } catch (...) {
164*0a6a1f1dSLionel Sambuc if (m_read_buf != NULL)
165*0a6a1f1dSLionel Sambuc delete [] m_read_buf;
166*0a6a1f1dSLionel Sambuc if (m_write_buf != NULL)
167*0a6a1f1dSLionel Sambuc delete [] m_write_buf;
168*0a6a1f1dSLionel Sambuc throw;
169*0a6a1f1dSLionel Sambuc }
170*0a6a1f1dSLionel Sambuc
171*0a6a1f1dSLionel Sambuc setp(m_write_buf, m_write_buf + m_bufsize);
172*0a6a1f1dSLionel Sambuc }
173*0a6a1f1dSLionel Sambuc
~systembuf(void)174*0a6a1f1dSLionel Sambuc impl::systembuf::~systembuf(void)
175*0a6a1f1dSLionel Sambuc {
176*0a6a1f1dSLionel Sambuc delete [] m_read_buf;
177*0a6a1f1dSLionel Sambuc delete [] m_write_buf;
178*0a6a1f1dSLionel Sambuc }
179*0a6a1f1dSLionel Sambuc
180*0a6a1f1dSLionel Sambuc impl::systembuf::int_type
underflow(void)181*0a6a1f1dSLionel Sambuc impl::systembuf::underflow(void)
182*0a6a1f1dSLionel Sambuc {
183*0a6a1f1dSLionel Sambuc assert(gptr() >= egptr());
184*0a6a1f1dSLionel Sambuc
185*0a6a1f1dSLionel Sambuc bool ok;
186*0a6a1f1dSLionel Sambuc ssize_t cnt = ::read(m_handle, m_read_buf, m_bufsize);
187*0a6a1f1dSLionel Sambuc ok = (cnt != -1 && cnt != 0);
188*0a6a1f1dSLionel Sambuc
189*0a6a1f1dSLionel Sambuc if (!ok)
190*0a6a1f1dSLionel Sambuc return traits_type::eof();
191*0a6a1f1dSLionel Sambuc else {
192*0a6a1f1dSLionel Sambuc setg(m_read_buf, m_read_buf, m_read_buf + cnt);
193*0a6a1f1dSLionel Sambuc return traits_type::to_int_type(*gptr());
194*0a6a1f1dSLionel Sambuc }
195*0a6a1f1dSLionel Sambuc }
196*0a6a1f1dSLionel Sambuc
197*0a6a1f1dSLionel Sambuc impl::systembuf::int_type
overflow(int c)198*0a6a1f1dSLionel Sambuc impl::systembuf::overflow(int c)
199*0a6a1f1dSLionel Sambuc {
200*0a6a1f1dSLionel Sambuc assert(pptr() >= epptr());
201*0a6a1f1dSLionel Sambuc if (sync() == -1)
202*0a6a1f1dSLionel Sambuc return traits_type::eof();
203*0a6a1f1dSLionel Sambuc if (!traits_type::eq_int_type(c, traits_type::eof())) {
204*0a6a1f1dSLionel Sambuc traits_type::assign(*pptr(), c);
205*0a6a1f1dSLionel Sambuc pbump(1);
206*0a6a1f1dSLionel Sambuc }
207*0a6a1f1dSLionel Sambuc return traits_type::not_eof(c);
208*0a6a1f1dSLionel Sambuc }
209*0a6a1f1dSLionel Sambuc
210*0a6a1f1dSLionel Sambuc int
sync(void)211*0a6a1f1dSLionel Sambuc impl::systembuf::sync(void)
212*0a6a1f1dSLionel Sambuc {
213*0a6a1f1dSLionel Sambuc ssize_t cnt = pptr() - pbase();
214*0a6a1f1dSLionel Sambuc
215*0a6a1f1dSLionel Sambuc bool ok;
216*0a6a1f1dSLionel Sambuc ok = ::write(m_handle, pbase(), cnt) == cnt;
217*0a6a1f1dSLionel Sambuc
218*0a6a1f1dSLionel Sambuc if (ok)
219*0a6a1f1dSLionel Sambuc pbump(-cnt);
220*0a6a1f1dSLionel Sambuc return ok ? 0 : -1;
221*0a6a1f1dSLionel Sambuc }
222*0a6a1f1dSLionel Sambuc
223*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
224*0a6a1f1dSLionel Sambuc // The "pistream" class.
225*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
226*0a6a1f1dSLionel Sambuc
pistream(const int fd)227*0a6a1f1dSLionel Sambuc impl::pistream::pistream(const int fd) :
228*0a6a1f1dSLionel Sambuc std::istream(NULL),
229*0a6a1f1dSLionel Sambuc m_systembuf(fd)
230*0a6a1f1dSLionel Sambuc {
231*0a6a1f1dSLionel Sambuc rdbuf(&m_systembuf);
232*0a6a1f1dSLionel Sambuc }
233*0a6a1f1dSLionel Sambuc
234*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
235*0a6a1f1dSLionel Sambuc // The "muxer" class.
236*0a6a1f1dSLionel Sambuc // ------------------------------------------------------------------------
237*0a6a1f1dSLionel Sambuc
238*0a6a1f1dSLionel Sambuc static int
safe_poll(struct pollfd fds[],nfds_t nfds,int timeout)239*0a6a1f1dSLionel Sambuc safe_poll(struct pollfd fds[], nfds_t nfds, int timeout)
240*0a6a1f1dSLionel Sambuc {
241*0a6a1f1dSLionel Sambuc int ret = ::poll(fds, nfds, timeout);
242*0a6a1f1dSLionel Sambuc if (ret == -1) {
243*0a6a1f1dSLionel Sambuc if (errno == EINTR)
244*0a6a1f1dSLionel Sambuc ret = 0;
245*0a6a1f1dSLionel Sambuc else
246*0a6a1f1dSLionel Sambuc throw tools::system_error(IMPL_NAME "::safe_poll", "poll(2) failed",
247*0a6a1f1dSLionel Sambuc errno);
248*0a6a1f1dSLionel Sambuc }
249*0a6a1f1dSLionel Sambuc assert(ret >= 0);
250*0a6a1f1dSLionel Sambuc return ret;
251*0a6a1f1dSLionel Sambuc }
252*0a6a1f1dSLionel Sambuc
253*0a6a1f1dSLionel Sambuc static size_t
safe_read(const int fd,void * buffer,const size_t nbytes,const bool report_errors)254*0a6a1f1dSLionel Sambuc safe_read(const int fd, void* buffer, const size_t nbytes,
255*0a6a1f1dSLionel Sambuc const bool report_errors)
256*0a6a1f1dSLionel Sambuc {
257*0a6a1f1dSLionel Sambuc int ret;
258*0a6a1f1dSLionel Sambuc while ((ret = ::read(fd, buffer, nbytes)) == -1 && errno == EINTR) {}
259*0a6a1f1dSLionel Sambuc if (ret == -1) {
260*0a6a1f1dSLionel Sambuc assert(errno != EINTR);
261*0a6a1f1dSLionel Sambuc
262*0a6a1f1dSLionel Sambuc if (report_errors)
263*0a6a1f1dSLionel Sambuc throw tools::system_error(IMPL_NAME "::safe_read", "read(2) failed",
264*0a6a1f1dSLionel Sambuc errno);
265*0a6a1f1dSLionel Sambuc else
266*0a6a1f1dSLionel Sambuc ret = 0;
267*0a6a1f1dSLionel Sambuc }
268*0a6a1f1dSLionel Sambuc assert(ret >= 0);
269*0a6a1f1dSLionel Sambuc return static_cast< size_t >(ret);
270*0a6a1f1dSLionel Sambuc }
271*0a6a1f1dSLionel Sambuc
muxer(const int * fds,const size_t nfds,const size_t bufsize)272*0a6a1f1dSLionel Sambuc impl::muxer::muxer(const int* fds, const size_t nfds, const size_t bufsize) :
273*0a6a1f1dSLionel Sambuc m_fds(fds),
274*0a6a1f1dSLionel Sambuc m_nfds(nfds),
275*0a6a1f1dSLionel Sambuc m_bufsize(bufsize),
276*0a6a1f1dSLionel Sambuc m_buffers(new std::string[nfds])
277*0a6a1f1dSLionel Sambuc {
278*0a6a1f1dSLionel Sambuc }
279*0a6a1f1dSLionel Sambuc
~muxer(void)280*0a6a1f1dSLionel Sambuc impl::muxer::~muxer(void)
281*0a6a1f1dSLionel Sambuc {
282*0a6a1f1dSLionel Sambuc }
283*0a6a1f1dSLionel Sambuc
284*0a6a1f1dSLionel Sambuc size_t
read_one(const size_t index,const int fd,std::string & accum,const bool report_errors)285*0a6a1f1dSLionel Sambuc impl::muxer::read_one(const size_t index, const int fd, std::string& accum,
286*0a6a1f1dSLionel Sambuc const bool report_errors)
287*0a6a1f1dSLionel Sambuc {
288*0a6a1f1dSLionel Sambuc tools::auto_array< char > buffer(new char[m_bufsize]);
289*0a6a1f1dSLionel Sambuc const size_t nbytes = safe_read(fd, buffer.get(), m_bufsize - 1,
290*0a6a1f1dSLionel Sambuc report_errors);
291*0a6a1f1dSLionel Sambuc assert(nbytes < m_bufsize);
292*0a6a1f1dSLionel Sambuc buffer[nbytes] = '\0';
293*0a6a1f1dSLionel Sambuc
294*0a6a1f1dSLionel Sambuc std::string line(accum);
295*0a6a1f1dSLionel Sambuc
296*0a6a1f1dSLionel Sambuc size_t line_start = 0;
297*0a6a1f1dSLionel Sambuc for (size_t i = 0; i < nbytes; i++) {
298*0a6a1f1dSLionel Sambuc if (buffer[i] == '\n') {
299*0a6a1f1dSLionel Sambuc line_callback(index, line);
300*0a6a1f1dSLionel Sambuc line.clear();
301*0a6a1f1dSLionel Sambuc accum.clear();
302*0a6a1f1dSLionel Sambuc line_start = i + 1;
303*0a6a1f1dSLionel Sambuc } else if (buffer[i] == '\r') {
304*0a6a1f1dSLionel Sambuc // Do nothing.
305*0a6a1f1dSLionel Sambuc } else {
306*0a6a1f1dSLionel Sambuc line.append(1, buffer[i]);
307*0a6a1f1dSLionel Sambuc }
308*0a6a1f1dSLionel Sambuc }
309*0a6a1f1dSLionel Sambuc accum.append(&buffer[line_start]);
310*0a6a1f1dSLionel Sambuc
311*0a6a1f1dSLionel Sambuc return nbytes;
312*0a6a1f1dSLionel Sambuc }
313*0a6a1f1dSLionel Sambuc
314*0a6a1f1dSLionel Sambuc void
mux(volatile const bool & terminate)315*0a6a1f1dSLionel Sambuc impl::muxer::mux(volatile const bool& terminate)
316*0a6a1f1dSLionel Sambuc {
317*0a6a1f1dSLionel Sambuc tools::auto_array< struct pollfd > poll_fds(new struct pollfd[m_nfds]);
318*0a6a1f1dSLionel Sambuc for (size_t i = 0; i < m_nfds; i++) {
319*0a6a1f1dSLionel Sambuc poll_fds[i].fd = m_fds[i];
320*0a6a1f1dSLionel Sambuc poll_fds[i].events = POLLIN;
321*0a6a1f1dSLionel Sambuc }
322*0a6a1f1dSLionel Sambuc
323*0a6a1f1dSLionel Sambuc size_t nactive = m_nfds;
324*0a6a1f1dSLionel Sambuc while (nactive > 0 && !terminate) {
325*0a6a1f1dSLionel Sambuc int ret;
326*0a6a1f1dSLionel Sambuc while (!terminate && (ret = safe_poll(poll_fds.get(), 2, 250)) == 0) {}
327*0a6a1f1dSLionel Sambuc
328*0a6a1f1dSLionel Sambuc for (size_t i = 0; !terminate && i < m_nfds; i++) {
329*0a6a1f1dSLionel Sambuc if (poll_fds[i].events == 0)
330*0a6a1f1dSLionel Sambuc continue;
331*0a6a1f1dSLionel Sambuc
332*0a6a1f1dSLionel Sambuc if (poll_fds[i].revents & POLLHUP) {
333*0a6a1f1dSLionel Sambuc // Any data still available at this point will be processed by
334*0a6a1f1dSLionel Sambuc // a call to the flush method.
335*0a6a1f1dSLionel Sambuc poll_fds[i].events = 0;
336*0a6a1f1dSLionel Sambuc
337*0a6a1f1dSLionel Sambuc assert(nactive >= 1);
338*0a6a1f1dSLionel Sambuc nactive--;
339*0a6a1f1dSLionel Sambuc } else if (poll_fds[i].revents & (POLLIN | POLLRDNORM | POLLRDBAND |
340*0a6a1f1dSLionel Sambuc POLLPRI)) {
341*0a6a1f1dSLionel Sambuc (void)read_one(i, poll_fds[i].fd, m_buffers[i], true);
342*0a6a1f1dSLionel Sambuc }
343*0a6a1f1dSLionel Sambuc }
344*0a6a1f1dSLionel Sambuc }
345*0a6a1f1dSLionel Sambuc }
346*0a6a1f1dSLionel Sambuc
347*0a6a1f1dSLionel Sambuc void
flush(void)348*0a6a1f1dSLionel Sambuc impl::muxer::flush(void)
349*0a6a1f1dSLionel Sambuc {
350*0a6a1f1dSLionel Sambuc for (size_t i = 0; i < m_nfds; i++) {
351*0a6a1f1dSLionel Sambuc while (read_one(i, m_fds[i], m_buffers[i], false) > 0) {}
352*0a6a1f1dSLionel Sambuc
353*0a6a1f1dSLionel Sambuc if (!m_buffers[i].empty())
354*0a6a1f1dSLionel Sambuc line_callback(i, m_buffers[i]);
355*0a6a1f1dSLionel Sambuc }
356*0a6a1f1dSLionel Sambuc }
357