Skip to content

Conversation

@ashgti
Copy link
Contributor

@ashgti ashgti commented Nov 21, 2025

This updates the EditlineTest to use lldb::FileSP to ensure the associated FDs are only closed a single time.

Currently, there is some confusion between the FilePointer, PseudoTerminal and LockableStreamFile about when the files are closed resulting in a crash in some due to a fflush on a closed file.

This updates the EditlineTest to use `lldb::FileSP` to ensure the associated FDs are only closed a single time.

Currently, there is some confusion between the `FilePointer`, `PseudoTerminal` and `LockableStreamFile` about when the files are closed resulting in a crash in some due to a `fflush` on a closed file.
@ashgti ashgti requested a review from cmtice November 21, 2025 21:37
@ashgti ashgti requested a review from JDevlieghere as a code owner November 21, 2025 21:37
@llvmbot llvmbot added the lldb label Nov 21, 2025
@llvmbot
Copy link
Member

llvmbot commented Nov 21, 2025

@llvm/pr-subscribers-lldb

Author: John Harrison (ashgti)

Changes

This updates the EditlineTest to use lldb::FileSP to ensure the associated FDs are only closed a single time.

Currently, there is some confusion between the FilePointer, PseudoTerminal and LockableStreamFile about when the files are closed resulting in a crash in some due to a fflush on a closed file.


Full diff: https://github.com/llvm/llvm-project/pull/169100.diff

1 Files Affected:

  • (modified) lldb/unittests/Editline/EditlineTest.cpp (+28-58)
diff --git a/lldb/unittests/Editline/EditlineTest.cpp b/lldb/unittests/Editline/EditlineTest.cpp
index 2875f4ee7e6b4..2afc33680f348 100644
--- a/lldb/unittests/Editline/EditlineTest.cpp
+++ b/lldb/unittests/Editline/EditlineTest.cpp
@@ -9,6 +9,8 @@
 #include "lldb/Host/Config.h"
 #include "lldb/Host/File.h"
 #include "lldb/Host/HostInfo.h"
+#include "lldb/lldb-forward.h"
+#include "llvm/Testing/Support/Error.h"
 
 #if LLDB_ENABLE_LIBEDIT
 
@@ -25,7 +27,6 @@
 #include "TestingSupport/SubsystemRAII.h"
 #include "lldb/Host/Editline.h"
 #include "lldb/Host/FileSystem.h"
-#include "lldb/Host/Pipe.h"
 #include "lldb/Host/PseudoTerminal.h"
 #include "lldb/Host/StreamFile.h"
 #include "lldb/Utility/Status.h"
@@ -37,27 +38,6 @@ namespace {
 const size_t TIMEOUT_MILLIS = 5000;
 }
 
-class FilePointer {
-public:
-  FilePointer() = delete;
-
-  FilePointer(const FilePointer &) = delete;
-
-  FilePointer(FILE *file_p) : _file_p(file_p) {}
-
-  ~FilePointer() {
-    if (_file_p != nullptr) {
-      const int close_result = fclose(_file_p);
-      EXPECT_EQ(0, close_result);
-    }
-  }
-
-  operator FILE *() { return _file_p; }
-
-private:
-  FILE *_file_p;
-};
-
 /**
  Wraps an Editline class, providing a simple way to feed
  input (as if from the keyboard) and receive output from Editline.
@@ -90,44 +70,39 @@ class EditlineAdapter {
   std::recursive_mutex output_mutex;
   std::unique_ptr<lldb_private::Editline> _editline_sp;
 
-  PseudoTerminal _pty;
-  int _pty_primary_fd = -1;
-  int _pty_secondary_fd = -1;
-
-  std::unique_ptr<FilePointer> _el_secondary_file;
+  lldb::FileSP _el_primary_file;
+  lldb::FileSP _el_secondary_file;
 };
 
-EditlineAdapter::EditlineAdapter()
-    : _editline_sp(), _pty(), _el_secondary_file() {
+EditlineAdapter::EditlineAdapter() : _editline_sp(), _el_secondary_file() {
   lldb_private::Status error;
+  PseudoTerminal pty;
 
   // Open the first primary pty available.
-  EXPECT_THAT_ERROR(_pty.OpenFirstAvailablePrimary(O_RDWR), llvm::Succeeded());
+  EXPECT_THAT_ERROR(pty.OpenFirstAvailablePrimary(O_RDWR), llvm::Succeeded());
+  // Open the corresponding secondary pty.
+  EXPECT_THAT_ERROR(pty.OpenSecondary(O_RDWR), llvm::Succeeded());
 
   // Grab the primary fd.  This is a file descriptor we will:
   // (1) write to when we want to send input to editline.
   // (2) read from when we want to see what editline sends back.
-  _pty_primary_fd = _pty.GetPrimaryFileDescriptor();
+  _el_primary_file.reset(
+      new NativeFile(pty.ReleasePrimaryFileDescriptor(),
+                     lldb_private::NativeFile::eOpenOptionReadWrite, true));
 
-  // Open the corresponding secondary pty.
-  EXPECT_THAT_ERROR(_pty.OpenSecondary(O_RDWR), llvm::Succeeded());
-  _pty_secondary_fd = _pty.GetSecondaryFileDescriptor();
-
-  _el_secondary_file.reset(new FilePointer(fdopen(_pty_secondary_fd, "rw")));
-  EXPECT_FALSE(nullptr == *_el_secondary_file);
-  if (*_el_secondary_file == nullptr)
-    return;
+  _el_secondary_file.reset(
+      new NativeFile(pty.ReleaseSecondaryFileDescriptor(),
+                     lldb_private::NativeFile::eOpenOptionReadWrite, true));
 
   lldb::LockableStreamFileSP output_stream_sp =
-      std::make_shared<LockableStreamFile>(*_el_secondary_file,
-                                           NativeFile::Unowned, output_mutex);
+      std::make_shared<LockableStreamFile>(_el_secondary_file, output_mutex);
   lldb::LockableStreamFileSP error_stream_sp =
-      std::make_shared<LockableStreamFile>(*_el_secondary_file,
-                                           NativeFile::Unowned, output_mutex);
+      std::make_shared<LockableStreamFile>(_el_secondary_file, output_mutex);
 
   // Create an Editline instance.
   _editline_sp.reset(new lldb_private::Editline(
-      "gtest editor", *_el_secondary_file, output_stream_sp, error_stream_sp,
+      "gtest editor", _el_secondary_file->GetStream(), output_stream_sp,
+      error_stream_sp,
       /*color=*/false));
   _editline_sp->SetPrompt("> ");
 
