Line data Source code
1 :
2 : /* Copyright (c) 2005-2017, Stefan Eilemann <eile@equalizergraphics.com>
3 : *
4 : * This file is part of Collage <https://github.com/Eyescale/Collage>
5 : *
6 : * This library is free software; you can redistribute it and/or modify it under
7 : * the terms of the GNU Lesser General Public License version 2.1 as published
8 : * by the Free Software Foundation.
9 : *
10 : * This library is distributed in the hope that it will be useful, but WITHOUT
11 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13 : * details.
14 : *
15 : * You should have received a copy of the GNU Lesser General Public License
16 : * along with this library; if not, write to the Free Software Foundation, Inc.,
17 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 : */
19 :
20 : #include "fdConnection.h"
21 :
22 : #include "connectionDescription.h"
23 : #include "exception.h"
24 : #include "global.h"
25 : #include "log.h"
26 :
27 : #include <lunchbox/os.h>
28 :
29 : #include <errno.h>
30 : #include <poll.h>
31 :
32 : namespace co
33 : {
34 355 : FDConnection::FDConnection()
35 : : _readFD(0)
36 355 : , _writeFD(0)
37 : {
38 355 : }
39 :
40 37 : int FDConnection::_getTimeOut()
41 : {
42 37 : const uint32_t timeout = Global::getTimeout();
43 37 : return timeout == LB_TIMEOUT_INDEFINITE ? -1 : int(timeout);
44 : }
45 :
46 : //----------------------------------------------------------------------
47 : // read
48 : //----------------------------------------------------------------------
49 3016576 : int64_t FDConnection::readSync(void* buffer, const uint64_t bytes, const bool)
50 : {
51 3016576 : if (_readFD < 1)
52 0 : return -1;
53 :
54 3016576 : ssize_t bytesRead = ::read(_readFD, buffer, bytes);
55 3016576 : if (bytesRead > 0)
56 3016539 : return bytesRead;
57 :
58 37 : if (bytesRead == 0 || errno == EWOULDBLOCK || errno == EAGAIN)
59 : {
60 : struct pollfd fds[1];
61 37 : fds[0].fd = _readFD;
62 37 : fds[0].events = POLLIN;
63 :
64 37 : const int res = poll(fds, 1, _getTimeOut());
65 37 : if (res < 0)
66 : {
67 0 : LBWARN << "Error during read : " << strerror(errno) << std::endl;
68 0 : return -1;
69 : }
70 :
71 37 : if (res == 0)
72 0 : throw Exception(Exception::TIMEOUT_READ);
73 :
74 37 : bytesRead = ::read(_readFD, buffer, bytes);
75 : }
76 :
77 37 : if (bytesRead > 0)
78 0 : return bytesRead;
79 :
80 37 : if (bytesRead == 0) // EOF
81 : {
82 185 : LBDEBUG << "Got EOF, closing " << getDescription()->toString()
83 148 : << std::endl;
84 37 : close();
85 37 : return -1;
86 : }
87 :
88 0 : LBASSERT(bytesRead == -1); // error
89 :
90 0 : if (errno == EINTR) // if interrupted, try again
91 0 : return 0;
92 :
93 0 : LBWARN << "Error during read: " << strerror(errno) << ", " << bytes
94 0 : << "b on fd " << _readFD << std::endl;
95 0 : return -1;
96 : }
97 :
98 : //----------------------------------------------------------------------
99 : // write
100 : //----------------------------------------------------------------------
101 2970178 : int64_t FDConnection::write(const void* buffer, const uint64_t bytes)
102 : {
103 2970178 : if (!isConnected() || _writeFD < 1)
104 0 : return -1;
105 :
106 2969872 : ssize_t bytesWritten = ::write(_writeFD, buffer, bytes);
107 2965889 : if (bytesWritten > 0)
108 2965889 : return bytesWritten;
109 :
110 0 : if (bytesWritten == 0 || errno == EWOULDBLOCK || errno == EAGAIN)
111 : {
112 : struct pollfd fds[1];
113 0 : fds[0].fd = _writeFD;
114 0 : fds[0].events = POLLOUT;
115 0 : const int res = poll(fds, 1, _getTimeOut());
116 0 : if (res < 0)
117 : {
118 0 : LBWARN << "Write error: " << lunchbox::sysError << std::endl;
119 0 : return -1;
120 : }
121 :
122 0 : if (res == 0)
123 0 : throw Exception(Exception::TIMEOUT_WRITE);
124 :
125 0 : bytesWritten = ::write(_writeFD, buffer, bytes);
126 : }
127 :
128 0 : if (bytesWritten > 0)
129 0 : return bytesWritten;
130 :
131 0 : if (bytesWritten == -1) // error
132 : {
133 0 : if (errno == EINTR) // if interrupted, try again
134 0 : return 0;
135 :
136 0 : LBWARN << "Error during write: " << lunchbox::sysError << std::endl;
137 0 : return -1;
138 : }
139 :
140 0 : return bytesWritten;
141 : }
142 63 : }
|