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