Skip to content

Commit 6ee1560

Browse files
committed
[lldb] Fix write only file action to truncate the file
1 parent b852fb1 commit 6ee1560

File tree

5 files changed

+111
-1
lines changed

5 files changed

+111
-1
lines changed

lldb/source/Host/common/FileAction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ bool FileAction::Open(int fd, const FileSpec &file_spec, bool read,
4141
else if (read)
4242
m_arg = O_NOCTTY | O_RDONLY;
4343
else
44-
m_arg = O_NOCTTY | O_CREAT | O_WRONLY;
44+
m_arg = O_NOCTTY | O_CREAT | O_WRONLY | O_TRUNC;
4545
m_file_spec = file_spec;
4646
return true;
4747
} else {

lldb/test/API/commands/settings/TestSettings.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,59 @@ def test_set_error_output_path(self):
528528
output, exe=False, startstr="This message should go to standard out."
529529
)
530530

531+
@skipIfDarwinEmbedded # <rdar://problem/34446098> debugserver on ios etc can't write files
532+
def test_same_error_output_path(self):
533+
"""Test that setting target.error and output-path to the same file path for the launched process works."""
534+
self.build()
535+
536+
exe = self.getBuildArtifact("a.out")
537+
self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
538+
539+
# Set the error-path and output-path and verify both are set.
540+
self.runCmd(
541+
"settings set target.error-path '{0}'".format(
542+
lldbutil.append_to_process_working_directory(self, "output.txt")
543+
)
544+
)
545+
self.runCmd(
546+
"settings set target.output-path '{0}".format(
547+
lldbutil.append_to_process_working_directory(self, "output.txt")
548+
)
549+
)
550+
# And add hooks to restore the original settings during tearDown().
551+
self.addTearDownHook(lambda: self.runCmd("settings clear target.output-path"))
552+
self.addTearDownHook(lambda: self.runCmd("settings clear target.error-path"))
553+
554+
self.expect(
555+
"settings show target.error-path",
556+
SETTING_MSG("target.error-path"),
557+
substrs=["target.error-path (file)", 'output.txt"'],
558+
)
559+
560+
self.expect(
561+
"settings show target.output-path",
562+
SETTING_MSG("target.output-path"),
563+
substrs=["target.output-path (file)", 'output.txt"'],
564+
)
565+
566+
self.runCmd(
567+
"process launch --working-dir '{0}'".format(
568+
self.get_process_working_directory()
569+
),
570+
RUN_SUCCEEDED,
571+
)
572+
573+
output = lldbutil.read_file_from_process_wd(self, "output.txt")
574+
err_message = "This message should go to standard error."
575+
out_message = "This message should go to standard out."
576+
# Error msg should get flushed by the output msg
577+
self.expect(output, exe=False, substrs=[out_message])
578+
self.assertNotIn(
579+
err_message,
580+
output,
581+
"Race condition when both stderr/stdout redirects to the same file",
582+
)
583+
531584
def test_print_dictionary_setting(self):
532585
self.runCmd("settings clear target.env-vars")
533586
self.runCmd('settings set target.env-vars ["MY_VAR"]=some-value')

lldb/test/API/python_api/process/io/TestProcessIO.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,36 @@ def test_stdout_stderr_redirection(self):
9595
error = self.read_error_file_and_delete()
9696
self.check_process_output(output, error)
9797

98+
@skipIfWindows # stdio manipulation unsupported on Windows
99+
@expectedFlakeyLinux(bugnumber="llvm.org/pr26437")
100+
@skipIfDarwinEmbedded # debugserver can't create/write files on the device
101+
def test_stdout_stderr_redirection_to_existing_files(self):
102+
"""Exercise SBLaunchInfo::AddOpenFileAction() for STDOUT and STDERR without redirecting STDIN to output files already exist."""
103+
self.setup_test()
104+
self.build()
105+
self.create_target()
106+
self.write_file_with_placeholder(self.output_file)
107+
self.write_file_with_placeholder(self.error_file)
108+
self.redirect_stdout()
109+
self.redirect_stderr()
110+
self.run_process(True)
111+
output = self.read_output_file_and_delete()
112+
error = self.read_error_file_and_delete()
113+
self.check_process_output(output, error)
114+
115+
def write_file_with_placeholder(self, target_file):
116+
placeholder = "This content should be overwritten."
117+
if lldb.remote_platform:
118+
self.runCmd(
119+
'platform file write "{target}" -d "{data}"'.format(
120+
target=target_file, data=placeholder
121+
)
122+
)
123+
else:
124+
f = open(target_file, "w")
125+
f.write(placeholder)
126+
f.close()
127+
98128
# target_file - path on local file system or remote file system if running remote
99129
# local_file - path on local system
100130
def read_file_and_delete(self, target_file, local_file):

lldb/unittests/Host/FileActionTest.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include <fcntl.h>
10+
911
#include "lldb/Host/FileAction.h"
1012
#include "gtest/gtest.h"
1113

@@ -17,3 +19,26 @@ TEST(FileActionTest, Open) {
1719
EXPECT_EQ(Action.GetAction(), FileAction::eFileActionOpen);
1820
EXPECT_EQ(Action.GetFileSpec(), FileSpec("/tmp"));
1921
}
22+
23+
TEST(FileActionTest, OpenReadWrite) {
24+
FileAction Action;
25+
Action.Open(48, FileSpec("/tmp_0"), /*read*/ true, /*write*/ true);
26+
EXPECT_TRUE(Action.GetActionArgument() & (O_NOCTTY | O_CREAT | O_RDWR));
27+
EXPECT_FALSE(Action.GetActionArgument() & O_RDONLY);
28+
EXPECT_FALSE(Action.GetActionArgument() & O_WRONLY);
29+
}
30+
31+
TEST(FileActionTest, OpenReadOnly) {
32+
FileAction Action;
33+
Action.Open(49, FileSpec("/tmp_1"), /*read*/ true, /*write*/ false);
34+
EXPECT_TRUE(Action.GetActionArgument() & (O_NOCTTY | O_RDONLY));
35+
EXPECT_FALSE(Action.GetActionArgument() & O_WRONLY);
36+
}
37+
38+
TEST(FileActionTest, OpenWriteOnly) {
39+
FileAction Action;
40+
Action.Open(50, FileSpec("/tmp_2"), /*read*/ false, /*write*/ true);
41+
EXPECT_TRUE(Action.GetActionArgument() &
42+
(O_NOCTTY | O_CREAT | O_WRONLY | O_TRUNC));
43+
EXPECT_FALSE(Action.GetActionArgument() & O_RDONLY);
44+
}

llvm/docs/ReleaseNotes.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,8 @@ Changes to LLDB
273273
* LLDB can now read the `fpmr` register from AArch64 Linux processes and core
274274
files.
275275

276+
* Program stdout/stderr redirection will now open the file with O_TRUNC flag, make sure to truncate the file if path already exists.
277+
* eg. `settings set target.output-path/target.error-path <path/to/file>`
276278

277279
Changes to BOLT
278280
---------------------------------

0 commit comments

Comments
 (0)