• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Keine Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

system/core


Commit MetaInfo

Revision7e1d397d1a0fb9397b91a636dc6a71d132e7286d (tree)
Zeit2019-04-11 03:13:39
AutorAlex Buynytskyy <alexbuy@goog...>
CommiterJosh Gao

Log Message

Binding err to inout for raw protocol for in-process execute.

As raw protocol does not allow for splitting err - it has to be redirected to inout.
Before this change it was not done for in-process and all err data was lost.

Bug: 130086616
Test: manual + atest adbd_test
Change-Id: I6cd11c940673d73e2993a6eb23c46d31bd8bf504
(cherry picked from commit 704c97d6c244093a94e0a39deb0f2265c3bf83dd)

Ändern Zusammenfassung

Diff

--- a/adb/daemon/shell_service.cpp
+++ b/adb/daemon/shell_service.cpp
@@ -406,11 +406,16 @@ bool Subprocess::ExecInProcess(Command command, std::string* _Nonnull error) {
406406 strerror(errno));
407407 return false;
408408 }
409- // Raw subprocess + shell protocol allows for splitting stderr.
410- if (!CreateSocketpair(&stderr_sfd_, &child_stderr_sfd)) {
411- *error = android::base::StringPrintf("failed to create socketpair for stderr: %s",
412- strerror(errno));
413- return false;
409+ if (protocol_ == SubprocessProtocol::kShell) {
410+ // Shell protocol allows for splitting stderr.
411+ if (!CreateSocketpair(&stderr_sfd_, &child_stderr_sfd)) {
412+ *error = android::base::StringPrintf("failed to create socketpair for stderr: %s",
413+ strerror(errno));
414+ return false;
415+ }
416+ } else {
417+ // Raw protocol doesn't support multiple output streams, so combine stdout and stderr.
418+ child_stderr_sfd.reset(dup(child_stdinout_sfd));
414419 }
415420
416421 D("execinprocess: stdin/stdout FD = %d, stderr FD = %d", stdinout_sfd_.get(),
--- a/adb/daemon/shell_service_test.cpp
+++ b/adb/daemon/shell_service_test.cpp
@@ -35,7 +35,6 @@ class ShellServiceTest : public ::testing::Test {
3535 static void SetUpTestCase() {
3636 // This is normally done in main.cpp.
3737 saved_sigpipe_handler_ = signal(SIGPIPE, SIG_IGN);
38-
3938 }
4039
4140 static void TearDownTestCase() {
@@ -49,26 +48,32 @@ class ShellServiceTest : public ::testing::Test {
4948 SubprocessProtocol protocol);
5049 void CleanupTestSubprocess();
5150
52- virtual void TearDown() override {
53- void CleanupTestSubprocess();
54- }
51+ void StartTestCommandInProcess(std::string name, Command command, SubprocessProtocol protocol);
52+
53+ virtual void TearDown() override { CleanupTestSubprocess(); }
5554
5655 static sighandler_t saved_sigpipe_handler_;
5756
58- unique_fd subprocess_fd_;
57+ unique_fd command_fd_;
5958 };
6059
6160 sighandler_t ShellServiceTest::saved_sigpipe_handler_ = nullptr;
6261
6362 void ShellServiceTest::StartTestSubprocess(
6463 const char* command, SubprocessType type, SubprocessProtocol protocol) {
65- subprocess_fd_ = StartSubprocess(command, nullptr, type, protocol);
66- ASSERT_TRUE(subprocess_fd_ >= 0);
64+ command_fd_ = StartSubprocess(command, nullptr, type, protocol);
65+ ASSERT_TRUE(command_fd_ >= 0);
6766 }
6867
6968 void ShellServiceTest::CleanupTestSubprocess() {
7069 }
7170
71+void ShellServiceTest::StartTestCommandInProcess(std::string name, Command command,
72+ SubprocessProtocol protocol) {
73+ command_fd_ = StartCommandInProcess(std::move(name), std::move(command), protocol);
74+ ASSERT_TRUE(command_fd_ >= 0);
75+}
76+
7277 namespace {
7378
7479 // Reads raw data from |fd| until it closes or errors.
@@ -93,7 +98,7 @@ int ReadShellProtocol(int fd, std::string* stdout, std::string* stderr) {
9398 stdout->clear();
9499 stderr->clear();
95100
96- ShellProtocol* protocol = new ShellProtocol(fd);
101+ auto protocol = std::make_unique<ShellProtocol>(fd);
97102 while (protocol->Read()) {
98103 switch (protocol->id()) {
99104 case ShellProtocol::kIdStdout:
@@ -111,7 +116,6 @@ int ReadShellProtocol(int fd, std::string* stdout, std::string* stderr) {
111116 ADD_FAILURE() << "Unidentified packet ID: " << protocol->id();
112117 }
113118 }
114- delete protocol;
115119
116120 return exit_code;
117121 }
@@ -154,7 +158,7 @@ TEST_F(ShellServiceTest, RawNoProtocolSubprocess) {
154158
155159 // [ -t 0 ] == 0 means we have a terminal (PTY). Even when requesting a raw subprocess, without
156160 // the shell protocol we should always force a PTY to ensure proper cleanup.
157- ExpectLinesEqual(ReadRaw(subprocess_fd_), {"foo", "bar", "0"});
161+ ExpectLinesEqual(ReadRaw(command_fd_), {"foo", "bar", "0"});
158162 }
159163
160164 // Tests a PTY subprocess with no protocol.
@@ -165,7 +169,7 @@ TEST_F(ShellServiceTest, PtyNoProtocolSubprocess) {
165169 SubprocessType::kPty, SubprocessProtocol::kNone));
166170
167171 // [ -t 0 ] == 0 means we have a terminal (PTY).
168- ExpectLinesEqual(ReadRaw(subprocess_fd_), {"foo", "bar", "0"});
172+ ExpectLinesEqual(ReadRaw(command_fd_), {"foo", "bar", "0"});
169173 }
170174
171175 // Tests a raw subprocess with the shell protocol.
@@ -175,7 +179,7 @@ TEST_F(ShellServiceTest, RawShellProtocolSubprocess) {
175179 SubprocessType::kRaw, SubprocessProtocol::kShell));
176180
177181 std::string stdout, stderr;
178- EXPECT_EQ(24, ReadShellProtocol(subprocess_fd_, &stdout, &stderr));
182+ EXPECT_EQ(24, ReadShellProtocol(command_fd_, &stdout, &stderr));
179183 ExpectLinesEqual(stdout, {"foo", "baz"});
180184 ExpectLinesEqual(stderr, {"bar"});
181185 }
@@ -189,7 +193,7 @@ TEST_F(ShellServiceTest, PtyShellProtocolSubprocess) {
189193 // PTY always combines stdout and stderr but the shell protocol should
190194 // still give us an exit code.
191195 std::string stdout, stderr;
192- EXPECT_EQ(50, ReadShellProtocol(subprocess_fd_, &stdout, &stderr));
196+ EXPECT_EQ(50, ReadShellProtocol(command_fd_, &stdout, &stderr));
193197 ExpectLinesEqual(stdout, {"foo", "bar", "baz"});
194198 ExpectLinesEqual(stderr, {});
195199 }
@@ -204,7 +208,7 @@ TEST_F(ShellServiceTest, InteractivePtySubprocess) {
204208 "echo --${TEST_STR}--",
205209 "exit"};
206210
207- ShellProtocol* protocol = new ShellProtocol(subprocess_fd_);
211+ ShellProtocol* protocol = new ShellProtocol(command_fd_);
208212 for (std::string command : commands) {
209213 // Interactive shell requires a newline to complete each command.
210214 command.push_back('\n');
@@ -214,7 +218,7 @@ TEST_F(ShellServiceTest, InteractivePtySubprocess) {
214218 delete protocol;
215219
216220 std::string stdout, stderr;
217- EXPECT_EQ(0, ReadShellProtocol(subprocess_fd_, &stdout, &stderr));
221+ EXPECT_EQ(0, ReadShellProtocol(command_fd_, &stdout, &stderr));
218222 // An unpredictable command prompt makes parsing exact output difficult but
219223 // it should at least contain echoed input and the expected output.
220224 for (const char* command : commands) {
@@ -230,14 +234,14 @@ TEST_F(ShellServiceTest, CloseClientStdin) {
230234 SubprocessType::kRaw, SubprocessProtocol::kShell));
231235
232236 std::string input = "foo\nbar";
233- ShellProtocol* protocol = new ShellProtocol(subprocess_fd_);
237+ ShellProtocol* protocol = new ShellProtocol(command_fd_);
234238 memcpy(protocol->data(), input.data(), input.length());
235239 ASSERT_TRUE(protocol->Write(ShellProtocol::kIdStdin, input.length()));
236240 ASSERT_TRUE(protocol->Write(ShellProtocol::kIdCloseStdin, 0));
237241 delete protocol;
238242
239243 std::string stdout, stderr;
240- EXPECT_EQ(0, ReadShellProtocol(subprocess_fd_, &stdout, &stderr));
244+ EXPECT_EQ(0, ReadShellProtocol(command_fd_, &stdout, &stderr));
241245 ExpectLinesEqual(stdout, {"foo", "barTEST_DONE"});
242246 ExpectLinesEqual(stderr, {});
243247 }
@@ -249,7 +253,7 @@ TEST_F(ShellServiceTest, CloseStdinStdoutSubprocess) {
249253 SubprocessType::kRaw, SubprocessProtocol::kShell));
250254
251255 std::string stdout, stderr;
252- EXPECT_EQ(0, ReadShellProtocol(subprocess_fd_, &stdout, &stderr));
256+ EXPECT_EQ(0, ReadShellProtocol(command_fd_, &stdout, &stderr));
253257 ExpectLinesEqual(stdout, {});
254258 ExpectLinesEqual(stderr, {"bar"});
255259 }
@@ -261,7 +265,56 @@ TEST_F(ShellServiceTest, CloseStderrSubprocess) {
261265 SubprocessType::kRaw, SubprocessProtocol::kShell));
262266
263267 std::string stdout, stderr;
264- EXPECT_EQ(0, ReadShellProtocol(subprocess_fd_, &stdout, &stderr));
268+ EXPECT_EQ(0, ReadShellProtocol(command_fd_, &stdout, &stderr));
265269 ExpectLinesEqual(stdout, {"foo"});
266270 ExpectLinesEqual(stderr, {});
267271 }
272+
273+// Tests an inprocess command with no protocol.
274+TEST_F(ShellServiceTest, RawNoProtocolInprocess) {
275+ ASSERT_NO_FATAL_FAILURE(
276+ StartTestCommandInProcess("123",
277+ [](auto args, auto in, auto out, auto err) -> int {
278+ EXPECT_EQ("123", args);
279+ char input[10];
280+ EXPECT_TRUE(ReadFdExactly(in, input, 2));
281+ input[2] = 0;
282+ EXPECT_STREQ("in", input);
283+ WriteFdExactly(out, "out\n");
284+ WriteFdExactly(err, "err\n");
285+ return 0;
286+ },
287+ SubprocessProtocol::kNone));
288+
289+ WriteFdExactly(command_fd_, "in");
290+ ExpectLinesEqual(ReadRaw(command_fd_), {"out", "err"});
291+}
292+
293+// Tests an inprocess command with the shell protocol.
294+TEST_F(ShellServiceTest, RawShellProtocolInprocess) {
295+ ASSERT_NO_FATAL_FAILURE(
296+ StartTestCommandInProcess("321",
297+ [](auto args, auto in, auto out, auto err) -> int {
298+ EXPECT_EQ("321", args);
299+ char input[10];
300+ EXPECT_TRUE(ReadFdExactly(in, input, 2));
301+ input[2] = 0;
302+ EXPECT_STREQ("in", input);
303+ WriteFdExactly(out, "out\n");
304+ WriteFdExactly(err, "err\n");
305+ return 0;
306+ },
307+ SubprocessProtocol::kShell));
308+
309+ {
310+ auto write_protocol = std::make_unique<ShellProtocol>(command_fd_);
311+ memcpy(write_protocol->data(), "in", 2);
312+ write_protocol->Write(ShellProtocol::kIdStdin, 2);
313+ }
314+
315+ std::string stdout, stderr;
316+ // For in-process commands the exit code is always the default (1).
317+ EXPECT_EQ(1, ReadShellProtocol(command_fd_, &stdout, &stderr));
318+ ExpectLinesEqual(stdout, {"out"});
319+ ExpectLinesEqual(stderr, {"err"});
320+}