1 //===-- ConnectionFileDescriptorPosix.cpp -----------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #if defined(__APPLE__) 11 // Enable this special support for Apple builds where we can have unlimited 12 // select bounds. We tried switching to poll() and kqueue and we were panicing 13 // the kernel, so we have to stick with select for now. 14 #define _DARWIN_UNLIMITED_SELECT 15 #endif 16 17 #include "lldb/Host/posix/ConnectionFileDescriptorPosix.h" 18 #include "lldb/Host/Config.h" 19 #include "lldb/Host/IOObject.h" 20 #include "lldb/Host/SocketAddress.h" 21 #include "lldb/Host/Socket.h" 22 23 // C Includes 24 #include <errno.h> 25 #include <fcntl.h> 26 #include <string.h> 27 #include <stdlib.h> 28 #include <sys/types.h> 29 30 #ifndef LLDB_DISABLE_POSIX 31 #include <termios.h> 32 #endif 33 34 // C++ Includes 35 // Other libraries and framework includes 36 #include "llvm/Support/ErrorHandling.h" 37 #if defined(__APPLE__) 38 #include "llvm/ADT/SmallVector.h" 39 #endif 40 // Project includes 41 #include "lldb/lldb-private-log.h" 42 #include "lldb/Core/Communication.h" 43 #include "lldb/Core/Log.h" 44 #include "lldb/Core/Timer.h" 45 #include "lldb/Host/Host.h" 46 #include "lldb/Host/Socket.h" 47 #include "lldb/Interpreter/Args.h" 48 49 using namespace lldb; 50 using namespace lldb_private; 51 52 ConnectionFileDescriptor::ConnectionFileDescriptor(bool child_processes_inherit) 53 : Connection() 54 , m_pipe() 55 , m_mutex(Mutex::eMutexTypeRecursive) 56 , m_shutting_down(false) 57 , m_waiting_for_accept(false) 58 , m_child_processes_inherit(child_processes_inherit) 59 { 60 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); 61 if (log) 62 log->Printf("%p ConnectionFileDescriptor::ConnectionFileDescriptor ()", static_cast<void *>(this)); 63 } 64 65 ConnectionFileDescriptor::ConnectionFileDescriptor(int fd, bool owns_fd) 66 : Connection() 67 , m_pipe() 68 , m_mutex(Mutex::eMutexTypeRecursive) 69 , m_shutting_down(false) 70 , m_waiting_for_accept(false) 71 , m_child_processes_inherit(false) 72 { 73 m_write_sp.reset(new File(fd, owns_fd)); 74 m_read_sp.reset(new File(fd, false)); 75 76 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); 77 if (log) 78 log->Printf("%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = %i, owns_fd = %i)", static_cast<void *>(this), fd, 79 owns_fd); 80 OpenCommandPipe(); 81 } 82 83 ConnectionFileDescriptor::~ConnectionFileDescriptor() 84 { 85 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION | LIBLLDB_LOG_OBJECT)); 86 if (log) 87 log->Printf("%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()", static_cast<void *>(this)); 88 Disconnect(NULL); 89 CloseCommandPipe(); 90 } 91 92 void 93 ConnectionFileDescriptor::OpenCommandPipe() 94 { 95 CloseCommandPipe(); 96 97 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); 98 // Make the command file descriptor here: 99 if (!m_pipe.Open(m_child_processes_inherit)) 100 { 101 if (log) 102 log->Printf("%p ConnectionFileDescriptor::OpenCommandPipe () - could not make pipe: %s", static_cast<void *>(this), 103 strerror(errno)); 104 } 105 else 106 { 107 if (log) 108 log->Printf("%p ConnectionFileDescriptor::OpenCommandPipe() - success readfd=%d writefd=%d", static_cast<void *>(this), 109 m_pipe.GetReadFileDescriptor(), m_pipe.GetWriteFileDescriptor()); 110 } 111 } 112 113 void 114 ConnectionFileDescriptor::CloseCommandPipe() 115 { 116 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); 117 if (log) 118 log->Printf("%p ConnectionFileDescriptor::CloseCommandPipe()", static_cast<void *>(this)); 119 120 m_pipe.Close(); 121 } 122 123 bool 124 ConnectionFileDescriptor::IsConnected() const 125 { 126 return (m_read_sp && m_read_sp->IsValid()) || (m_write_sp && m_write_sp->IsValid()); 127 } 128 129 ConnectionStatus 130 ConnectionFileDescriptor::Connect(const char *s, Error *error_ptr) 131 { 132 Mutex::Locker locker(m_mutex); 133 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); 134 if (log) 135 log->Printf("%p ConnectionFileDescriptor::Connect (url = '%s')", static_cast<void *>(this), s); 136 137 OpenCommandPipe(); 138 139 if (s && s[0]) 140 { 141 if (strstr(s, "listen://") == s) 142 { 143 // listen://HOST:PORT 144 return SocketListen(s + strlen("listen://"), error_ptr); 145 } 146 else if (strstr(s, "accept://") == s) 147 { 148 // unix://SOCKNAME 149 return NamedSocketAccept(s + strlen("accept://"), error_ptr); 150 } 151 else if (strstr(s, "unix-accept://") == s) 152 { 153 // unix://SOCKNAME 154 return NamedSocketAccept(s + strlen("unix-accept://"), error_ptr); 155 } 156 else if (strstr(s, "connect://") == s) 157 { 158 return ConnectTCP(s + strlen("connect://"), error_ptr); 159 } 160 else if (strstr(s, "tcp-connect://") == s) 161 { 162 return ConnectTCP(s + strlen("tcp-connect://"), error_ptr); 163 } 164 else if (strstr(s, "udp://") == s) 165 { 166 return ConnectUDP(s + strlen("udp://"), error_ptr); 167 } 168 #ifndef LLDB_DISABLE_POSIX 169 else if (strstr(s, "fd://") == s) 170 { 171 // Just passing a native file descriptor within this current process 172 // that is already opened (possibly from a service or other source). 173 s += strlen("fd://"); 174 bool success = false; 175 int fd = Args::StringToSInt32(s, -1, 0, &success); 176 177 if (success) 178 { 179 // We have what looks to be a valid file descriptor, but we 180 // should make sure it is. We currently are doing this by trying to 181 // get the flags from the file descriptor and making sure it 182 // isn't a bad fd. 183 errno = 0; 184 int flags = ::fcntl(fd, F_GETFL, 0); 185 if (flags == -1 || errno == EBADF) 186 { 187 if (error_ptr) 188 error_ptr->SetErrorStringWithFormat("stale file descriptor: %s", s); 189 m_read_sp.reset(); 190 m_write_sp.reset(); 191 return eConnectionStatusError; 192 } 193 else 194 { 195 // Don't take ownership of a file descriptor that gets passed 196 // to us since someone else opened the file descriptor and 197 // handed it to us. 198 // TODO: Since are using a URL to open connection we should 199 // eventually parse options using the web standard where we 200 // have "fd://123?opt1=value;opt2=value" and we can have an 201 // option be "owns=1" or "owns=0" or something like this to 202 // allow us to specify this. For now, we assume we must 203 // assume we don't own it. 204 205 std::unique_ptr<Socket> tcp_socket; 206 tcp_socket.reset(new Socket(fd, Socket::ProtocolTcp, false)); 207 // Try and get a socket option from this file descriptor to 208 // see if this is a socket and set m_is_socket accordingly. 209 int resuse; 210 bool is_socket = !!tcp_socket->GetOption(SOL_SOCKET, SO_REUSEADDR, resuse); 211 if (is_socket) 212 { 213 m_read_sp = std::move(tcp_socket); 214 m_write_sp = m_read_sp; 215 } 216 else 217 { 218 m_read_sp.reset(new File(fd, false)); 219 m_write_sp.reset(new File(fd, false)); 220 } 221 return eConnectionStatusSuccess; 222 } 223 } 224 225 if (error_ptr) 226 error_ptr->SetErrorStringWithFormat("invalid file descriptor: \"fd://%s\"", s); 227 m_read_sp.reset(); 228 m_write_sp.reset(); 229 return eConnectionStatusError; 230 } 231 else if (strstr(s, "file://") == s) 232 { 233 // file:///PATH 234 const char *path = s + strlen("file://"); 235 int fd = -1; 236 do 237 { 238 fd = ::open(path, O_RDWR); 239 } while (fd == -1 && errno == EINTR); 240 241 if (fd == -1) 242 { 243 if (error_ptr) 244 error_ptr->SetErrorToErrno(); 245 return eConnectionStatusError; 246 } 247 248 if (::isatty(fd)) 249 { 250 // Set up serial terminal emulation 251 struct termios options; 252 ::tcgetattr(fd, &options); 253 254 // Set port speed to maximum 255 ::cfsetospeed(&options, B115200); 256 ::cfsetispeed(&options, B115200); 257 258 // Raw input, disable echo and signals 259 options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); 260 261 // Make sure only one character is needed to return from a read 262 options.c_cc[VMIN] = 1; 263 options.c_cc[VTIME] = 0; 264 265 ::tcsetattr(fd, TCSANOW, &options); 266 } 267 268 int flags = ::fcntl(fd, F_GETFL, 0); 269 if (flags >= 0) 270 { 271 if ((flags & O_NONBLOCK) == 0) 272 { 273 flags |= O_NONBLOCK; 274 ::fcntl(fd, F_SETFL, flags); 275 } 276 } 277 m_read_sp.reset(new File(fd, true)); 278 m_write_sp.reset(new File(fd, false)); 279 return eConnectionStatusSuccess; 280 } 281 #endif 282 if (error_ptr) 283 error_ptr->SetErrorStringWithFormat("unsupported connection URL: '%s'", s); 284 return eConnectionStatusError; 285 } 286 if (error_ptr) 287 error_ptr->SetErrorString("invalid connect arguments"); 288 return eConnectionStatusError; 289 } 290 291 bool 292 ConnectionFileDescriptor::InterruptRead() 293 { 294 return m_pipe.Write("i", 1) == 1; 295 } 296 297 ConnectionStatus 298 ConnectionFileDescriptor::Disconnect(Error *error_ptr) 299 { 300 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); 301 if (log) 302 log->Printf("%p ConnectionFileDescriptor::Disconnect ()", static_cast<void *>(this)); 303 304 ConnectionStatus status = eConnectionStatusSuccess; 305 306 if (!IsConnected()) 307 { 308 if (log) 309 log->Printf("%p ConnectionFileDescriptor::Disconnect(): Nothing to disconnect", static_cast<void *>(this)); 310 return eConnectionStatusSuccess; 311 } 312 313 if (m_read_sp && m_read_sp->IsValid() && m_read_sp->GetFdType() == IOObject::eFDTypeSocket) 314 static_cast<Socket &>(*m_read_sp).PreDisconnect(); 315 316 // Try to get the ConnectionFileDescriptor's mutex. If we fail, that is quite likely 317 // because somebody is doing a blocking read on our file descriptor. If that's the case, 318 // then send the "q" char to the command file channel so the read will wake up and the connection 319 // will then know to shut down. 320 321 m_shutting_down = true; 322 323 Mutex::Locker locker; 324 bool got_lock = locker.TryLock(m_mutex); 325 326 if (!got_lock) 327 { 328 if (m_pipe.WriteDescriptorIsValid()) 329 { 330 int result; 331 result = m_pipe.Write("q", 1) == 1; 332 if (log) 333 log->Printf("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the lock, sent 'q' to %d, result = %d.", 334 static_cast<void *>(this), m_pipe.GetWriteFileDescriptor(), result); 335 } 336 else if (log) 337 { 338 log->Printf("%p ConnectionFileDescriptor::Disconnect(): Couldn't get the lock, but no command pipe is available.", 339 static_cast<void *>(this)); 340 } 341 locker.Lock(m_mutex); 342 } 343 344 Error error = m_read_sp->Close(); 345 Error error2 = m_write_sp->Close(); 346 if (error.Fail() || error2.Fail()) 347 status = eConnectionStatusError; 348 if (error_ptr) 349 *error_ptr = error.Fail() ? error : error2; 350 351 m_shutting_down = false; 352 return status; 353 } 354 355 size_t 356 ConnectionFileDescriptor::Read(void *dst, size_t dst_len, uint32_t timeout_usec, ConnectionStatus &status, Error *error_ptr) 357 { 358 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); 359 360 Mutex::Locker locker; 361 bool got_lock = locker.TryLock(m_mutex); 362 if (!got_lock) 363 { 364 if (log) 365 log->Printf("%p ConnectionFileDescriptor::Read () failed to get the connection lock.", static_cast<void *>(this)); 366 if (error_ptr) 367 error_ptr->SetErrorString("failed to get the connection lock for read."); 368 369 status = eConnectionStatusTimedOut; 370 return 0; 371 } 372 else if (m_shutting_down) 373 return eConnectionStatusError; 374 375 status = BytesAvailable(timeout_usec, error_ptr); 376 if (status != eConnectionStatusSuccess) 377 return 0; 378 379 Error error; 380 size_t bytes_read = dst_len; 381 error = m_read_sp->Read(dst, bytes_read); 382 383 if (log) 384 { 385 log->Printf("%p ConnectionFileDescriptor::Read() fd = %" PRIu64 ", dst = %p, dst_len = %" PRIu64 ") => %" PRIu64 ", error = %s", 386 static_cast<void *>(this), static_cast<uint64_t>(m_read_sp->GetWaitableHandle()), static_cast<void *>(dst), 387 static_cast<uint64_t>(dst_len), static_cast<uint64_t>(bytes_read), error.AsCString()); 388 } 389 390 if (bytes_read == 0) 391 { 392 error.Clear(); // End-of-file. Do not automatically close; pass along for the end-of-file handlers. 393 status = eConnectionStatusEndOfFile; 394 } 395 396 if (error_ptr) 397 *error_ptr = error; 398 399 if (error.Fail()) 400 { 401 uint32_t error_value = error.GetError(); 402 switch (error_value) 403 { 404 case EAGAIN: // The file was marked for non-blocking I/O, and no data were ready to be read. 405 if (m_read_sp->GetFdType() == IOObject::eFDTypeSocket) 406 status = eConnectionStatusTimedOut; 407 else 408 status = eConnectionStatusSuccess; 409 return 0; 410 411 case EFAULT: // Buf points outside the allocated address space. 412 case EINTR: // A read from a slow device was interrupted before any data arrived by the delivery of a signal. 413 case EINVAL: // The pointer associated with fildes was negative. 414 case EIO: // An I/O error occurred while reading from the file system. 415 // The process group is orphaned. 416 // The file is a regular file, nbyte is greater than 0, 417 // the starting position is before the end-of-file, and 418 // the starting position is greater than or equal to the 419 // offset maximum established for the open file 420 // descriptor associated with fildes. 421 case EISDIR: // An attempt is made to read a directory. 422 case ENOBUFS: // An attempt to allocate a memory buffer fails. 423 case ENOMEM: // Insufficient memory is available. 424 status = eConnectionStatusError; 425 break; // Break to close.... 426 427 case ENOENT: // no such file or directory 428 case EBADF: // fildes is not a valid file or socket descriptor open for reading. 429 case ENXIO: // An action is requested of a device that does not exist.. 430 // A requested action cannot be performed by the device. 431 case ECONNRESET: // The connection is closed by the peer during a read attempt on a socket. 432 case ENOTCONN: // A read is attempted on an unconnected socket. 433 status = eConnectionStatusLostConnection; 434 break; // Break to close.... 435 436 case ETIMEDOUT: // A transmission timeout occurs during a read attempt on a socket. 437 status = eConnectionStatusTimedOut; 438 return 0; 439 440 default: 441 if (log) 442 log->Printf("%p ConnectionFileDescriptor::Read (), unexpected error: %s", static_cast<void *>(this), 443 strerror(error_value)); 444 status = eConnectionStatusError; 445 break; // Break to close.... 446 } 447 448 return 0; 449 } 450 return bytes_read; 451 } 452 453 size_t 454 ConnectionFileDescriptor::Write(const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr) 455 { 456 Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_CONNECTION)); 457 if (log) 458 log->Printf("%p ConnectionFileDescriptor::Write (src = %p, src_len = %" PRIu64 ")", static_cast<void *>(this), 459 static_cast<const void *>(src), static_cast<uint64_t>(src_len)); 460 461 if (!IsConnected()) 462 { 463 if (error_ptr) 464 error_ptr->SetErrorString("not connected"); 465 status = eConnectionStatusNoConnection; 466 return 0; 467 } 468 469 Error error; 470 471 size_t bytes_sent = src_len; 472 error = m_write_sp->Write(src, bytes_sent); 473 474 if (log) 475 { 476 log->Printf("%p ConnectionFileDescriptor::Write(fd = %" PRIu64 ", src = %p, src_len = %" PRIu64 ") => %" PRIu64 " (error = %s)", 477 static_cast<void *>(this), static_cast<uint64_t>(m_write_sp->GetWaitableHandle()), static_cast<const void *>(src), 478 static_cast<uint64_t>(src_len), static_cast<uint64_t>(bytes_sent), error.AsCString()); 479 } 480 481 if (error_ptr) 482 *error_ptr = error; 483 484 if (error.Fail()) 485 { 486 switch (error.GetError()) 487 { 488 case EAGAIN: 489 case EINTR: 490 status = eConnectionStatusSuccess; 491 return 0; 492 493 case ECONNRESET: // The connection is closed by the peer during a read attempt on a socket. 494 case ENOTCONN: // A read is attempted on an unconnected socket. 495 status = eConnectionStatusLostConnection; 496 break; // Break to close.... 497 498 default: 499 status = eConnectionStatusError; 500 break; // Break to close.... 501 } 502 503 return 0; 504 } 505 506 status = eConnectionStatusSuccess; 507 return bytes_sent; 508 } 509 510 // This ConnectionFileDescriptor::BytesAvailable() uses select(). 511 // 512 // PROS: 513 // - select is consistent across most unix platforms 514 // - The Apple specific version allows for unlimited fds in the fd_sets by 515 // setting the _DARWIN_UNLIMITED_SELECT define prior to including the 516 // required header files. 517 // CONS: 518 // - on non-Apple platforms, only supports file descriptors up to FD_SETSIZE. 519 // This implementation will assert if it runs into that hard limit to let 520 // users know that another ConnectionFileDescriptor::BytesAvailable() should 521 // be used or a new version of ConnectionFileDescriptor::BytesAvailable() 522 // should be written for the system that is running into the limitations. 523 524 #if defined(__APPLE__) 525 #define FD_SET_DATA(fds) fds.data() 526 #else 527 #define FD_SET_DATA(fds) &fds 528 #endif 529 530 ConnectionStatus 531 ConnectionFileDescriptor::BytesAvailable(uint32_t timeout_usec, Error *error_ptr) 532 { 533 // Don't need to take the mutex here separately since we are only called from Read. If we 534 // ever get used more generally we will need to lock here as well. 535 536 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_CONNECTION)); 537 if (log) 538 log->Printf("%p ConnectionFileDescriptor::BytesAvailable (timeout_usec = %u)", static_cast<void *>(this), timeout_usec); 539 540 struct timeval *tv_ptr; 541 struct timeval tv; 542 if (timeout_usec == UINT32_MAX) 543 { 544 // Inifinite wait... 545 tv_ptr = nullptr; 546 } 547 else 548 { 549 TimeValue time_value; 550 time_value.OffsetWithMicroSeconds(timeout_usec); 551 tv.tv_sec = time_value.seconds(); 552 tv.tv_usec = time_value.microseconds(); 553 tv_ptr = &tv; 554 } 555 556 // Make a copy of the file descriptors to make sure we don't 557 // have another thread change these values out from under us 558 // and cause problems in the loop below where like in FS_SET() 559 const IOObject::WaitableHandle handle = m_read_sp->GetWaitableHandle(); 560 const int pipe_fd = m_pipe.GetReadFileDescriptor(); 561 562 if (handle != IOObject::kInvalidHandleValue) 563 { 564 #if defined(_MSC_VER) 565 // select() won't accept pipes on Windows. The entire Windows codepath needs to be 566 // converted over to using WaitForMultipleObjects and event HANDLEs, but for now at least 567 // this will allow ::select() to not return an error. 568 const bool have_pipe_fd = false; 569 #else 570 const bool have_pipe_fd = pipe_fd >= 0; 571 #if !defined(__APPLE__) 572 assert(handle < FD_SETSIZE); 573 if (have_pipe_fd) 574 assert(pipe_fd < FD_SETSIZE); 575 #endif 576 #endif 577 while (handle == m_read_sp->GetWaitableHandle()) 578 { 579 const int nfds = std::max<int>(handle, pipe_fd) + 1; 580 #if defined(__APPLE__) 581 llvm::SmallVector<fd_set, 1> read_fds; 582 read_fds.resize((nfds / FD_SETSIZE) + 1); 583 for (size_t i = 0; i < read_fds.size(); ++i) 584 FD_ZERO(&read_fds[i]); 585 // FD_SET doesn't bounds check, it just happily walks off the end 586 // but we have taken care of making the extra storage with our 587 // SmallVector of fd_set objects 588 #else 589 fd_set read_fds; 590 FD_ZERO(&read_fds); 591 #endif 592 FD_SET(handle, FD_SET_DATA(read_fds)); 593 if (have_pipe_fd) 594 FD_SET(pipe_fd, FD_SET_DATA(read_fds)); 595 596 Error error; 597 598 if (log) 599 { 600 if (have_pipe_fd) 601 log->Printf( 602 "%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i, %i}, NULL, NULL, timeout=%p)...", 603 static_cast<void *>(this), nfds, handle, pipe_fd, static_cast<void *>(tv_ptr)); 604 else 605 log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i}, NULL, NULL, timeout=%p)...", 606 static_cast<void *>(this), nfds, handle, static_cast<void *>(tv_ptr)); 607 } 608 609 const int num_set_fds = ::select(nfds, FD_SET_DATA(read_fds), NULL, NULL, tv_ptr); 610 if (num_set_fds < 0) 611 error.SetErrorToErrno(); 612 else 613 error.Clear(); 614 615 if (log) 616 { 617 if (have_pipe_fd) 618 log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i, %i}, NULL, NULL, timeout=%p) " 619 "=> %d, error = %s", 620 static_cast<void *>(this), nfds, handle, pipe_fd, static_cast<void *>(tv_ptr), num_set_fds, 621 error.AsCString()); 622 else 623 log->Printf("%p ConnectionFileDescriptor::BytesAvailable() ::select (nfds=%i, fds={%i}, NULL, NULL, timeout=%p) => " 624 "%d, error = %s", 625 static_cast<void *>(this), nfds, handle, static_cast<void *>(tv_ptr), num_set_fds, error.AsCString()); 626 } 627 628 if (error_ptr) 629 *error_ptr = error; 630 631 if (error.Fail()) 632 { 633 switch (error.GetError()) 634 { 635 case EBADF: // One of the descriptor sets specified an invalid descriptor. 636 return eConnectionStatusLostConnection; 637 638 case EINVAL: // The specified time limit is invalid. One of its components is negative or too large. 639 default: // Other unknown error 640 return eConnectionStatusError; 641 642 case EAGAIN: // The kernel was (perhaps temporarily) unable to 643 // allocate the requested number of file descriptors, 644 // or we have non-blocking IO 645 case EINTR: // A signal was delivered before the time limit 646 // expired and before any of the selected events 647 // occurred. 648 break; // Lets keep reading to until we timeout 649 } 650 } 651 else if (num_set_fds == 0) 652 { 653 return eConnectionStatusTimedOut; 654 } 655 else if (num_set_fds > 0) 656 { 657 if (FD_ISSET(handle, FD_SET_DATA(read_fds))) 658 return eConnectionStatusSuccess; 659 if (have_pipe_fd && FD_ISSET(pipe_fd, FD_SET_DATA(read_fds))) 660 { 661 // We got a command to exit. Read the data from that pipe: 662 char buffer[16]; 663 ssize_t bytes_read; 664 665 do 666 { 667 bytes_read = ::read(pipe_fd, buffer, sizeof(buffer)); 668 } while (bytes_read < 0 && errno == EINTR); 669 670 switch (buffer[0]) 671 { 672 case 'q': 673 if (log) 674 log->Printf("%p ConnectionFileDescriptor::BytesAvailable() got data: %*s from the command channel.", 675 static_cast<void *>(this), static_cast<int>(bytes_read), buffer); 676 return eConnectionStatusEndOfFile; 677 case 'i': 678 // Interrupt the current read 679 return eConnectionStatusInterrupted; 680 } 681 } 682 } 683 } 684 } 685 686 if (error_ptr) 687 error_ptr->SetErrorString("not connected"); 688 return eConnectionStatusLostConnection; 689 } 690 691 ConnectionStatus 692 ConnectionFileDescriptor::NamedSocketAccept(const char *socket_name, Error *error_ptr) 693 { 694 Socket *socket = nullptr; 695 Error error = Socket::UnixDomainAccept(socket_name, m_child_processes_inherit, socket); 696 if (error_ptr) 697 *error_ptr = error; 698 m_write_sp.reset(socket); 699 m_read_sp = m_write_sp; 700 return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError; 701 } 702 703 ConnectionStatus 704 ConnectionFileDescriptor::NamedSocketConnect(const char *socket_name, Error *error_ptr) 705 { 706 Socket *socket = nullptr; 707 Error error = Socket::UnixDomainConnect(socket_name, m_child_processes_inherit, socket); 708 if (error_ptr) 709 *error_ptr = error; 710 m_write_sp.reset(socket); 711 m_read_sp = m_write_sp; 712 return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError; 713 } 714 715 ConnectionStatus 716 ConnectionFileDescriptor::SocketListen(const char *s, Error *error_ptr) 717 { 718 m_port_predicate.SetValue(0, eBroadcastNever); 719 720 Socket *socket = nullptr; 721 m_waiting_for_accept = true; 722 Error error = Socket::TcpListen(s, m_child_processes_inherit, socket, &m_port_predicate); 723 if (error_ptr) 724 *error_ptr = error; 725 if (error.Fail()) 726 return eConnectionStatusError; 727 728 std::unique_ptr<Socket> listening_socket_up; 729 730 listening_socket_up.reset(socket); 731 socket = nullptr; 732 error = listening_socket_up->BlockingAccept(s, m_child_processes_inherit, socket); 733 listening_socket_up.reset(); 734 if (error_ptr) 735 *error_ptr = error; 736 if (error.Fail()) 737 return eConnectionStatusError; 738 739 m_write_sp.reset(socket); 740 m_read_sp = m_write_sp; 741 return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError; 742 } 743 744 ConnectionStatus 745 ConnectionFileDescriptor::ConnectTCP(const char *s, Error *error_ptr) 746 { 747 Socket *socket = nullptr; 748 Error error = Socket::TcpConnect(s, m_child_processes_inherit, socket); 749 if (error_ptr) 750 *error_ptr = error; 751 m_write_sp.reset(socket); 752 m_read_sp = m_write_sp; 753 return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError; 754 } 755 756 ConnectionStatus 757 ConnectionFileDescriptor::ConnectUDP(const char *s, Error *error_ptr) 758 { 759 Socket *send_socket = nullptr; 760 Socket *recv_socket = nullptr; 761 Error error = Socket::UdpConnect(s, m_child_processes_inherit, send_socket, recv_socket); 762 if (error_ptr) 763 *error_ptr = error; 764 m_write_sp.reset(send_socket); 765 m_read_sp.reset(recv_socket); 766 return (error.Success()) ? eConnectionStatusSuccess : eConnectionStatusError; 767 } 768 769 uint16_t 770 ConnectionFileDescriptor::GetListeningPort(uint32_t timeout_sec) 771 { 772 uint16_t bound_port = 0; 773 if (timeout_sec == UINT32_MAX) 774 m_port_predicate.WaitForValueNotEqualTo(0, bound_port); 775 else 776 { 777 TimeValue timeout = TimeValue::Now(); 778 timeout.OffsetWithSeconds(timeout_sec); 779 m_port_predicate.WaitForValueNotEqualTo(0, bound_port, &timeout); 780 } 781 return bound_port; 782 } 783 784 bool 785 ConnectionFileDescriptor::GetChildProcessesInherit() const 786 { 787 return m_child_processes_inherit; 788 } 789 790 void 791 ConnectionFileDescriptor::SetChildProcessesInherit(bool child_processes_inherit) 792 { 793 m_child_processes_inherit = child_processes_inherit; 794 } 795