From 1e9a75d9f20d77ef5ce2377d652efb1a7d0cec7e Mon Sep 17 00:00:00 2001 From: Andrzej Szombierski Date: Thu, 1 Nov 2018 00:50:26 +0200 Subject: [PATCH] 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. --- atom/app/atom_main.cc | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/atom/app/atom_main.cc b/atom/app/atom_main.cc index d6f3e0a1cfa5..85675e11edd7 100644 --- a/atom/app/atom_main.cc +++ b/atom/app/atom_main.cc @@ -25,9 +25,13 @@ #include "content/public/app/sandbox_helper_win.h" #include "sandbox/win/src/sandbox_types.h" #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); }