1 //===-- ConnectionFileDescriptorPosix.cpp ---------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 // Enable this special support for Apple builds where we can have unlimited
11 // select bounds. We tried switching to poll() and kqueue and we were panicing
12 // the kernel, so we have to stick with select for now.
13 #define _DARWIN_UNLIMITED_SELECT
16 #include "lldb/Host/posix/ConnectionFileDescriptorPosix.h"
17 #include "lldb/Host/Config.h"
18 #include "lldb/Host/FileSystem.h"
19 #include "lldb/Host/Socket.h"
20 #include "lldb/Host/SocketAddress.h"
21 #include "lldb/Utility/LLDBLog.h"
22 #include "lldb/Utility/SelectHelper.h"
23 #include "lldb/Utility/Timeout.h"
29 #include <sys/types.h>
39 #include "llvm/Support/Errno.h"
40 #include "llvm/Support/ErrorHandling.h"
41 #if defined(__APPLE__)
42 #include "llvm/ADT/SmallVector.h"
44 #include "lldb/Host/Host.h"
45 #include "lldb/Host/Socket.h"
46 #include "lldb/Host/common/TCPSocket.h"
47 #include "lldb/Host/common/UDPSocket.h"
48 #include "lldb/Utility/Log.h"
49 #include "lldb/Utility/StreamString.h"
50 #include "lldb/Utility/Timer.h"
53 using namespace lldb_private
;
55 ConnectionFileDescriptor::ConnectionFileDescriptor(bool child_processes_inherit
)
56 : Connection(), m_pipe(), m_mutex(), m_shutting_down(false),
58 m_child_processes_inherit(child_processes_inherit
) {
59 Log
*log(GetLog(LLDBLog::Connection
| LLDBLog::Object
));
60 LLDB_LOGF(log
, "%p ConnectionFileDescriptor::ConnectionFileDescriptor ()",
61 static_cast<void *>(this));
64 ConnectionFileDescriptor::ConnectionFileDescriptor(int fd
, bool owns_fd
)
65 : Connection(), m_pipe(), m_mutex(), m_shutting_down(false),
66 m_child_processes_inherit(false) {
68 std::make_shared
<NativeFile
>(fd
, File::eOpenOptionReadWrite
, owns_fd
);
70 Log
*log(GetLog(LLDBLog::Connection
| LLDBLog::Object
));
72 "%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = "
74 static_cast<void *>(this), fd
, owns_fd
);
78 ConnectionFileDescriptor::ConnectionFileDescriptor(Socket
*socket
)
79 : Connection(), m_pipe(), m_mutex(), m_shutting_down(false),
80 m_child_processes_inherit(false) {
81 InitializeSocket(socket
);
84 ConnectionFileDescriptor::~ConnectionFileDescriptor() {
85 Log
*log(GetLog(LLDBLog::Connection
| LLDBLog::Object
));
86 LLDB_LOGF(log
, "%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()",
87 static_cast<void *>(this));
92 void ConnectionFileDescriptor::OpenCommandPipe() {
95 Log
*log
= GetLog(LLDBLog::Connection
);
96 // Make the command file descriptor here:
97 Status result
= m_pipe
.CreateNew(m_child_processes_inherit
);
98 if (!result
.Success()) {
100 "%p ConnectionFileDescriptor::OpenCommandPipe () - could not "
102 static_cast<void *>(this), result
.AsCString());
105 "%p ConnectionFileDescriptor::OpenCommandPipe() - success "
106 "readfd=%d writefd=%d",
107 static_cast<void *>(this), m_pipe
.GetReadFileDescriptor(),
108 m_pipe
.GetWriteFileDescriptor());
112 void ConnectionFileDescriptor::CloseCommandPipe() {
113 Log
*log
= GetLog(LLDBLog::Connection
);
114 LLDB_LOGF(log
, "%p ConnectionFileDescriptor::CloseCommandPipe()",
115 static_cast<void *>(this));
120 bool ConnectionFileDescriptor::IsConnected() const {
121 return m_io_sp
&& m_io_sp
->IsValid();
124 ConnectionStatus
ConnectionFileDescriptor::Connect(llvm::StringRef path
,
127 path
, [](llvm::StringRef
) {}, error_ptr
);
131 ConnectionFileDescriptor::Connect(llvm::StringRef path
,
132 socket_id_callback_type socket_id_callback
,
134 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
135 Log
*log
= GetLog(LLDBLog::Connection
);
136 LLDB_LOGF(log
, "%p ConnectionFileDescriptor::Connect (url = '%s')",
137 static_cast<void *>(this), path
.str().c_str());
143 error_ptr
->SetErrorString("invalid connect arguments");
144 return eConnectionStatusError
;
147 llvm::StringRef scheme
;
148 std::tie(scheme
, path
) = path
.split("://");
152 llvm::StringSwitch
<ConnectionStatus (ConnectionFileDescriptor::*)(
153 llvm::StringRef
, socket_id_callback_type
, Status
*)>(scheme
)
154 .Case("listen", &ConnectionFileDescriptor::AcceptTCP
)
155 .Cases("accept", "unix-accept",
156 &ConnectionFileDescriptor::AcceptNamedSocket
)
157 .Case("unix-abstract-accept",
158 &ConnectionFileDescriptor::AcceptAbstractSocket
)
159 .Cases("connect", "tcp-connect",
160 &ConnectionFileDescriptor::ConnectTCP
)
161 .Case("udp", &ConnectionFileDescriptor::ConnectUDP
)
162 .Case("unix-connect", &ConnectionFileDescriptor::ConnectNamedSocket
)
163 .Case("unix-abstract-connect",
164 &ConnectionFileDescriptor::ConnectAbstractSocket
)
165 #if LLDB_ENABLE_POSIX
166 .Case("fd", &ConnectionFileDescriptor::ConnectFD
)
167 .Case("file", &ConnectionFileDescriptor::ConnectFile
)
168 .Case("serial", &ConnectionFileDescriptor::ConnectSerialPort
)
174 *error_ptr
= Status();
175 return (this->*method
)(path
, socket_id_callback
, error_ptr
);
180 error_ptr
->SetErrorStringWithFormat("unsupported connection URL: '%s'",
182 return eConnectionStatusError
;
185 bool ConnectionFileDescriptor::InterruptRead() {
186 size_t bytes_written
= 0;
187 Status result
= m_pipe
.Write("i", 1, bytes_written
);
188 return result
.Success();
191 ConnectionStatus
ConnectionFileDescriptor::Disconnect(Status
*error_ptr
) {
192 Log
*log
= GetLog(LLDBLog::Connection
);
193 LLDB_LOGF(log
, "%p ConnectionFileDescriptor::Disconnect ()",
194 static_cast<void *>(this));
196 ConnectionStatus status
= eConnectionStatusSuccess
;
198 if (!IsConnected()) {
200 log
, "%p ConnectionFileDescriptor::Disconnect(): Nothing to disconnect",
201 static_cast<void *>(this));
202 return eConnectionStatusSuccess
;
205 // Try to get the ConnectionFileDescriptor's mutex. If we fail, that is
206 // quite likely because somebody is doing a blocking read on our file
207 // descriptor. If that's the case, then send the "q" char to the command
208 // file channel so the read will wake up and the connection will then know to
210 std::unique_lock
<std::recursive_mutex
> locker(m_mutex
, std::defer_lock
);
211 if (!locker
.try_lock()) {
212 if (m_pipe
.CanWrite()) {
213 size_t bytes_written
= 0;
214 Status result
= m_pipe
.Write("q", 1, bytes_written
);
216 "%p ConnectionFileDescriptor::Disconnect(): Couldn't get "
217 "the lock, sent 'q' to %d, error = '%s'.",
218 static_cast<void *>(this), m_pipe
.GetWriteFileDescriptor(),
222 "%p ConnectionFileDescriptor::Disconnect(): Couldn't get the "
223 "lock, but no command pipe is available.",
224 static_cast<void *>(this));
229 // Prevents reads and writes during shutdown.
230 m_shutting_down
= true;
232 Status error
= m_io_sp
->Close();
234 status
= eConnectionStatusError
;
238 // Close any pipes we were using for async interrupts
242 m_shutting_down
= false;
246 size_t ConnectionFileDescriptor::Read(void *dst
, size_t dst_len
,
247 const Timeout
<std::micro
> &timeout
,
248 ConnectionStatus
&status
,
250 Log
*log
= GetLog(LLDBLog::Connection
);
252 std::unique_lock
<std::recursive_mutex
> locker(m_mutex
, std::defer_lock
);
253 if (!locker
.try_lock()) {
255 "%p ConnectionFileDescriptor::Read () failed to get the "
257 static_cast<void *>(this));
259 error_ptr
->SetErrorString("failed to get the connection lock for read.");
261 status
= eConnectionStatusTimedOut
;
265 if (m_shutting_down
) {
267 error_ptr
->SetErrorString("shutting down");
268 status
= eConnectionStatusError
;
272 status
= BytesAvailable(timeout
, error_ptr
);
273 if (status
!= eConnectionStatusSuccess
)
277 size_t bytes_read
= dst_len
;
278 error
= m_io_sp
->Read(dst
, bytes_read
);
282 "%p ConnectionFileDescriptor::Read() fd = %" PRIu64
283 ", dst = %p, dst_len = %" PRIu64
") => %" PRIu64
", error = %s",
284 static_cast<void *>(this),
285 static_cast<uint64_t>(m_io_sp
->GetWaitableHandle()),
286 static_cast<void *>(dst
), static_cast<uint64_t>(dst_len
),
287 static_cast<uint64_t>(bytes_read
), error
.AsCString());
290 if (bytes_read
== 0) {
291 error
.Clear(); // End-of-file. Do not automatically close; pass along for
292 // the end-of-file handlers.
293 status
= eConnectionStatusEndOfFile
;
300 uint32_t error_value
= error
.GetError();
301 switch (error_value
) {
302 case EAGAIN
: // The file was marked for non-blocking I/O, and no data were
304 if (m_io_sp
->GetFdType() == IOObject::eFDTypeSocket
)
305 status
= eConnectionStatusTimedOut
;
307 status
= eConnectionStatusSuccess
;
310 case EFAULT
: // Buf points outside the allocated address space.
311 case EINTR
: // A read from a slow device was interrupted before any data
312 // arrived by the delivery of a signal.
313 case EINVAL
: // The pointer associated with fildes was negative.
314 case EIO
: // An I/O error occurred while reading from the file system.
315 // The process group is orphaned.
316 // The file is a regular file, nbyte is greater than 0, the
317 // starting position is before the end-of-file, and the
318 // starting position is greater than or equal to the offset
319 // maximum established for the open file descriptor
320 // associated with fildes.
321 case EISDIR
: // An attempt is made to read a directory.
322 case ENOBUFS
: // An attempt to allocate a memory buffer fails.
323 case ENOMEM
: // Insufficient memory is available.
324 status
= eConnectionStatusError
;
325 break; // Break to close....
327 case ENOENT
: // no such file or directory
328 case EBADF
: // fildes is not a valid file or socket descriptor open for
330 case ENXIO
: // An action is requested of a device that does not exist..
331 // A requested action cannot be performed by the device.
332 case ECONNRESET
: // The connection is closed by the peer during a read
333 // attempt on a socket.
334 case ENOTCONN
: // A read is attempted on an unconnected socket.
335 status
= eConnectionStatusLostConnection
;
336 break; // Break to close....
338 case ETIMEDOUT
: // A transmission timeout occurs during a read attempt on a
340 status
= eConnectionStatusTimedOut
;
344 LLDB_LOG(log
, "this = {0}, unexpected error: {1}", this,
345 llvm::sys::StrError(error_value
));
346 status
= eConnectionStatusError
;
347 break; // Break to close....
355 size_t ConnectionFileDescriptor::Write(const void *src
, size_t src_len
,
356 ConnectionStatus
&status
,
358 Log
*log
= GetLog(LLDBLog::Connection
);
360 "%p ConnectionFileDescriptor::Write (src = %p, src_len = %" PRIu64
362 static_cast<void *>(this), static_cast<const void *>(src
),
363 static_cast<uint64_t>(src_len
));
365 if (!IsConnected()) {
367 error_ptr
->SetErrorString("not connected");
368 status
= eConnectionStatusNoConnection
;
372 if (m_shutting_down
) {
374 error_ptr
->SetErrorString("shutting down");
375 status
= eConnectionStatusError
;
381 size_t bytes_sent
= src_len
;
382 error
= m_io_sp
->Write(src
, bytes_sent
);
386 "%p ConnectionFileDescriptor::Write(fd = %" PRIu64
387 ", src = %p, src_len = %" PRIu64
") => %" PRIu64
" (error = %s)",
388 static_cast<void *>(this),
389 static_cast<uint64_t>(m_io_sp
->GetWaitableHandle()),
390 static_cast<const void *>(src
), static_cast<uint64_t>(src_len
),
391 static_cast<uint64_t>(bytes_sent
), error
.AsCString());
398 switch (error
.GetError()) {
401 status
= eConnectionStatusSuccess
;
404 case ECONNRESET
: // The connection is closed by the peer during a read
405 // attempt on a socket.
406 case ENOTCONN
: // A read is attempted on an unconnected socket.
407 status
= eConnectionStatusLostConnection
;
408 break; // Break to close....
411 status
= eConnectionStatusError
;
412 break; // Break to close....
418 status
= eConnectionStatusSuccess
;
422 std::string
ConnectionFileDescriptor::GetURI() { return m_uri
; }
424 // This ConnectionFileDescriptor::BytesAvailable() uses select() via
428 // - select is consistent across most unix platforms
429 // - The Apple specific version allows for unlimited fds in the fd_sets by
430 // setting the _DARWIN_UNLIMITED_SELECT define prior to including the
431 // required header files.
433 // - on non-Apple platforms, only supports file descriptors up to FD_SETSIZE.
434 // This implementation will assert if it runs into that hard limit to let
435 // users know that another ConnectionFileDescriptor::BytesAvailable() should
436 // be used or a new version of ConnectionFileDescriptor::BytesAvailable()
437 // should be written for the system that is running into the limitations.
440 ConnectionFileDescriptor::BytesAvailable(const Timeout
<std::micro
> &timeout
,
442 // Don't need to take the mutex here separately since we are only called from
443 // Read. If we ever get used more generally we will need to lock here as
446 Log
*log
= GetLog(LLDBLog::Connection
);
447 LLDB_LOG(log
, "this = {0}, timeout = {1}", this, timeout
);
449 // Make a copy of the file descriptors to make sure we don't have another
450 // thread change these values out from under us and cause problems in the
451 // loop below where like in FS_SET()
452 const IOObject::WaitableHandle handle
= m_io_sp
->GetWaitableHandle();
453 const int pipe_fd
= m_pipe
.GetReadFileDescriptor();
455 if (handle
!= IOObject::kInvalidHandleValue
) {
456 SelectHelper select_helper
;
458 select_helper
.SetTimeout(*timeout
);
460 select_helper
.FDSetRead(handle
);
462 // select() won't accept pipes on Windows. The entire Windows codepath
463 // needs to be converted over to using WaitForMultipleObjects and event
464 // HANDLEs, but for now at least this will allow ::select() to not return
466 const bool have_pipe_fd
= false;
468 const bool have_pipe_fd
= pipe_fd
>= 0;
471 select_helper
.FDSetRead(pipe_fd
);
473 while (handle
== m_io_sp
->GetWaitableHandle()) {
475 Status error
= select_helper
.Select();
481 switch (error
.GetError()) {
482 case EBADF
: // One of the descriptor sets specified an invalid
484 return eConnectionStatusLostConnection
;
486 case EINVAL
: // The specified time limit is invalid. One of its
487 // components is negative or too large.
488 default: // Other unknown error
489 return eConnectionStatusError
;
492 return eConnectionStatusTimedOut
;
494 case EAGAIN
: // The kernel was (perhaps temporarily) unable to
495 // allocate the requested number of file descriptors, or
496 // we have non-blocking IO
497 case EINTR
: // A signal was delivered before the time limit
498 // expired and before any of the selected events occurred.
499 break; // Lets keep reading to until we timeout
502 if (select_helper
.FDIsSetRead(handle
))
503 return eConnectionStatusSuccess
;
505 if (select_helper
.FDIsSetRead(pipe_fd
)) {
506 // There is an interrupt or exit command in the command pipe Read the
507 // data from that pipe:
511 llvm::sys::RetryAfterSignal(-1, ::read
, pipe_fd
, &c
, 1);
512 assert(bytes_read
== 1);
517 "%p ConnectionFileDescriptor::BytesAvailable() "
518 "got data: %c from the command channel.",
519 static_cast<void *>(this), c
);
520 return eConnectionStatusEndOfFile
;
522 // Interrupt the current read
523 return eConnectionStatusInterrupted
;
531 error_ptr
->SetErrorString("not connected");
532 return eConnectionStatusLostConnection
;
535 lldb::ConnectionStatus
ConnectionFileDescriptor::AcceptSocket(
536 Socket::SocketProtocol socket_protocol
, llvm::StringRef socket_name
,
537 llvm::function_ref
<void(Socket
&)> post_listen_callback
,
540 std::unique_ptr
<Socket
> listening_socket
=
541 Socket::Create(socket_protocol
, m_child_processes_inherit
, error
);
542 Socket
*accepted_socket
;
545 error
= listening_socket
->Listen(socket_name
, 5);
548 post_listen_callback(*listening_socket
);
549 error
= listening_socket
->Accept(accepted_socket
);
553 m_io_sp
.reset(accepted_socket
);
554 m_uri
.assign(socket_name
.str());
555 return eConnectionStatusSuccess
;
560 return eConnectionStatusError
;
563 lldb::ConnectionStatus
564 ConnectionFileDescriptor::ConnectSocket(Socket::SocketProtocol socket_protocol
,
565 llvm::StringRef socket_name
,
568 std::unique_ptr
<Socket
> socket
=
569 Socket::Create(socket_protocol
, m_child_processes_inherit
, error
);
572 error
= socket
->Connect(socket_name
);
575 m_io_sp
= std::move(socket
);
576 m_uri
.assign(socket_name
.str());
577 return eConnectionStatusSuccess
;
582 return eConnectionStatusError
;
585 ConnectionStatus
ConnectionFileDescriptor::AcceptNamedSocket(
586 llvm::StringRef socket_name
, socket_id_callback_type socket_id_callback
,
589 Socket::ProtocolUnixDomain
, socket_name
,
590 [socket_id_callback
, socket_name
](Socket
&listening_socket
) {
591 socket_id_callback(socket_name
);
596 ConnectionStatus
ConnectionFileDescriptor::ConnectNamedSocket(
597 llvm::StringRef socket_name
, socket_id_callback_type socket_id_callback
,
599 return ConnectSocket(Socket::ProtocolUnixDomain
, socket_name
, error_ptr
);
602 ConnectionStatus
ConnectionFileDescriptor::AcceptAbstractSocket(
603 llvm::StringRef socket_name
, socket_id_callback_type socket_id_callback
,
606 Socket::ProtocolUnixAbstract
, socket_name
,
607 [socket_id_callback
, socket_name
](Socket
&listening_socket
) {
608 socket_id_callback(socket_name
);
613 lldb::ConnectionStatus
ConnectionFileDescriptor::ConnectAbstractSocket(
614 llvm::StringRef socket_name
, socket_id_callback_type socket_id_callback
,
616 return ConnectSocket(Socket::ProtocolUnixAbstract
, socket_name
, error_ptr
);
620 ConnectionFileDescriptor::AcceptTCP(llvm::StringRef socket_name
,
621 socket_id_callback_type socket_id_callback
,
623 ConnectionStatus ret
= AcceptSocket(
624 Socket::ProtocolTcp
, socket_name
,
625 [socket_id_callback
](Socket
&listening_socket
) {
627 static_cast<TCPSocket
&>(listening_socket
).GetLocalPortNumber();
628 socket_id_callback(std::to_string(port
));
631 if (ret
== eConnectionStatusSuccess
)
633 static_cast<TCPSocket
*>(m_io_sp
.get())->GetRemoteConnectionURI());
638 ConnectionFileDescriptor::ConnectTCP(llvm::StringRef socket_name
,
639 socket_id_callback_type socket_id_callback
,
641 return ConnectSocket(Socket::ProtocolTcp
, socket_name
, error_ptr
);
645 ConnectionFileDescriptor::ConnectUDP(llvm::StringRef s
,
646 socket_id_callback_type socket_id_callback
,
649 *error_ptr
= Status();
650 llvm::Expected
<std::unique_ptr
<UDPSocket
>> socket
=
651 Socket::UdpConnect(s
, m_child_processes_inherit
);
654 *error_ptr
= socket
.takeError();
656 LLDB_LOG_ERROR(GetLog(LLDBLog::Connection
), socket
.takeError(),
657 "tcp connect failed: {0}");
658 return eConnectionStatusError
;
660 m_io_sp
= std::move(*socket
);
661 m_uri
.assign(std::string(s
));
662 return eConnectionStatusSuccess
;
666 ConnectionFileDescriptor::ConnectFD(llvm::StringRef s
,
667 socket_id_callback_type socket_id_callback
,
669 #if LLDB_ENABLE_POSIX
670 // Just passing a native file descriptor within this current process that
671 // is already opened (possibly from a service or other source).
674 if (!s
.getAsInteger(0, fd
)) {
675 // We have what looks to be a valid file descriptor, but we should make
676 // sure it is. We currently are doing this by trying to get the flags
677 // from the file descriptor and making sure it isn't a bad fd.
679 int flags
= ::fcntl(fd
, F_GETFL
, 0);
680 if (flags
== -1 || errno
== EBADF
) {
682 error_ptr
->SetErrorStringWithFormat("stale file descriptor: %s",
685 return eConnectionStatusError
;
687 // Don't take ownership of a file descriptor that gets passed to us
688 // since someone else opened the file descriptor and handed it to us.
689 // TODO: Since are using a URL to open connection we should
690 // eventually parse options using the web standard where we have
691 // "fd://123?opt1=value;opt2=value" and we can have an option be
692 // "owns=1" or "owns=0" or something like this to allow us to specify
693 // this. For now, we assume we must assume we don't own it.
695 std::unique_ptr
<TCPSocket
> tcp_socket
;
696 tcp_socket
= std::make_unique
<TCPSocket
>(fd
, false, false);
697 // Try and get a socket option from this file descriptor to see if
698 // this is a socket and set m_is_socket accordingly.
701 !!tcp_socket
->GetOption(SOL_SOCKET
, SO_REUSEADDR
, resuse
);
703 m_io_sp
= std::move(tcp_socket
);
706 std::make_shared
<NativeFile
>(fd
, File::eOpenOptionReadWrite
, false);
708 return eConnectionStatusSuccess
;
713 error_ptr
->SetErrorStringWithFormat("invalid file descriptor: \"%s\"",
716 return eConnectionStatusError
;
717 #endif // LLDB_ENABLE_POSIX
718 llvm_unreachable("this function should be only called w/ LLDB_ENABLE_POSIX");
721 ConnectionStatus
ConnectionFileDescriptor::ConnectFile(
722 llvm::StringRef s
, socket_id_callback_type socket_id_callback
,
724 #if LLDB_ENABLE_POSIX
725 std::string addr_str
= s
.str();
727 int fd
= FileSystem::Instance().Open(addr_str
.c_str(), O_RDWR
);
730 error_ptr
->SetErrorToErrno();
731 return eConnectionStatusError
;
735 // Set up serial terminal emulation
736 struct termios options
;
737 ::tcgetattr(fd
, &options
);
739 // Set port speed to maximum
740 ::cfsetospeed(&options
, B115200
);
741 ::cfsetispeed(&options
, B115200
);
743 // Raw input, disable echo and signals
744 options
.c_lflag
&= ~(ICANON
| ECHO
| ECHOE
| ISIG
);
746 // Make sure only one character is needed to return from a read
747 options
.c_cc
[VMIN
] = 1;
748 options
.c_cc
[VTIME
] = 0;
750 llvm::sys::RetryAfterSignal(-1, ::tcsetattr
, fd
, TCSANOW
, &options
);
753 m_io_sp
= std::make_shared
<NativeFile
>(fd
, File::eOpenOptionReadWrite
, true);
754 return eConnectionStatusSuccess
;
755 #endif // LLDB_ENABLE_POSIX
756 llvm_unreachable("this function should be only called w/ LLDB_ENABLE_POSIX");
759 ConnectionStatus
ConnectionFileDescriptor::ConnectSerialPort(
760 llvm::StringRef s
, socket_id_callback_type socket_id_callback
,
762 #if LLDB_ENABLE_POSIX
763 llvm::StringRef path
, qs
;
764 // serial:///PATH?k1=v1&k2=v2...
765 std::tie(path
, qs
) = s
.split('?');
767 llvm::Expected
<SerialPort::Options
> serial_options
=
768 SerialPort::OptionsFromURL(qs
);
769 if (!serial_options
) {
771 *error_ptr
= serial_options
.takeError();
773 llvm::consumeError(serial_options
.takeError());
774 return eConnectionStatusError
;
777 int fd
= FileSystem::Instance().Open(path
.str().c_str(), O_RDWR
);
780 error_ptr
->SetErrorToErrno();
781 return eConnectionStatusError
;
784 llvm::Expected
<std::unique_ptr
<SerialPort
>> serial_sp
= SerialPort::Create(
785 fd
, File::eOpenOptionReadWrite
, serial_options
.get(), true);
788 *error_ptr
= serial_sp
.takeError();
790 llvm::consumeError(serial_sp
.takeError());
791 return eConnectionStatusError
;
793 m_io_sp
= std::move(serial_sp
.get());
795 return eConnectionStatusSuccess
;
796 #endif // LLDB_ENABLE_POSIX
797 llvm_unreachable("this function should be only called w/ LLDB_ENABLE_POSIX");
800 bool ConnectionFileDescriptor::GetChildProcessesInherit() const {
801 return m_child_processes_inherit
;
804 void ConnectionFileDescriptor::SetChildProcessesInherit(
805 bool child_processes_inherit
) {
806 m_child_processes_inherit
= child_processes_inherit
;
809 void ConnectionFileDescriptor::InitializeSocket(Socket
*socket
) {
810 m_io_sp
.reset(socket
);
811 m_uri
= socket
->GetRemoteConnectionURI();