aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build2/b.cxx83
-rw-r--r--libbuild2/build/script/parser.test.cxx2
-rw-r--r--libbuild2/function.test.cxx2
-rw-r--r--libbuild2/make-parser.test.cxx2
-rw-r--r--libbuild2/test/script/parser.test.cxx2
-rw-r--r--libbuild2/utility.cxx87
-rw-r--r--libbuild2/utility.hxx14
-rw-r--r--tests/libbuild2/driver.cxx2
8 files changed, 109 insertions, 85 deletions
diff --git a/build2/b.cxx b/build2/b.cxx
index 304b58e..e636a9d 100644
--- a/build2/b.cxx
+++ b/build2/b.cxx
@@ -1,16 +1,6 @@
// file : build2/b.cxx -*- C++ -*-
// license : MIT; see accompanying LICENSE file
-#ifndef _WIN32
-# include <signal.h> // signal()
-#else
-# include <libbutl/win32-utility.hxx>
-#endif
-
-#ifdef __GLIBCXX__
-# include <locale>
-#endif
-
#include <sstream>
#include <typeinfo>
#include <iostream> // cout
@@ -171,59 +161,9 @@ main (int argc, char* argv[])
tracer trace ("main");
- int r (0);
-
- // This is a little hack to make out baseutils for Windows work when called
- // with absolute path. In a nutshell, MSYS2's exec*p() doesn't search in the
- // parent's executable directory, only in PATH. And since we are running
- // without a shell (that would read /etc/profile which sets PATH to some
- // sensible values), we are only getting Win32 PATH values. And MSYS2 /bin
- // is not one of them. So what we are going to do is add /bin at the end of
- // PATH (which will be passed as is by the MSYS2 machinery). This will make
- // MSYS2 search in /bin (where our baseutils live). And for everyone else
- // this should be harmless since it is not a valid Win32 path.
- //
-#ifdef _WIN32
- {
- string mp;
- if (optional<string> p = getenv ("PATH"))
- {
- mp = move (*p);
- mp += ';';
- }
- mp += "/bin";
-
- setenv ("PATH", mp);
- }
-#endif
-
- // A data race happens in the libstdc++ (as of GCC 7.2) implementation of
- // the ctype<char>::narrow() function (bug #77704). The issue is easily
- // triggered by the testscript runner that indirectly (via regex) uses
- // ctype<char> facet of the global locale (and can potentially be triggered
- // by other locale-aware code). We work around this by pre-initializing the
- // global locale facet internal cache.
- //
-#ifdef __GLIBCXX__
- {
- const ctype<char>& ct (use_facet<ctype<char>> (locale ()));
-
- for (size_t i (0); i != 256; ++i)
- ct.narrow (static_cast<char> (i), '\0');
- }
-#endif
-
- // On POSIX ignore SIGPIPE which is signaled to a pipe-writing process if
- // the pipe reading end is closed. Note that by default this signal
- // terminates a process. Also note that there is no way to disable this
- // behavior on a file descriptor basis or for the write() function call.
- //
-#ifndef _WIN32
- if (signal (SIGPIPE, SIG_IGN) == SIG_ERR)
- fail << "unable to ignore broken pipe (SIGPIPE) signal: "
- << system_error (errno, generic_category ()); // Sanitize.
-#endif
+ init_process ();
+ int r (0);
options ops;
scheduler sched;
@@ -314,32 +254,15 @@ main (int argc, char* argv[])
}
}
- // Initialize time conversion data that is used by localtime_r().
- //
-#ifndef _WIN32
- tzset ();
-#else
- _tzset ();
-#endif
-
// Initialize the global state.
//
init (&::terminate,
argv[0],
+ ops.serial_stop (),
cmdl.mtime_check,
cmdl.config_sub,
cmdl.config_guess);
-#ifdef _WIN32
- // On Windows disable displaying error reporting dialog box for the
- // current and child processes unless we are in the stop mode. Failed that
- // we may have multiple dialog boxes popping up.
- //
- if (!ops.serial_stop ())
- SetErrorMode (SetErrorMode (0) | // Returns the current mode.
- SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
-#endif
-
// Load builtin modules.
//
load_builtin_module (&config::build2_config_load);
diff --git a/libbuild2/build/script/parser.test.cxx b/libbuild2/build/script/parser.test.cxx
index 63d41ff..5808015 100644
--- a/libbuild2/build/script/parser.test.cxx
+++ b/libbuild2/build/script/parser.test.cxx
@@ -176,7 +176,7 @@ namespace build2
// Fake build system driver, default verbosity.
//
init_diag (1);
- init (nullptr, argv[0]);
+ init (nullptr, argv[0], true);
// Serial execution.
//
diff --git a/libbuild2/function.test.cxx b/libbuild2/function.test.cxx
index 0b3c922..f711d2f 100644
--- a/libbuild2/function.test.cxx
+++ b/libbuild2/function.test.cxx
@@ -44,7 +44,7 @@ namespace build2
// Fake build system driver, default verbosity.
//
init_diag (1);
- init (nullptr, argv[0]);
+ init (nullptr, argv[0], true);
// Serial execution.
//
diff --git a/libbuild2/make-parser.test.cxx b/libbuild2/make-parser.test.cxx
index 5c57978..00a265a 100644
--- a/libbuild2/make-parser.test.cxx
+++ b/libbuild2/make-parser.test.cxx
@@ -22,7 +22,7 @@ namespace build2
// Fake build system driver, default verbosity.
//
init_diag (1);
- init (nullptr, argv[0]);
+ init (nullptr, argv[0], true);
path_name in ("<stdin>");
diff --git a/libbuild2/test/script/parser.test.cxx b/libbuild2/test/script/parser.test.cxx
index eb4a59b..e0dd3d2 100644
--- a/libbuild2/test/script/parser.test.cxx
+++ b/libbuild2/test/script/parser.test.cxx
@@ -162,7 +162,7 @@ namespace build2
// Fake build system driver, default verbosity.
//
init_diag (1);
- init (nullptr, argv[0]);
+ init (nullptr, argv[0], true);
// Serial execution.
//
diff --git a/libbuild2/utility.cxx b/libbuild2/utility.cxx
index 3f89def..31be3aa 100644
--- a/libbuild2/utility.cxx
+++ b/libbuild2/utility.cxx
@@ -3,8 +3,18 @@
#include <libbuild2/utility.hxx>
+#ifndef _WIN32
+# include <signal.h> // signal()
+#else
+# include <libbutl/win32-utility.hxx>
+#endif
+
#include <time.h> // tzset() (POSIX), _tzset() (Windows)
+#ifdef __GLIBCXX__
+# include <locale>
+#endif
+
#include <cerrno> // ENOENT
#include <cstring> // strlen(), str[n]cmp()
#include <iostream> // cerr
@@ -551,8 +561,73 @@ namespace build2
}
void
+ init_process ()
+ {
+ // This is a little hack to make out baseutils for Windows work when
+ // called with absolute path. In a nutshell, MSYS2's exec*p() doesn't
+ // search in the parent's executable directory, only in PATH. And since we
+ // are running without a shell (that would read /etc/profile which sets
+ // PATH to some sensible values), we are only getting Win32 PATH values.
+ // And MSYS2 /bin is not one of them. So what we are going to do is add
+ // /bin at the end of PATH (which will be passed as is by the MSYS2
+ // machinery). This will make MSYS2 search in /bin (where our baseutils
+ // live). And for everyone else this should be harmless since it is not a
+ // valid Win32 path.
+ //
+#ifdef _WIN32
+ {
+ string mp;
+ if (optional<string> p = getenv ("PATH"))
+ {
+ mp = move (*p);
+ mp += ';';
+ }
+ mp += "/bin";
+
+ setenv ("PATH", mp);
+ }
+#endif
+
+ // On POSIX ignore SIGPIPE which is signaled to a pipe-writing process if
+ // the pipe reading end is closed. Note that by default this signal
+ // terminates a process. Also note that there is no way to disable this
+ // behavior on a file descriptor basis or for the write() function call.
+ //
+#ifndef _WIN32
+ if (signal (SIGPIPE, SIG_IGN) == SIG_ERR)
+ fail << "unable to ignore broken pipe (SIGPIPE) signal: "
+ << system_error (errno, generic_category ()); // Sanitize.
+#endif
+
+ // Initialize time conversion data that is used by localtime_r().
+ //
+#ifndef _WIN32
+ tzset ();
+#else
+ _tzset ();
+#endif
+
+ // A data race happens in the libstdc++ (as of GCC 7.2) implementation of
+ // the ctype<char>::narrow() function (bug #77704). The issue is easily
+ // triggered by the testscript runner that indirectly (via regex) uses
+ // ctype<char> facet of the global locale (and can potentially be
+ // triggered by other locale-aware code). We work around this by
+ // pre-initializing the global locale facet internal cache.
+ //
+#ifdef __GLIBCXX__
+ {
+ const ctype<char>& ct (use_facet<ctype<char>> (locale ()));
+
+ for (size_t i (0); i != 256; ++i)
+ ct.narrow (static_cast<char> (i), '\0');
+ }
+#endif
+ }
+
+ void
init (void (*t) (bool),
const char* a0,
+ bool ss,
optional<bool> mc,
optional<path> cs,
optional<path> cg)
@@ -587,6 +662,18 @@ namespace build2
}
script::regex::init ();
+
+ if (!ss)
+ {
+#ifdef _WIN32
+ // On Windows disable displaying error reporting dialog box for the
+ // current and child processes unless we are in the stop mode. Failed
+ // that we may have multiple dialog boxes popping up.
+ //
+ SetErrorMode (SetErrorMode (0) | // Returns the current mode.
+ SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
+#endif
+ }
}
optional<uint64_t>
diff --git a/libbuild2/utility.hxx b/libbuild2/utility.hxx
index b62d2ab..c82dcc2 100644
--- a/libbuild2/utility.hxx
+++ b/libbuild2/utility.hxx
@@ -97,6 +97,19 @@ namespace build2
//
using butl::path_pattern;
+ // Perform process-wide initializations/adjustments/workarounds. Should be
+ // called once early in main(). In particular, besides other things, this
+ // functions does the following:
+ //
+ // - Sets PATH to include baseutils /bin on Windows.
+ //
+ // - Ignores SIGPIPE.
+ //
+ // - Calls tzset().
+ //
+ LIBBUILD2_SYMEXPORT void
+ init_process ();
+
// Diagnostics state (verbosity level, etc; see <libbuild2/diagnostics.hxx>).
//
// Note on naming of values (here and in the global state below) that come
@@ -138,6 +151,7 @@ namespace build2
LIBBUILD2_SYMEXPORT void
init (void (*terminate) (bool),
const char* argv0,
+ bool serial_stop,
optional<bool> mtime_check = nullopt,
optional<path> config_sub = nullopt,
optional<path> config_guess = nullopt);
diff --git a/tests/libbuild2/driver.cxx b/tests/libbuild2/driver.cxx
index dafb38e..6201a6c 100644
--- a/tests/libbuild2/driver.cxx
+++ b/tests/libbuild2/driver.cxx
@@ -32,7 +32,7 @@ main (int, char* argv[])
// Fake build system driver, default verbosity.
//
init_diag (1);
- init (nullptr, argv[0]);
+ init (nullptr, argv[0], true);
load_builtin_module (&config::build2_config_load);
load_builtin_module (&dist::build2_dist_load);