LLDB  mainline
PseudoTerminal.cpp
Go to the documentation of this file.
1 //===-- PseudoTerminal.cpp ------------------------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
10 #include "lldb/Host/Config.h"
11 #include "llvm/Support/Errc.h"
12 #include "llvm/Support/Errno.h"
13 #include <cassert>
14 #include <climits>
15 #include <cstdio>
16 #include <cstdlib>
17 #include <cstring>
18 #include <mutex>
19 #if defined(TIOCSCTTY)
20 #include <sys/ioctl.h>
21 #endif
22 
23 #include "lldb/Host/PosixApi.h"
24 
25 #if defined(__ANDROID__)
26 int posix_openpt(int flags);
27 #endif
28 
29 using namespace lldb_private;
30 
31 // PseudoTerminal constructor
33 
34 // Destructor
35 //
36 // The destructor will close the primary and secondary file descriptors if they
37 // are valid and ownership has not been released using the
38 // ReleasePrimaryFileDescriptor() or the ReleaseSaveFileDescriptor() member
39 // functions.
43 }
44 
45 // Close the primary file descriptor if it is valid.
47  if (m_primary_fd >= 0) {
48  ::close(m_primary_fd);
50  }
51 }
52 
53 // Close the secondary file descriptor if it is valid.
55  if (m_secondary_fd >= 0) {
56  ::close(m_secondary_fd);
58  }
59 }
60 
62 #if LLDB_ENABLE_POSIX
63  // Open the primary side of a pseudo terminal
65  if (m_primary_fd < 0) {
66  return llvm::errorCodeToError(
67  std::error_code(errno, std::generic_category()));
68  }
69 
70  // Grant access to the secondary pseudo terminal
71  if (::grantpt(m_primary_fd) < 0) {
72  std::error_code EC(errno, std::generic_category());
74  return llvm::errorCodeToError(EC);
75  }
76 
77  // Clear the lock flag on the secondary pseudo terminal
78  if (::unlockpt(m_primary_fd) < 0) {
79  std::error_code EC(errno, std::generic_category());
81  return llvm::errorCodeToError(EC);
82  }
83 
84  return llvm::Error::success();
85 #else
86  return llvm::errorCodeToError(llvm::errc::not_supported);
87 #endif
88 }
89 
92 
94  m_secondary_fd = llvm::sys::RetryAfterSignal(-1, ::open, name.c_str(), oflag);
95  if (m_secondary_fd >= 0)
96  return llvm::Error::success();
97 
98  return llvm::errorCodeToError(
99  std::error_code(errno, std::generic_category()));
100 }
101 
103  assert(m_primary_fd >= 0);
104 #if HAVE_PTSNAME_R
105  char buf[PATH_MAX];
106  buf[0] = '\0';
107  int r = ptsname_r(m_primary_fd, buf, sizeof(buf));
108  (void)r;
109  assert(r == 0);
110  return buf;
111 #else
112  static std::mutex mutex;
113  std::lock_guard<std::mutex> guard(mutex);
114  const char *r = ptsname(m_primary_fd);
115  assert(r != nullptr);
116  return r;
117 #endif
118 }
119 
120 llvm::Expected<lldb::pid_t> PseudoTerminal::Fork() {
121 #if LLDB_ENABLE_POSIX
122  if (llvm::Error Err = OpenFirstAvailablePrimary(O_RDWR | O_CLOEXEC))
123  return std::move(Err);
124 
125  pid_t pid = ::fork();
126  if (pid < 0) {
127  return llvm::errorCodeToError(
128  std::error_code(errno, std::generic_category()));
129  }
130  if (pid > 0) {
131  // Parent process.
132  return pid;
133  }
134 
135  // Child Process
136  ::setsid();
137 
138  if (llvm::Error Err = OpenSecondary(O_RDWR))
139  return std::move(Err);
140 
141  // Primary FD should have O_CLOEXEC set, but let's close it just in
142  // case...
144 
145 #if defined(TIOCSCTTY)
146  // Acquire the controlling terminal
147  if (::ioctl(m_secondary_fd, TIOCSCTTY, (char *)0) < 0) {
148  return llvm::errorCodeToError(
149  std::error_code(errno, std::generic_category()));
150  }
151 #endif
152  // Duplicate all stdio file descriptors to the secondary pseudo terminal
153  for (int fd : {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO}) {
154  if (::dup2(m_secondary_fd, fd) != fd) {
155  return llvm::errorCodeToError(
156  std::error_code(errno, std::generic_category()));
157  }
158  }
159 #endif
160  return 0;
161 }
162 
163 // The primary file descriptor accessor. This object retains ownership of the
164 // primary file descriptor when this accessor is used. Use
165 // ReleasePrimaryFileDescriptor() if you wish this object to release ownership
166 // of the primary file descriptor.
167 //
168 // Returns the primary file descriptor, or -1 if the primary file descriptor is
169 // not currently valid.
171 
172 // The secondary file descriptor accessor.
173 //
174 // Returns the secondary file descriptor, or -1 if the secondary file descriptor
175 // is not currently valid.
177  return m_secondary_fd;
178 }
179 
180 // Release ownership of the primary pseudo terminal file descriptor without
181 // closing it. The destructor for this class will close the primary file
182 // descriptor if the ownership isn't released using this call and the primary
183 // file descriptor has been opened.
185  // Release ownership of the primary pseudo terminal file descriptor without
186  // closing it. (the destructor for this class will close it otherwise!)
187  int fd = m_primary_fd;
189  return fd;
190 }
191 
192 // Release ownership of the secondary pseudo terminal file descriptor without
193 // closing it. The destructor for this class will close the secondary file
194 // descriptor if the ownership isn't released using this call and the secondary
195 // file descriptor has been opened.
197  // Release ownership of the secondary pseudo terminal file descriptor without
198  // closing it (the destructor for this class will close it otherwise!)
199  int fd = m_secondary_fd;
201  return fd;
202 }
lldb_private::PseudoTerminal::ReleaseSecondaryFileDescriptor
int ReleaseSecondaryFileDescriptor()
Release the secondary file descriptor.
Definition: PseudoTerminal.cpp:196
lldb_private::PseudoTerminal::m_secondary_fd
int m_secondary_fd
The file descriptor for the secondary.
Definition: PseudoTerminal.h:179
lldb_private::PseudoTerminal::GetPrimaryFileDescriptor
int GetPrimaryFileDescriptor() const
The primary file descriptor accessor.
Definition: PseudoTerminal.cpp:170
unlockpt
int unlockpt(int fd)
Definition: windows/PosixApi.h:117
lldb_private::PseudoTerminal::invalid_fd
@ invalid_fd
Invalid file descriptor value.
Definition: PseudoTerminal.h:27
lldb_private::PseudoTerminal::m_primary_fd
int m_primary_fd
The file descriptor for the primary.
Definition: PseudoTerminal.h:178
lldb_private::PseudoTerminal::GetSecondaryFileDescriptor
int GetSecondaryFileDescriptor() const
The secondary file descriptor accessor.
Definition: PseudoTerminal.cpp:176
lldb_private::PseudoTerminal::OpenFirstAvailablePrimary
llvm::Error OpenFirstAvailablePrimary(int oflag)
Open the first available pseudo terminal.
Definition: PseudoTerminal.cpp:61
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:40
lldb_private::PseudoTerminal::OpenSecondary
llvm::Error OpenSecondary(int oflag)
Open the secondary for the current primary pseudo terminal.
Definition: PseudoTerminal.cpp:90
lldb_private::PseudoTerminal::ClosePrimaryFileDescriptor
void ClosePrimaryFileDescriptor()
Close the primary file descriptor if it is valid.
Definition: PseudoTerminal.cpp:46
lldb_private::PseudoTerminal::GetSecondaryName
std::string GetSecondaryName() const
Get the name of the secondary pseudo terminal.
Definition: PseudoTerminal.cpp:102
posix_openpt
int posix_openpt(int flag)
Definition: windows/PosixApi.h:111
lldb_private::PseudoTerminal::ReleasePrimaryFileDescriptor
int ReleasePrimaryFileDescriptor()
Release the primary file descriptor.
Definition: PseudoTerminal.cpp:184
lldb_private::PseudoTerminal::CloseSecondaryFileDescriptor
void CloseSecondaryFileDescriptor()
Close the secondary file descriptor if it is valid.
Definition: PseudoTerminal.cpp:54
lldb_private::PseudoTerminal::PseudoTerminal
PseudoTerminal()
Default constructor.
setsid
pid_t setsid(void)
Definition: windows/PosixApi.h:122
lldb::pid_t
uint64_t pid_t
Definition: lldb-types.h:85
lldb_private::PseudoTerminal::~PseudoTerminal
~PseudoTerminal()
Destructor.
Definition: PseudoTerminal.cpp:40
PseudoTerminal.h
lldb_private::PseudoTerminal::Fork
llvm::Expected< lldb::pid_t > Fork()
Fork a child process that uses pseudo terminals for its stdio.
Definition: PseudoTerminal.cpp:120
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
ptsname
char * ptsname(int fd)
Definition: windows/PosixApi.h:119
fork
pid_t fork(void)
Definition: windows/PosixApi.h:121
Error
llvm::Error Error
Definition: UdtRecordCompleter.cpp:29
PosixApi.h
grantpt
int grantpt(int fd)
Definition: windows/PosixApi.h:118
PATH_MAX
#define PATH_MAX
Definition: windows/PosixApi.h:25