1 /*
2 * Copyright (C) 2005 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //
18 // Unidirectional pipe.
19 //
20
21 #include "Pipe.h"
22 #include <utils/Log.h>
23
24 #if defined(HAVE_WIN32_IPC)
25 # include <windows.h>
26 #else
27 # include <fcntl.h>
28 # include <unistd.h>
29 # include <errno.h>
30 #endif
31
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <assert.h>
35 #include <string.h>
36
37 using namespace android;
38
39 const unsigned long kInvalidHandle = (unsigned long) -1;
40
41
42 /*
43 * Constructor. Do little.
44 */
Pipe(void)45 Pipe::Pipe(void)
46 : mReadNonBlocking(false), mReadHandle(kInvalidHandle),
47 mWriteHandle(kInvalidHandle)
48 {
49 }
50
51 /*
52 * Destructor. Use the system-appropriate close call.
53 */
~Pipe(void)54 Pipe::~Pipe(void)
55 {
56 #if defined(HAVE_WIN32_IPC)
57 if (mReadHandle != kInvalidHandle) {
58 if (!CloseHandle((HANDLE)mReadHandle))
59 LOG(LOG_WARN, "pipe", "failed closing read handle (%ld)\n",
60 mReadHandle);
61 }
62 if (mWriteHandle != kInvalidHandle) {
63 FlushFileBuffers((HANDLE)mWriteHandle);
64 if (!CloseHandle((HANDLE)mWriteHandle))
65 LOG(LOG_WARN, "pipe", "failed closing write handle (%ld)\n",
66 mWriteHandle);
67 }
68 #else
69 if (mReadHandle != kInvalidHandle) {
70 if (close((int) mReadHandle) != 0)
71 LOG(LOG_WARN, "pipe", "failed closing read fd (%d)\n",
72 (int) mReadHandle);
73 }
74 if (mWriteHandle != kInvalidHandle) {
75 if (close((int) mWriteHandle) != 0)
76 LOG(LOG_WARN, "pipe", "failed closing write fd (%d)\n",
77 (int) mWriteHandle);
78 }
79 #endif
80 }
81
82 /*
83 * Create the pipe.
84 *
85 * Use the POSIX stuff for everything but Windows.
86 */
create(void)87 bool Pipe::create(void)
88 {
89 assert(mReadHandle == kInvalidHandle);
90 assert(mWriteHandle == kInvalidHandle);
91
92 #if defined(HAVE_WIN32_IPC)
93 /* we use this across processes, so they need to be inheritable */
94 HANDLE handles[2];
95 SECURITY_ATTRIBUTES saAttr;
96
97 saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
98 saAttr.bInheritHandle = TRUE;
99 saAttr.lpSecurityDescriptor = NULL;
100
101 if (!CreatePipe(&handles[0], &handles[1], &saAttr, 0)) {
102 LOG(LOG_ERROR, "pipe", "unable to create pipe\n");
103 return false;
104 }
105 mReadHandle = (unsigned long) handles[0];
106 mWriteHandle = (unsigned long) handles[1];
107 return true;
108 #else
109 int fds[2];
110
111 if (pipe(fds) != 0) {
112 LOG(LOG_ERROR, "pipe", "unable to create pipe\n");
113 return false;
114 }
115 mReadHandle = fds[0];
116 mWriteHandle = fds[1];
117 return true;
118 #endif
119 }
120
121 /*
122 * Create a "half pipe". Please, no Segway riding.
123 */
createReader(unsigned long handle)124 bool Pipe::createReader(unsigned long handle)
125 {
126 mReadHandle = handle;
127 assert(mWriteHandle == kInvalidHandle);
128 return true;
129 }
130
131 /*
132 * Create a "half pipe" for writing.
133 */
createWriter(unsigned long handle)134 bool Pipe::createWriter(unsigned long handle)
135 {
136 mWriteHandle = handle;
137 assert(mReadHandle == kInvalidHandle);
138 return true;
139 }
140
141 /*
142 * Return "true" if create() has been called successfully.
143 */
isCreated(void)144 bool Pipe::isCreated(void)
145 {
146 // one or the other should be open
147 return (mReadHandle != kInvalidHandle || mWriteHandle != kInvalidHandle);
148 }
149
150
151 /*
152 * Read data from the pipe.
153 *
154 * For Linux and Darwin, just call read(). For Windows, implement
155 * non-blocking reads by calling PeekNamedPipe first.
156 */
read(void * buf,int count)157 int Pipe::read(void* buf, int count)
158 {
159 assert(mReadHandle != kInvalidHandle);
160
161 #if defined(HAVE_WIN32_IPC)
162 DWORD totalBytesAvail = count;
163 DWORD bytesRead;
164
165 if (mReadNonBlocking) {
166 // use PeekNamedPipe to adjust read count expectations
167 if (!PeekNamedPipe((HANDLE) mReadHandle, NULL, 0, NULL,
168 &totalBytesAvail, NULL))
169 {
170 LOG(LOG_ERROR, "pipe", "PeekNamedPipe failed\n");
171 return -1;
172 }
173
174 if (totalBytesAvail == 0)
175 return 0;
176 }
177
178 if (!ReadFile((HANDLE) mReadHandle, buf, totalBytesAvail, &bytesRead,
179 NULL))
180 {
181 DWORD err = GetLastError();
182 if (err == ERROR_HANDLE_EOF || err == ERROR_BROKEN_PIPE)
183 return 0;
184 LOG(LOG_ERROR, "pipe", "ReadFile failed (err=%ld)\n", err);
185 return -1;
186 }
187
188 return (int) bytesRead;
189 #else
190 int cc;
191 cc = ::read(mReadHandle, buf, count);
192 if (cc < 0 && errno == EAGAIN)
193 return 0;
194 return cc;
195 #endif
196 }
197
198 /*
199 * Write data to the pipe.
200 *
201 * POSIX systems are trivial, Windows uses a different call and doesn't
202 * handle non-blocking writes.
203 *
204 * If we add non-blocking support here, we probably want to make it an
205 * all-or-nothing write.
206 *
207 * DO NOT use LOG() here, we could be writing a log message.
208 */
write(const void * buf,int count)209 int Pipe::write(const void* buf, int count)
210 {
211 assert(mWriteHandle != kInvalidHandle);
212
213 #if defined(HAVE_WIN32_IPC)
214 DWORD bytesWritten;
215
216 if (mWriteNonBlocking) {
217 // BUG: can't use PeekNamedPipe() to get the amount of space
218 // left. Looks like we need to use "overlapped I/O" functions.
219 // I just don't care that much.
220 }
221
222 if (!WriteFile((HANDLE) mWriteHandle, buf, count, &bytesWritten, NULL)) {
223 // can't LOG, use stderr
224 fprintf(stderr, "WriteFile failed (err=%ld)\n", GetLastError());
225 return -1;
226 }
227
228 return (int) bytesWritten;
229 #else
230 int cc;
231 cc = ::write(mWriteHandle, buf, count);
232 if (cc < 0 && errno == EAGAIN)
233 return 0;
234 return cc;
235 #endif
236 }
237
238 /*
239 * Figure out if there is data available on the read fd.
240 *
241 * We return "true" on error because we want the caller to try to read
242 * from the pipe. They'll notice the read failure and do something
243 * appropriate.
244 */
readReady(void)245 bool Pipe::readReady(void)
246 {
247 assert(mReadHandle != kInvalidHandle);
248
249 #if defined(HAVE_WIN32_IPC)
250 DWORD totalBytesAvail;
251
252 if (!PeekNamedPipe((HANDLE) mReadHandle, NULL, 0, NULL,
253 &totalBytesAvail, NULL))
254 {
255 LOG(LOG_ERROR, "pipe", "PeekNamedPipe failed\n");
256 return true;
257 }
258
259 return (totalBytesAvail != 0);
260 #else
261 errno = 0;
262 fd_set readfds;
263 struct timeval tv = { 0, 0 };
264 int cc;
265
266 FD_ZERO(&readfds);
267 FD_SET(mReadHandle, &readfds);
268
269 cc = select(mReadHandle+1, &readfds, NULL, NULL, &tv);
270 if (cc < 0) {
271 LOG(LOG_ERROR, "pipe", "select() failed\n");
272 return true;
273 } else if (cc == 0) {
274 /* timed out, nothing available */
275 return false;
276 } else if (cc == 1) {
277 /* our fd is ready */
278 return true;
279 } else {
280 LOG(LOG_ERROR, "pipe", "HUH? select() returned > 1\n");
281 return true;
282 }
283 #endif
284 }
285
286 /*
287 * Enable or disable non-blocking mode for the read descriptor.
288 *
289 * NOTE: the calls succeed under Mac OS X, but the pipe doesn't appear to
290 * actually be in non-blocking mode. If this matters -- i.e. you're not
291 * using a select() call -- put a call to readReady() in front of the
292 * ::read() call, with a PIPE_NONBLOCK_BROKEN #ifdef in the Makefile for
293 * Darwin.
294 */
setReadNonBlocking(bool val)295 bool Pipe::setReadNonBlocking(bool val)
296 {
297 assert(mReadHandle != kInvalidHandle);
298
299 #if defined(HAVE_WIN32_IPC)
300 // nothing to do
301 #else
302 int flags;
303
304 if (fcntl(mReadHandle, F_GETFL, &flags) == -1) {
305 LOG(LOG_ERROR, "pipe", "couldn't get flags for pipe read fd\n");
306 return false;
307 }
308 if (val)
309 flags |= O_NONBLOCK;
310 else
311 flags &= ~(O_NONBLOCK);
312 if (fcntl(mReadHandle, F_SETFL, &flags) == -1) {
313 LOG(LOG_ERROR, "pipe", "couldn't set flags for pipe read fd\n");
314 return false;
315 }
316 #endif
317
318 mReadNonBlocking = val;
319 return true;
320 }
321
322 /*
323 * Enable or disable non-blocking mode for the write descriptor.
324 *
325 * As with setReadNonBlocking(), this does not work on the Mac.
326 */
setWriteNonBlocking(bool val)327 bool Pipe::setWriteNonBlocking(bool val)
328 {
329 assert(mWriteHandle != kInvalidHandle);
330
331 #if defined(HAVE_WIN32_IPC)
332 // nothing to do
333 #else
334 int flags;
335
336 if (fcntl(mWriteHandle, F_GETFL, &flags) == -1) {
337 LOG(LOG_WARN, "pipe",
338 "Warning: couldn't get flags for pipe write fd (errno=%d)\n",
339 errno);
340 return false;
341 }
342 if (val)
343 flags |= O_NONBLOCK;
344 else
345 flags &= ~(O_NONBLOCK);
346 if (fcntl(mWriteHandle, F_SETFL, &flags) == -1) {
347 LOG(LOG_WARN, "pipe",
348 "Warning: couldn't set flags for pipe write fd (errno=%d)\n",
349 errno);
350 return false;
351 }
352 #endif
353
354 mWriteNonBlocking = val;
355 return true;
356 }
357
358 /*
359 * Specify whether a file descriptor can be inherited by a child process.
360 * Under Linux this means setting the close-on-exec flag, under Windows
361 * this is SetHandleInformation(HANDLE_FLAG_INHERIT).
362 */
disallowReadInherit(void)363 bool Pipe::disallowReadInherit(void)
364 {
365 if (mReadHandle == kInvalidHandle)
366 return false;
367
368 #if defined(HAVE_WIN32_IPC)
369 if (SetHandleInformation((HANDLE) mReadHandle, HANDLE_FLAG_INHERIT, 0) == 0)
370 return false;
371 #else
372 if (fcntl((int) mReadHandle, F_SETFD, FD_CLOEXEC) != 0)
373 return false;
374 #endif
375 return true;
376 }
disallowWriteInherit(void)377 bool Pipe::disallowWriteInherit(void)
378 {
379 if (mWriteHandle == kInvalidHandle)
380 return false;
381
382 #if defined(HAVE_WIN32_IPC)
383 if (SetHandleInformation((HANDLE) mWriteHandle, HANDLE_FLAG_INHERIT, 0) == 0)
384 return false;
385 #else
386 if (fcntl((int) mWriteHandle, F_SETFD, FD_CLOEXEC) != 0)
387 return false;
388 #endif
389 return true;
390 }
391
392 /*
393 * Close read descriptor.
394 */
closeRead(void)395 bool Pipe::closeRead(void)
396 {
397 if (mReadHandle == kInvalidHandle)
398 return false;
399
400 #if defined(HAVE_WIN32_IPC)
401 if (mReadHandle != kInvalidHandle) {
402 if (!CloseHandle((HANDLE)mReadHandle)) {
403 LOG(LOG_WARN, "pipe", "failed closing read handle\n");
404 return false;
405 }
406 }
407 #else
408 if (mReadHandle != kInvalidHandle) {
409 if (close((int) mReadHandle) != 0) {
410 LOG(LOG_WARN, "pipe", "failed closing read fd\n");
411 return false;
412 }
413 }
414 #endif
415 mReadHandle = kInvalidHandle;
416 return true;
417 }
418
419 /*
420 * Close write descriptor.
421 */
closeWrite(void)422 bool Pipe::closeWrite(void)
423 {
424 if (mWriteHandle == kInvalidHandle)
425 return false;
426
427 #if defined(HAVE_WIN32_IPC)
428 if (mWriteHandle != kInvalidHandle) {
429 if (!CloseHandle((HANDLE)mWriteHandle)) {
430 LOG(LOG_WARN, "pipe", "failed closing write handle\n");
431 return false;
432 }
433 }
434 #else
435 if (mWriteHandle != kInvalidHandle) {
436 if (close((int) mWriteHandle) != 0) {
437 LOG(LOG_WARN, "pipe", "failed closing write fd\n");
438 return false;
439 }
440 }
441 #endif
442 mWriteHandle = kInvalidHandle;
443 return true;
444 }
445
446 /*
447 * Get the read handle.
448 */
getReadHandle(void)449 unsigned long Pipe::getReadHandle(void)
450 {
451 assert(mReadHandle != kInvalidHandle);
452
453 return mReadHandle;
454 }
455
456 /*
457 * Get the write handle.
458 */
getWriteHandle(void)459 unsigned long Pipe::getWriteHandle(void)
460 {
461 assert(mWriteHandle != kInvalidHandle);
462
463 return mWriteHandle;
464 }
465
466