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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 } 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 */ 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 */ 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 */ 449 unsigned long Pipe::getReadHandle(void) 450 { 451 assert(mReadHandle != kInvalidHandle); 452 453 return mReadHandle; 454 } 455 456 /* 457 * Get the write handle. 458 */ 459 unsigned long Pipe::getWriteHandle(void) 460 { 461 assert(mWriteHandle != kInvalidHandle); 462 463 return mWriteHandle; 464 } 465 466