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