From ab4fa2a8200b0e2386570f3b9ffd1ef8675a0292 Mon Sep 17 00:00:00 2001 From: Andrzej Szombierski Date: Mon, 26 Nov 2018 19:28:14 +0100 Subject: [PATCH] fix: ensure that file descriptors 0/1/2 are opened at startup (backport: 3-0-x) (#15781) This fixes an issue where the gpu subprocess was writing messages to a random pipe or socket. The standard file desciptors are closed in chromium's subprocesses because of an unfortunate interaction with libuv's tty handling code leaving them with the FD_CLOEXEC flag. --- atom/app/atom_main.cc | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/atom/app/atom_main.cc b/atom/app/atom_main.cc index d6f3e0a1cfa5..80e06f4efa26 100644 --- a/atom/app/atom_main.cc +++ b/atom/app/atom_main.cc @@ -24,10 +24,14 @@ #include "base/win/windows_version.h" #include "content/public/app/sandbox_helper_win.h" #include "sandbox/win/src/sandbox_types.h" -#elif defined(OS_LINUX) // defined(OS_WIN) +#elif defined(OS_LINUX) // defined(OS_WIN) +#include +#include #include "atom/app/atom_main_delegate.h" // NOLINT #include "content/public/app/content_main.h" #else // defined(OS_LINUX) +#include +#include #include "atom/app/atom_library_main.h" #endif // defined(OS_MACOSX) @@ -55,6 +59,25 @@ bool IsEnvSet(const char* name) { } #endif +#if defined(OS_POSIX) +void FixStdioStreams() { + // libuv may mark stdin/stdout/stderr as close-on-exec, which interferes + // with chromium's subprocess spawning. As a workaround, we detect if these + // streams are closed on startup, and reopen them as /dev/null if necessary. + // Otherwise, an unrelated file descriptor will be assigned as stdout/stderr + // which may cause various errors when attempting to write to them. + // + // For details see https://github.com/libuv/libuv/issues/2062 + struct stat st; + if (fstat(STDIN_FILENO, &st) < 0 && errno == EBADF) + freopen("/dev/null", "r", stdin); + if (fstat(STDOUT_FILENO, &st) < 0 && errno == EBADF) + freopen("/dev/null", "w", stdout); + if (fstat(STDERR_FILENO, &st) < 0 && errno == EBADF) + freopen("/dev/null", "w", stderr); +} +#endif + } // namespace #if defined(OS_WIN) @@ -157,6 +180,8 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) { int main(int argc, char* argv[]) { #ifdef ENABLE_RUN_AS_NODE + FixStdioStreams(); + if (IsEnvSet(kRunAsNode)) { base::i18n::InitializeICU(); base::AtExitManager atexit_manager; @@ -176,6 +201,8 @@ int main(int argc, char* argv[]) { int main(int argc, char* argv[]) { #ifdef ENABLE_RUN_AS_NODE + FixStdioStreams(); + if (IsEnvSet(kRunAsNode)) { return AtomInitializeICUandStartNode(argc, argv); }