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