]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
Improve the failed() and fatal() mechanisms
authorJoel Rosdahl <joel@rosdahl.net>
Sat, 8 Feb 2020 22:19:18 +0000 (23:19 +0100)
committerJoel Rosdahl <joel@rosdahl.net>
Sat, 8 Feb 2020 22:19:18 +0000 (23:19 +0100)
The failure() and fatal() functions now exit by throwing exceptions that
are caught by the top level functions. This makes it possible to “throw
Failure” in functions that don’t have access to orig_args (or the future
context object).

While at it, renamed top-level functions to better reflect their
purpose.

20 files changed:
dev.mk.in
src/AtomicFile.cpp
src/CacheEntryReader.cpp
src/CacheFile.hpp
src/Compression.cpp
src/Config.cpp
src/Error.hpp [deleted file]
src/NullCompressor.cpp
src/NullDecompressor.cpp
src/Stat.hpp
src/ZstdCompressor.cpp
src/ZstdDecompressor.cpp
src/ccache.cpp
src/exceptions.hpp [new file with mode: 0644]
src/legacy_util.cpp
src/legacy_util.hpp
src/logging.cpp
src/logging.hpp
src/result.cpp
unittest/test_Config.cpp

index 7e726ad43418f46476f6e7fd78e346e7470b3422..8032083ef5e204a4d39be1e1d2b41cf3df634716 100644 (file)
--- a/dev.mk.in
+++ b/dev.mk.in
@@ -36,7 +36,6 @@ built_dist_files = $(generated_sources) $(generated_docs)
 
 non_third_party_headers_without_cpp = \
     src/Checksum.hpp \
-    src/Error.hpp \
     src/File.hpp \
     src/FormatNonstdStringView.hpp \
     src/NonCopyable.hpp \
@@ -47,6 +46,7 @@ non_third_party_headers_without_cpp = \
     src/Stat.hpp \
     src/StdMakeUnique.hpp \
     src/ThreadPool.hpp \
+    src/exceptions.hpp \
     src/macroskip.hpp \
     src/system.hpp \
     unittest/framework.hpp \
index 9dad3a3924d520e32e356b52512a7cd12f7e17f6..3626f4517607e9d85675b89c767c8ae8dcff5442 100644 (file)
@@ -18,7 +18,7 @@
 
 #include "AtomicFile.hpp"
 
-#include "Error.hpp"
+#include "exceptions.hpp"
 #include "Util.hpp"
 
 #include "third_party/fmt/core.h"
index 28090780b455c73412c2308bfd052d233f4fb538..1772e1a8813fdee2e27a7703cadb2509ae8d259d 100644 (file)
@@ -19,7 +19,7 @@
 #include "CacheEntryReader.hpp"
 
 #include "Compressor.hpp"
-#include "Error.hpp"
+#include "exceptions.hpp"
 
 #include "third_party/fmt/core.h"
 
index 0c98d337d4ab59b7e1bbde8d6db49452cad1988a..d684f69115ed0faca682382220cde690b5605116 100644 (file)
@@ -20,7 +20,7 @@
 
 #include "system.hpp"
 
-#include "Error.hpp"
+#include "exceptions.hpp"
 #include "Stat.hpp"
 
 #include "third_party/fmt/core.h"
index 08d50e530844c1bc4049f1a3455768e6069b4ec0..ecf93fc370393c82a189751a6c573462e3335123 100644 (file)
@@ -19,7 +19,7 @@
 #include "Compression.hpp"
 
 #include "Config.hpp"