@@ -140,7 +115,7 @@ EditlineAdapter::EditlineAdapter()
 
 void EditlineAdapter::CloseInput() {
   if (_el_secondary_file != nullptr)
-    _el_secondary_file.reset(nullptr);
+    _el_secondary_file->Close();
 }
 
 bool EditlineAdapter::SendLine(const std::string &line) {
@@ -148,19 +123,14 @@ bool EditlineAdapter::SendLine(const std::string &line) {
   if (!IsValid())
     return false;
 
+  std::string out = line + "\n";
+
   // Write the line out to the pipe connected to editline's input.
-  ssize_t input_bytes_written =
-      ::write(_pty_primary_fd, line.c_str(),
-              line.length() * sizeof(std::string::value_type));
-
-  const char *eoln = "\n";
-  const size_t eoln_length = strlen(eoln);
-  input_bytes_written =
-      ::write(_pty_primary_fd, eoln, eoln_length * sizeof(char));
-
-  EXPECT_NE(-1, input_bytes_written) << strerror(errno);
-  EXPECT_EQ(eoln_length * sizeof(char), size_t(input_bytes_written));
-  return eoln_length * sizeof(char) == size_t(input_bytes_written);
+  size_t num_bytes = out.length() * sizeof(std::string::value_type);
+  EXPECT_THAT_ERROR(_el_primary_file->Write(out.c_str(), num_bytes).takeError(),
+                    llvm::Succeeded());
+  EXPECT_EQ(num_bytes, out.length() * sizeof(std::string::value_type));
+  return true;
 }
 
 bool EditlineAdapter::SendLines(const std::vector<std::string> &lines) {
@@ -215,7 +185,7 @@ bool EditlineAdapter::IsInputComplete(lldb_private::Editline *editline,
 }
 
 void EditlineAdapter::ConsumeAllOutput() {
-  FilePointer output_file(fdopen(_pty_primary_fd, "r"));
+  FILE *output_file = _el_primary_file->GetStream();
 
   int ch;
   while ((ch = fgetc(output_file)) != EOF) {

@github-actions
Copy link

🐧 Linux x64 Test Results

  • 33166 tests passed
  • 491 tests skipped

@ashgti ashgti merged commit 7e6c913 into llvm:main Nov 21, 2025
12 checks passed
aadeshps-mcw pushed a commit to aadeshps-mcw/llvm-project that referenced this pull request Nov 26, 2025
This updates the EditlineTest to use `lldb::FileSP` to ensure the
associated FDs are only closed a single time.

Currently, there is some confusion between the `FilePointer`,
`PseudoTerminal` and `LockableStreamFile` about when the files are
closed resulting in a crash in some due to a `fflush` on a closed file.
Priyanshu3820 pushed a commit to Priyanshu3820/llvm-project that referenced this pull request Nov 26, 2025
This updates the EditlineTest to use `lldb::FileSP` to ensure the
associated FDs are only closed a single time.

Currently, there is some confusion between the `FilePointer`,
`PseudoTerminal` and `LockableStreamFile` about when the files are
closed resulting in a crash in some due to a `fflush` on a closed file.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants