From 51cb36fa9b2c9c829050b6612bc6770f048db245 Mon Sep 17 00:00:00 2001 From: Andrzej Szombierski Date: Mon, 19 Nov 2018 17:53:55 +0100 Subject: [PATCH] fix: ensure that file descriptors 0/1/2 are opened at startup (#15555) * fix: ensure that file descriptors 0/1/2 are opened at startup 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. * style: fix lint warnings --- 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 d9baf0dd993f..a739c0926823 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) @@ -54,6 +58,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) @@ -155,6 +178,8 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) { #elif defined(OS_LINUX) // defined(OS_WIN) int main(int argc, char* argv[]) { + FixStdioStreams(); + #if BUILDFLAG(ENABLE_RUN_AS_NODE) if (IsEnvSet(kRunAsNode)) { base::i18n::InitializeICU(); @@ -174,6 +199,8 @@ int main(int argc, char* argv[]) { #else // defined(OS_LINUX) int main(int argc, char* argv[]) { + FixStdioStreams(); + #if BUILDFLAG(ENABLE_RUN_AS_NODE) if (IsEnvSet(kRunAsNode)) { return AtomInitializeICUandStartNode(argc, argv);