-#include "Error.hpp"
+#include "exceptions.hpp"
 
 namespace Compression {
 
index d786fdd16475ea499e640c06bdac4359840652f2..bfaef8da520c5651aba0f3351d681ef18c700af3 100644 (file)
@@ -19,7 +19,7 @@
 #include "Config.hpp"
 
 #include "AtomicFile.hpp"
-#include "Error.hpp"
+#include "exceptions.hpp"
 #include "Util.hpp"
 #include "ccache.hpp"
 
diff --git a/src/Error.hpp b/src/Error.hpp
deleted file mode 100644 (file)
index 0e155e3..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (C) 2019 Joel Rosdahl and other contributors
-//
-// See doc/AUTHORS.adoc for a complete list of contributors.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License as published by the Free
-// Software Foundation; either version 3 of the License, or (at your option)
-// any later version.
-//
-// This program is distributed in the hope that it will be useful, but WITHOUT
-// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-// more details.
-//
-// You should have received a copy of the GNU General Public License along with
-// this program; if not, write to the Free Software Foundation, Inc., 51
-// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
-#pragma once
-
-#include "system.hpp"
-
-#include <stdexcept>
-
-class Error : public std::runtime_error
-{
-  using std::runtime_error::runtime_error;
-};
index f54438df702896015a2244eb6acd291e92adb14d..9757fd984eab2c12dbf0501bf9bb43c21a6c3566 100644 (file)
@@ -18,7 +18,7 @@
 
 #include "NullCompressor.hpp"
 
-#include "Error.hpp"
+#include "exceptions.hpp"
 
 NullCompressor::NullCompressor(FILE* stream) : m_stream(stream)
 {
index 789de4fa0bc3f623066602d9d645ce8c7dd5dd02..090bdf5d1fad749f3eabe9f52277294f4a925d9b 100644 (file)
@@ -18,7 +18,7 @@
 
 #include "NullDecompressor.hpp"
 
-#include "Error.hpp"
+#include "exceptions.hpp"
 
 NullDecompressor::NullDecompressor(FILE* stream) : m_stream(stream)
 {
index 8f78a3d68686a09c890cb5f9619e1f72065bc7bb..7eb0251018913a151cea48b620caf419621d886d 100644 (file)
@@ -20,7 +20,7 @@
 
 #include "system.hpp"
 
-#include "Error.hpp"
+#include "exceptions.hpp"
 
 #include <string>
 
index a5d16854b6d2b4ef203242e74fa2d3695d4d70d5..beaa5896dc9af4dc39ea88ffe11d3189874e2589 100644 (file)
@@ -18,7 +18,7 @@
 
 #include "ZstdCompressor.hpp"
 
-#include "Error.hpp"
+#include "exceptions.hpp"
 #include "logging.hpp"
 
 const uint8_t k_default_zstd_compression_level = -1;
index 9b8658602e4b973b55281dcf5639e02acc65627b..75a8b16617f86d0f3b318c07fe0df3c582cb4104 100644 (file)
@@ -18,7 +18,7 @@
 
 #include "ZstdDecompressor.hpp"
 
-#include "Error.hpp"
+#include "exceptions.hpp"
 
 ZstdDecompressor::ZstdDecompressor(FILE* stream)
   : m_stream(stream),
index b807e1cc60707b95b1cbf888f8ba52f9fa88e745..79e60e117f83761e8bb4c27edfcedaa1f13fc78a 100644 (file)
@@ -20,7 +20,6 @@
 #include "ccache.hpp"
 
 #include "ArgsInfo.hpp"
-#include "Error.hpp"
 #include "FormatNonstdStringView.hpp"
 #include "ProgressBar.hpp"
 #include "ScopeGuard.hpp"
@@ -29,6 +28,7 @@
 #include "cleanup.hpp"
 #include "compopt.hpp"
 #include "compress.hpp"
+#include "exceptions.hpp"
 #include "execute.hpp"
 #include "exitfn.hpp"
 #include "hash.hpp"
@@ -186,22 +186,13 @@ add_prefix(struct args* args, const char* prefix_command)
   args_free(prefix);
 }
 
-static void failed(void) ATTR_NORETURN;
+static void failed(enum stats stat = STATS_NONE) ATTR_NORETURN;
 
 // Something went badly wrong - just execute the real compiler.
 static void
-failed(void)
+failed(enum stats stat)
 {
-  assert(orig_args);
-
-  args_strip(orig_args, "--ccache-");
-  add_prefix(orig_args, g_config.prefix_command().c_str());
-
-  cc_log("Failed; falling back to running the real compiler");
-  cc_log_argv("Executing ", orig_args->argv);
-  exitfn_call();
-  execv(orig_args->argv[0], orig_args->argv);
-  fatal("execv of %s failed: %s", orig_args->argv[0], strerror(errno));
+  throw Failure(stat);
 }
 
 static const char*
@@ -3603,11 +3594,12 @@ configuration_printer(const std::string& key,
   fmt::print("({}) {} = {}\n", origin, key, value);
 }
 
-static void ccache(int argc, char* argv[]) ATTR_NORETURN;
+static void cache_compilation(int argc, char* argv[]) ATTR_NORETURN;
+static void do_cache_compilation(char* argv[]) ATTR_NORETURN;
 
-// The main ccache driver function.
+// The entry point when invoked to cache a compilation.
 static void
-ccache(int argc, char* argv[])
+cache_compilation(int argc, char* argv[])
 {
 #ifndef _WIN32
   set_up_signal_handlers();
@@ -3619,10 +3611,34 @@ ccache(int argc, char* argv[])
   orig_args = args_init(argc, argv);
 
   initialize();
+
   MTR_BEGIN("main", "find_compiler");
   find_compiler(argv);
   MTR_END("main", "find_compiler");
 
+  try {
+    do_cache_compilation(argv);
+  } catch (const Failure& e) {
+    if (e.stat() != STATS_NONE) {
+      stats_update(e.stat());
+    }
+
+    assert(orig_args);
+
+    args_strip(orig_args, "--ccache-");
+    add_prefix(orig_args, g_config.prefix_command().c_str());
+
+    cc_log("Failed; falling back to running the real compiler");
+    cc_log_argv("Executing ", orig_args->argv);
+    exitfn_call();
+    execv(orig_args->argv[0], orig_args->argv);
+    fatal("execv of %s failed: %s", orig_args->argv[0], strerror(errno));
+  }
+}
+
+static void
+do_cache_compilation(char* argv[])
+{
   MTR_BEGIN("main", "clean_up_internal_tempdir");
   if (g_config.temporary_dir().empty()) {
     clean_up_internal_tempdir();
@@ -3856,7 +3872,7 @@ ccache(int argc, char* argv[])
 
 // The main program when not doing a compile.
 static int
-ccache_main_options(int argc, char* argv[])
+handle_main_options(int argc, char* argv[])
 {
   enum longopts {
     DUMP_MANIFEST,
@@ -4061,13 +4077,13 @@ ccache_main(int argc, char* argv[])
       // If the first argument isn't an option, then assume we are being passed
       // a compiler name and options.
       if (argv[1][0] == '-') {
-        return ccache_main_options(argc, argv);
+        return handle_main_options(argc, argv);
       }
     }
 
-    ccache(argc, argv);
-  } catch (const Error& e) {
-    fmt::print("ccache: error: {}\n", e.what());
-    return 1;
+    cache_compilation(argc, argv);
+  } catch (const ErrorBase& e) {
+    fmt::print(stderr, "ccache: error: {}\n", e.what());
+    return EXIT_FAILURE;
   }
 }
diff --git a/src/exceptions.hpp b/src/exceptions.hpp
new file mode 100644 (file)
index 0000000..f9bb78b
--- /dev/null
@@ -0,0 +1,69 @@
+// Copyright (C) 2019-2020 Joel Rosdahl and other contributors
+//
+// See doc/AUTHORS.adoc for a complete list of contributors.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Software Foundation, Inc., 51
+// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#pragma once
+
+#include "system.hpp"
+
+#include "stats.hpp"
+
+#include <stdexcept>
+
+// Don't throw or catch ErrorBase directly, use a subclass.
+class ErrorBase : public std::runtime_error
+{
+  using std::runtime_error::runtime_error;
+};
+
+// Throw an Error to indicate a potentially non-fatal error that may be caught
+// and handled by callers. An uncaught Error that reaches the top level will be
+// treated similar to FatalError.
+class Error : public ErrorBase
+{
+  using ErrorBase::ErrorBase;
+};
+
+// Throw a FatalError to make ccache print the error message to stderr and exit
+// with a non-zero exit code.
+class FatalError : public ErrorBase
+{
+  using ErrorBase::ErrorBase;
+};
+
+// Throw a Failure to make ccache fall back to running the real compiler. Also
+// updates statistics counter `stat` if it's not STATS_NONE.
+class Failure : public std::exception
+{
+public:
+  Failure(enum stats stat = STATS_NONE);
+
+  enum stats stat() const;
+
+private:
+  enum stats m_stat;
+};
+
+inline Failure::Failure(enum stats stat) : m_stat(stat)
+{
+}
+
+inline enum stats
+Failure::stat() const
+{
+  return m_stat;
+}
index 8aee912c3c2cbe5b80a25285a9a64d9b3d20c655..728aeb0da805355f7b24bbaabce8cf048014b24b 100644 (file)
@@ -19,8 +19,8 @@
 
 #include "legacy_util.hpp"
 
-#include "Error.hpp"
 #include "Util.hpp"
+#include "exceptions.hpp"
 #include "logging.hpp"
 
 #include "third_party/fmt/core.h"
@@ -85,10 +85,7 @@ fatal(const char* format, ...)
   vsnprintf(msg, sizeof(msg), format, ap);
   va_end(ap);
 
-  cc_log("FATAL: %s", msg);
-  fprintf(stderr, "ccache: error: %s\n", msg);
-
-  x_exit(1);
+  throw FatalError(msg);
 }
 
 // Copy all data from fd_in to fd_out.
index d18266ecb4f28f7c30078e2300d730d454c15a37..55f8902c2a1f3c196d5f4784c793ee74e45dd808 100644 (file)
@@ -22,6 +22,8 @@
 
 #include <string>
 
+void fatal(const char* format, ...) ATTR_FORMAT(printf, 1, 2) ATTR_NORETURN;
+
 bool copy_fd(int fd_in, int fd_out);
 bool clone_file(const char* src, const char* dest, bool via_tmp_file);
 bool copy_file(const char* src, const char* dest, bool via_tmp_file);
index 44f5a6d3c48675f6d0dd4f409994bfed0b0fa233..cfcd8198011467ca81b2799ecc8b7922ff3f260a 100644 (file)
@@ -20,6 +20,7 @@
 #include "logging.hpp"
 
 #include "Config.hpp"
+#include "exceptions.hpp"
 #include "execute.hpp"
 
 #ifdef HAVE_SYSLOG_H
index c0ca0d87a556f3e539277cd792f53e17a236a1d9..e80be653d5ad7e497bc0ff0713a7bad32c3f2238 100644 (file)
@@ -26,4 +26,3 @@ void cc_log(const char* format, ...) ATTR_FORMAT(printf, 1, 2);
 void cc_bulklog(const char* format, ...) ATTR_FORMAT(printf, 1, 2);
 void cc_log_argv(const char* prefix, char** argv);
 void cc_dump_debug_log_buffer(const char* path);
-void fatal(const char* format, ...) ATTR_FORMAT(printf, 1, 2) ATTR_NORETURN;
index d60903632a3d3d9d647c2f518adbbb9b6be87667..971567f09d3c4b33d6cdc1ece8316ab250b6b8f9 100644 (file)
@@ -22,7 +22,7 @@
 #include "CacheEntryReader.hpp"
 #include "CacheEntryWriter.hpp"
 #include "Config.hpp"
-#include "Error.hpp"
+#include "exceptions.hpp"
 #include "File.hpp"
 #include "Stat.hpp"
 #include "Util.hpp"
index c3e485fd9cbc0f856f939cf7a2205baf783b444c..5496f7faac80a79f044af975e4e693a4ace1cdbc 100644 (file)
@@ -17,7 +17,7 @@
 // Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
 #include "../src/Config.hpp"
-#include "../src/Error.hpp"
+#include "../src/exceptions.hpp"
 #include "../src/Util.hpp"
 #include "../src/ccache.hpp"