xcbuild: fix interactive applications run by xcrun

Fixes #358795

+143
+2
pkgs/by-name/xc/xcbuild/package.nix
··· 84 84 ./patches/Use-system-toolchain-for-usr-bin.patch 85 85 # Suppress warnings due to newer SDKs with unknown keys 86 86 ./patches/Suppress-unknown-key-warnings.patch 87 + # Don't pipe stdout / stderr of processes launched by xcrun 88 + ./patches/fix-interactive-apps.patch 87 89 ]; 88 90 89 91 prePatch = ''
+141
pkgs/by-name/xc/xcbuild/patches/fix-interactive-apps.patch
··· 1 + diff --git a/Libraries/process/Headers/process/DefaultLauncher.h b/Libraries/process/Headers/process/DefaultLauncher.h 2 + index cee6e145..698ffe84 100644 3 + --- a/Libraries/process/Headers/process/DefaultLauncher.h 4 + +++ b/Libraries/process/Headers/process/DefaultLauncher.h 5 + @@ -20,11 +20,14 @@ namespace process { 6 + */ 7 + class DefaultLauncher : public Launcher { 8 + public: 9 + - DefaultLauncher(); 10 + + DefaultLauncher(bool sync_output); 11 + ~DefaultLauncher(); 12 + 13 + public: 14 + virtual ext::optional<int> launch(libutil::Filesystem *filesystem, Context const *context); 15 + + 16 + +private: 17 + + bool sync_output_; 18 + }; 19 + 20 + } 21 + diff --git a/Libraries/process/Sources/DefaultLauncher.cpp b/Libraries/process/Sources/DefaultLauncher.cpp 22 + index a7f14e1a..e9aaf330 100644 23 + --- a/Libraries/process/Sources/DefaultLauncher.cpp 24 + +++ b/Libraries/process/Sources/DefaultLauncher.cpp 25 + @@ -91,9 +91,18 @@ EscapedToken(const WideString &token) 26 + } 27 + #endif 28 + 29 + +namespace { 30 + + enum class PipeStatus { 31 + + UNUSED, 32 + + CREATED, 33 + + ERROR 34 + + }; 35 + +} 36 + + 37 + DefaultLauncher:: 38 + -DefaultLauncher() : 39 + - Launcher() 40 + +DefaultLauncher(bool sync_output) : 41 + + Launcher(), 42 + + sync_output_{sync_output} 43 + { 44 + } 45 + 46 + @@ -199,10 +208,14 @@ launch(Filesystem *filesystem, Context const *context) 47 + 48 + /* Setup parent-child stdout/stderr pipe. */ 49 + int pfd[2]; 50 + - bool pipe_setup_success = true; 51 + - if (pipe(pfd) == -1) { 52 + - ::perror("pipe"); 53 + - pipe_setup_success = false; 54 + + PipeStatus pipe_status = PipeStatus::UNUSED; 55 + + if (sync_output_) { 56 + + if (pipe(pfd) == -1) { 57 + + ::perror("pipe"); 58 + + pipe_status = PipeStatus::ERROR; 59 + + } else { 60 + + pipe_status = PipeStatus::CREATED; 61 + + } 62 + } 63 + 64 + /* 65 + @@ -214,22 +227,25 @@ launch(Filesystem *filesystem, Context const *context) 66 + return ext::nullopt; 67 + } else if (pid == 0) { 68 + /* Fork succeeded, new process. */ 69 + - if (pipe_setup_success) { 70 + - /* Setup pipe to parent, redirecting both stdout and stderr */ 71 + - dup2(pfd[1], STDOUT_FILENO); 72 + - dup2(pfd[1], STDERR_FILENO); 73 + - close(pfd[0]); 74 + - close(pfd[1]); 75 + - } else { 76 + - /* No parent-child pipe setup, just ignore outputs from child */ 77 + - int nullfd = open("/dev/null", O_WRONLY); 78 + - if (nullfd == -1) { 79 + - ::perror("open"); 80 + - ::_exit(1); 81 + - } 82 + - dup2(nullfd, STDOUT_FILENO); 83 + - dup2(nullfd, STDERR_FILENO); 84 + - close(nullfd); 85 + + switch (pipe_status) { 86 + + case PipeStatus::CREATED: 87 + + /* Setup pipe to parent, redirecting both stdout and stderr */ 88 + + dup2(pfd[1], STDOUT_FILENO); 89 + + dup2(pfd[1], STDERR_FILENO); 90 + + close(pfd[0]); 91 + + close(pfd[1]); 92 + + break; 93 + + case PipeStatus::ERROR: 94 + + /* No parent-child pipe setup, just ignore outputs from child */ 95 + + int nullfd = open("/dev/null", O_WRONLY); 96 + + if (nullfd == -1) { 97 + + ::perror("open"); 98 + + ::_exit(1); 99 + + } 100 + + dup2(nullfd, STDOUT_FILENO); 101 + + dup2(nullfd, STDERR_FILENO); 102 + + close(nullfd); 103 + + break; 104 + } 105 + 106 + if (::chdir(cDirectory) == -1) { 107 + @@ -243,7 +259,7 @@ launch(Filesystem *filesystem, Context const *context) 108 + return ext::nullopt; 109 + } else { 110 + /* Fork succeeded, existing process. */ 111 + - if (pipe_setup_success) { 112 + + if (pipe_status == PipeStatus::CREATED) { 113 + close(pfd[1]); 114 + /* Read child's stdout/stderr through pipe, and output stdout */ 115 + while (true) { 116 + diff --git a/Libraries/xcdriver/Tools/xcbuild.cpp b/Libraries/xcdriver/Tools/xcbuild.cpp 117 + index 3a1baadc..c9340ff5 100644 118 + --- a/Libraries/xcdriver/Tools/xcbuild.cpp 119 + +++ b/Libraries/xcdriver/Tools/xcbuild.cpp 120 + @@ -19,7 +19,7 @@ main(int argc, char **argv) 121 + { 122 + DefaultFilesystem filesystem = DefaultFilesystem(); 123 + process::DefaultContext processContext = process::DefaultContext(); 124 + - process::DefaultLauncher processLauncher = process::DefaultLauncher(); 125 + + process::DefaultLauncher processLauncher = process::DefaultLauncher(true); 126 + process::DefaultUser user = process::DefaultUser(); 127 + return xcdriver::Driver::Run(&user, &processContext, &processLauncher, &filesystem); 128 + } 129 + diff --git a/Libraries/xcsdk/Tools/xcrun.cpp b/Libraries/xcsdk/Tools/xcrun.cpp 130 + index 9d6d4576..c177b273 100644 131 + --- a/Libraries/xcsdk/Tools/xcrun.cpp 132 + +++ b/Libraries/xcsdk/Tools/xcrun.cpp 133 + @@ -469,7 +469,7 @@ main(int argc, char **argv) 134 + { 135 + DefaultFilesystem filesystem = DefaultFilesystem(); 136 + process::DefaultContext processContext = process::DefaultContext(); 137 + - process::DefaultLauncher processLauncher = process::DefaultLauncher(); 138 + + process::DefaultLauncher processLauncher = process::DefaultLauncher(false); 139 + process::DefaultUser user = process::DefaultUser(); 140 + return Run(&filesystem, &user, &processContext, &processLauncher); 141 + }