Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package ccache for openSUSE:Factory checked 
in at 2024-02-28 19:45:10
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ccache (Old)
 and      /work/SRC/openSUSE:Factory/.ccache.new.1770 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "ccache"

Wed Feb 28 19:45:10 2024 rev:76 rq:1152216 version:4.9.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/ccache/ccache.changes    2024-01-19 
23:00:19.553925187 +0100
+++ /work/SRC/openSUSE:Factory/.ccache.new.1770/ccache.changes  2024-02-28 
19:45:33.486402286 +0100
@@ -1,0 +2,12 @@
+Tue Feb 27 10:33:09 UTC 2024 - ming li <m...@suse.com>
+
+- Update to 4.9.1:
+  * Improved detection of bad remote storage URLs gracefully. This also fixes
+    crashes seen in ccache’s own test suite.
+  * Made caching completely disabled when modification of a source or include
+    file is detected during ccache invocation. Previously this was only done 
for the direct mode.
+  * Fixed an MSVC crash when using /Zi with many concurrent compilations.
+  * Fixed a crash when -arch is the last compiler option.
+- Drop no longer needed fix2038.patch
+
+-------------------------------------------------------------------

Old:
----
  ccache-4.9.tar.xz
  ccache-4.9.tar.xz.asc
  fix2038.patch

New:
----
  ccache-4.9.1.tar.xz
  ccache-4.9.1.tar.xz.asc

BETA DEBUG BEGIN:
  Old:  * Fixed a crash when -arch is the last compiler option.
- Drop no longer needed fix2038.patch
BETA DEBUG END:

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ ccache.spec ++++++
--- /var/tmp/diff_new_pack.3sRuTC/_old  2024-02-28 19:45:34.158426544 +0100
+++ /var/tmp/diff_new_pack.3sRuTC/_new  2024-02-28 19:45:34.162426688 +0100
@@ -23,7 +23,7 @@
 %bcond_with hiredis
 %endif
 Name:           ccache
-Version:        4.9
+Version:        4.9.1
 Release:        0
 Summary:        A Fast C/C++ Compiler Cache
 License:        GPL-3.0-or-later
@@ -45,7 +45,6 @@
 BuildRequires:  rubygem(asciidoctor)
 Provides:       distcc:%{_bindir}/ccache
 %ifnarch %{ix86} %{arm}
-Patch0:         fix2038.patch
 %endif
 %if %{with hiredis}
 BuildRequires:  pkgconfig(hiredis) >= 0.13.3

++++++ ccache-4.9.tar.xz -> ccache-4.9.1.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ccache-4.9/LICENSE.adoc new/ccache-4.9.1/LICENSE.adoc
--- old/ccache-4.9/LICENSE.adoc 2023-12-30 16:08:02.000000000 +0100
+++ new/ccache-4.9.1/LICENSE.adoc       2024-02-05 20:29:52.000000000 +0100
@@ -35,7 +35,7 @@
 
 ----
 Copyright (C) 2002-2007 Andrew Tridgell
-Copyright (C) 2009-2023 Joel Rosdahl and other contributors
+Copyright (C) 2009-2024 Joel Rosdahl and other contributors
 ----
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ccache-4.9/cmake/CcacheVersion.cmake 
new/ccache-4.9.1/cmake/CcacheVersion.cmake
--- old/ccache-4.9/cmake/CcacheVersion.cmake    2023-12-30 16:08:02.000000000 
+0100
+++ new/ccache-4.9.1/cmake/CcacheVersion.cmake  2024-02-05 20:29:52.000000000 
+0100
@@ -22,7 +22,7 @@
 # CCACHE_VERSION_ORIGIN is set to "archive" in scenario 1 and "git" in scenario
 # 3.
 
-set(version_info "d65ba0b384f1df970e573fab8f5325399d9e3900 HEAD, tag: v4.9, 
origin/master, origin/HEAD, master")
+set(version_info "ec510e9b0f333b8e97aee98108de3e0858340d59 HEAD, tag: v4.9.1, 
origin/HEAD, origin/4.9-maint, 4.9-maint")
 set(CCACHE_VERSION "unknown")
 
 if(version_info MATCHES 
"^([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f])[0-9a-f]* 
(.*)")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ccache-4.9/doc/MANUAL.adoc 
new/ccache-4.9.1/doc/MANUAL.adoc
--- old/ccache-4.9/doc/MANUAL.adoc      2023-12-30 16:08:02.000000000 +0100
+++ new/ccache-4.9.1/doc/MANUAL.adoc    2024-02-05 20:29:52.000000000 +0100
@@ -1027,13 +1027,15 @@
     directory in the `.gcno` file. *gcno_cwd* also disables hashing of the
     current working directory if `-fprofile-abs-path` is used.
 *include_file_ctime*::
-    By default, ccache will disable the direct mode if an include file has too
-    new ctime. This sloppiness disables that check. See also _<<Handling of
-    newly created header files>>_.
+    By default, ccache will disable caching if a source code file has a status
+    change time (ctime) after the start of the ccache invocation. This
+    sloppiness disables that check. See also _<<Handling of newly created 
source
+    files>>_.
 *include_file_mtime*::
-    By default, ccache will disable the direct mode if an include file has too
-    new mtime. This sloppiness disables that check. See also _<<Handling of
-    newly created header files>>_.
+    By default, ccache will disable caching if a source code file has a
+    modification time (mtime) after the start of the ccache invocation. This
+    sloppiness disables that check. See also _<<Handling of newly created 
source
+    files>>_.
 *ivfsoverlay*::
     Ignore the Clang compiler option `-ivfsoverlay` and its argument. This is
     useful if you use Xcode, which uses a virtual file system (VFS) for things
@@ -1429,6 +1431,9 @@
 Preconditions for using <<Precompiled headers,precompiled headers>> were not
 fulfilled.
 
+| Could not read or parse input file |
+An input file could not be read or parsed (see the debug log for details).
+
 | Could not write to output file |
 The output path specified with `-o` could not be written to.
 
@@ -1457,6 +1462,9 @@
 | Forced recache |
 <<config_recache,*CCACHE_RECACHE*>> was used to overwrite an existing result.
 
+| Input file modified during compilation |
+An input file was modified during compilation.
+
 | Internal error |
 Unexpected failure, e.g. due to problems reading/writing the cache.
 
@@ -1631,31 +1639,23 @@
   `/showIncludes` is added automatically if not specified by the user).
 
 
-== Handling of newly created header files
+== Handling of newly created source files
 
-If modification time (mtime) or status change time (ctime) of one of the 
include
-files is equal to (or newer than) the time compilation is being done, ccache
-disables the direct mode (or, in the case of a <<Precompiled 
headers,precompiled
-header>>, disables caching completely). This done as a safety measure to avoid 
a
-race condition (see below).
-
-To be able to use a newly created header files in direct mode (or use a newly
-precompiled header), either:
-
-* create the include file earlier in the build process, or
-* set <<config_sloppiness,*sloppiness*>> to
-  *include_file_ctime,include_file_mtime* if you are willing to take the risk,
-  for instance if you know that your build system is robust enough not to
-  trigger the race condition.
+If modification time (mtime) or status change time (ctime) of the source file 
or
+one of the include files is equal to (or newer than) the time that ccache was
+invoked, ccache disables caching completely. This is done as a safety measure 
to
+avoid a race condition (see below). In practice, this is only a problem when
+using file systems with very low timestamp granularity. You can set
+<<config_sloppiness,*sloppiness*>> to *include_file_ctime,include_file_mtime* 
to
+opt out of the safety measure.
 
 For reference, the race condition mentioned above consists of these events:
 
-1. The preprocessor is run.
-2. An include file is modified by someone.
-3. The new include file is hashed by ccache.
-4. The real compiler is run on the preprocessor's output, which contains data
-   from the old header file.
-5. The wrong object file is stored in the cache.
+1. A source code file is read by ccache and added to the input hash.
+2. The source code file is modified.
+3. The compiler is executed and reads the modified source code.
+4. Ccache stores the compiler output in the cache associated with the incorrect
+   key (based on the unmodified source code).
 
 
 == Cache debugging
@@ -1767,7 +1767,7 @@
   works in combination with precompiled headers.
 * You may also want to include *include_file_mtime,include_file_ctime* in
   <<config_sloppiness,*sloppiness*>>. See
-  _<<Handling of newly created header files>>_.
+  _<<Handling of newly created source files>>_.
 * You must either:
 +
 --
@@ -1932,9 +1932,8 @@
    `-Wp,-MMD,<path>`, and `-Wp,-D<define>`) is used.
 ** This was the first compilation with a new value of the
    <<config_base_dir,base directory>>.
-** A modification or status change time of one of the include files is too new
-   (created the same second as the compilation is being done). See
-   _<<Handling of newly created header files>>_.
+** A modification or status change time of one of the include files is too new 
.
+   See _<<Handling of newly created source files>>_.
 ** The `+__TIME__+` preprocessor macro is (potentially) being used. Ccache 
turns
    off direct mode if `+__TIME__+` is present in the source code. This is done
    as a safety measure since the string indicates that a `+__TIME__+` macro
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ccache-4.9/doc/NEWS.adoc 
new/ccache-4.9.1/doc/NEWS.adoc
--- old/ccache-4.9/doc/NEWS.adoc        2023-12-30 16:08:02.000000000 +0100
+++ new/ccache-4.9.1/doc/NEWS.adoc      2024-02-05 20:29:52.000000000 +0100
@@ -1,5 +1,27 @@
 = Ccache news
 
+== Ccache 4.9.1
+
+Release date: 2024-02-05
+
+=== Bug fixes
+
+- Improved detection of bad remote storage URLs gracefully. This also fixes
+  crashes seen in ccache's own test suite. +
+  [small]#_[contributed by Joel Rosdahl]_#
+
+- Made caching completely disabled when modification of a source or include 
file
+  is detected during ccache invocation. Previously this was only done for the
+  direct mode. +
+  [small]#_[contributed by Joel Rosdahl]_#
+
+- Fixed a MSVC crash when using `/Zi` with many concurrent compilations. +
+  [small]#_[contributed by Joel Rosdahl]_#
+
+- Fixed a crash when `-arch` is the last compiler option. +
+  [small]#_[contributed by Joel Rosdahl]_#
+
+
 == Ccache 4.9
 
 Release date: 2023-12-30
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ccache-4.9/src/Context.cpp 
new/ccache-4.9.1/src/Context.cpp
--- old/ccache-4.9/src/Context.cpp      2023-12-30 16:08:02.000000000 +0100
+++ new/ccache-4.9.1/src/Context.cpp    2024-02-05 20:29:52.000000000 +0100
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2023 Joel Rosdahl and other contributors
+// Copyright (C) 2020-2024 Joel Rosdahl and other contributors
 //
 // See doc/AUTHORS.adoc for a complete list of contributors.
 //
@@ -41,13 +41,12 @@
 Context::Context()
   : actual_cwd(util::actual_cwd()),
     apparent_cwd(util::apparent_cwd(actual_cwd)),
-    storage(config)
+    storage(config),
 #ifdef INODE_CACHE_SUPPORTED
-    ,
-    inode_cache(config)
+    inode_cache(config),
 #endif
+    time_of_invocation(util::TimePoint::now())
 {
-  time_of_invocation = util::TimePoint::now();
 }
 
 void
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ccache-4.9/src/Context.hpp 
new/ccache-4.9.1/src/Context.hpp
--- old/ccache-4.9/src/Context.hpp      2023-12-30 16:08:02.000000000 +0100
+++ new/ccache-4.9.1/src/Context.hpp    2024-02-05 20:29:52.000000000 +0100
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2023 Joel Rosdahl and other contributors
+// Copyright (C) 2020-2024 Joel Rosdahl and other contributors
 //
 // See doc/AUTHORS.adoc for a complete list of contributors.
 //
@@ -67,13 +67,6 @@
   // The original argument list.
   Args orig_args;
 
-  // Time of ccache invocation.
-  util::TimePoint time_of_invocation;
-
-  // Time of compilation. Used to see if include files have changed after
-  // compilation.
-  util::TimePoint time_of_compilation;
-
   // Files included by the preprocessor and their hashes.
   std::unordered_map<std::string, Hash::Digest> included_files;
 
@@ -100,6 +93,9 @@
   mutable InodeCache inode_cache;
 #endif
 
+  // Time of ccache invocation.
+  util::TimePoint time_of_invocation;
+
   // PID of currently executing compiler that we have started, if any. 0 means
   // no ongoing compilation.
   pid_t compiler_pid = 0;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ccache-4.9/src/argprocessing.cpp 
new/ccache-4.9.1/src/argprocessing.cpp
--- old/ccache-4.9/src/argprocessing.cpp        2023-12-30 16:08:02.000000000 
+0100
+++ new/ccache-4.9.1/src/argprocessing.cpp      2024-02-05 20:29:52.000000000 
+0100
@@ -426,6 +426,10 @@
 
   // Handle -arch options.
   if (arg == "-arch") {
+    if (i == args.size() - 1) {
+      LOG("Missing argument to {}", args[i]);
+      return Statistic::bad_compiler_arguments;
+    }
     ++i;
     args_info.arch_args.emplace_back(args[i]);
     if (args_info.arch_args.size() == 2) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ccache-4.9/src/ccache.cpp 
new/ccache-4.9.1/src/ccache.cpp
--- old/ccache-4.9/src/ccache.cpp       2023-12-30 16:08:02.000000000 +0100
+++ new/ccache-4.9.1/src/ccache.cpp     2024-02-05 20:29:52.000000000 +0100
@@ -304,54 +304,29 @@
 #endif
 }
 
-static bool
-include_file_too_new(const Context& ctx,
-                     const std::string& path,
-                     const DirEntry& dir_entry)
-{
-  // The comparison using >= is intentional, due to a possible race between
-  // starting compilation and writing the include file. See also the notes 
under
-  // "Performance" in doc/MANUAL.adoc.
-  if (!(ctx.config.sloppiness().contains(core::Sloppy::include_file_mtime))
-      && dir_entry.mtime() >= ctx.time_of_compilation) {
-    LOG("Include file {} too new", path);
-    return true;
-  }
-
-  // The same >= logic as above applies to the change time of the file.
-  if (!(ctx.config.sloppiness().contains(core::Sloppy::include_file_ctime))
-      && dir_entry.ctime() >= ctx.time_of_compilation) {
-    LOG("Include file {} ctime too new", path);
-    return true;
-  }
-
-  return false;
-}
-
-// Returns false if the include file was "too new" and therefore should disable
-// the direct mode (or, in the case of a preprocessed header, fall back to just
-// running the real compiler), otherwise true.
-static bool
-do_remember_include_file(Context& ctx,
-                         std::string path,
-                         Hash& cpp_hash,
-                         bool system,
-                         Hash* depend_mode_hash)
+// This function hashes an include file and stores the path and hash in
+// ctx.included_files. If the include file is a PCH, cpp_hash is also updated.
+[[nodiscard]] tl::expected<void, Failure>
+remember_include_file(Context& ctx,
+                      std::string path,
+                      Hash& cpp_hash,
+                      bool system,
+                      Hash* depend_mode_hash)
 {
   if (path.length() >= 2 && path[0] == '<' && path[path.length() - 1] == '>') {
     // Typically <built-in> or <command-line>.
-    return true;
+    return {};
   }
 
   if (path == ctx.args_info.normalized_input_file) {
     // Don't remember the input file.
-    return true;
+    return {};
   }
 
   if (system
-      && (ctx.config.sloppiness().contains(core::Sloppy::system_headers))) {
+      && ctx.config.sloppiness().contains(core::Sloppy::system_headers)) {
     // Don't remember this system header.
-    return true;
+    return {};
   }
 
   // Canonicalize path for comparison; Clang uses ./header.h.
@@ -361,7 +336,7 @@
 
   if (ctx.included_files.find(path) != ctx.included_files.end()) {
     // Already known include file.
-    return true;
+    return {};
   }
 
 #ifdef _WIN32
@@ -370,52 +345,35 @@
     DWORD attributes = GetFileAttributes(path.c_str());
     if (attributes != INVALID_FILE_ATTRIBUTES
         && attributes & FILE_ATTRIBUTE_DIRECTORY) {
-      return true;
+      return {};
     }
   }
 #endif
 
   DirEntry dir_entry(path, DirEntry::LogOnError::yes);
   if (!dir_entry.exists()) {
-    return false;
+    return tl::unexpected(Statistic::bad_input_file);
   }
   if (dir_entry.is_directory()) {
     // Ignore directory, typically $PWD.
-    return true;
+    return {};
   }
   if (!dir_entry.is_regular_file()) {
     // Device, pipe, socket or other strange creature.
     LOG("Non-regular include file {}", path);
-    return false;
+    return tl::unexpected(Statistic::bad_input_file);
   }
 
   for (const auto& ignore_header_path : ctx.ignore_header_paths) {
     if (file_path_matches_dir_prefix_or_file(ignore_header_path, path)) {
-      return true;
+      return {};
     }
   }
 
-  const bool is_pch = is_precompiled_header(path);
-  const bool too_new = include_file_too_new(ctx, path, dir_entry);
-
-  if (too_new) {
-    // Opt out of direct mode because of a race condition.
-    //
-    // The race condition consists of these events:
-    //
-    // - the preprocessor is run
-    // - an include file is modified by someone
-    // - the new include file is hashed by ccache
-    // - the real compiler is run on the preprocessor's output, which contains
-    //   data from the old header file
-    // - the wrong object file is stored in the cache.
-
-    return false;
-  }
-
   // Let's hash the include file content.
   Hash::Digest file_digest;
 
+  const bool is_pch = is_precompiled_header(path);
   if (is_pch) {
     if (ctx.args_info.included_pch_file.empty()) {
       LOG("Detected use of precompiled header: {}", path);
@@ -433,7 +391,7 @@
     }
 
     if (!hash_binary_file(ctx, file_digest, path)) {
-      return false;
+      return tl::unexpected(Statistic::bad_input_file);
     }
     cpp_hash.hash_delimiter(using_pch_sum ? "pch_sum_hash" : "pch_hash");
     cpp_hash.hash(util::format_digest(file_digest));
@@ -442,45 +400,24 @@
   if (ctx.config.direct_mode()) {
     if (!is_pch) { // else: the file has already been hashed.
       auto ret = hash_source_code_file(ctx, file_digest, path);
-      if (ret.contains(HashSourceCode::error)
-          || ret.contains(HashSourceCode::found_time)) {
-        return false;
+      if (ret.contains(HashSourceCode::error)) {
+        return tl::unexpected(Statistic::bad_input_file);
+      }
+      if (ret.contains(HashSourceCode::found_time)) {
+        LOG_RAW("Disabling direct mode");
+        ctx.config.set_direct_mode(false);
       }
     }
 
-    ctx.included_files.emplace(path, file_digest);
-
     if (depend_mode_hash) {
       depend_mode_hash->hash_delimiter("include");
       depend_mode_hash->hash(util::format_digest(file_digest));
     }
   }
 
-  return true;
-}
-
-enum class RememberIncludeFileResult { ok, cannot_use_pch };
-
-// This function hashes an include file and stores the path and hash in
-// ctx.included_files. If the include file is a PCH, cpp_hash is also updated.
-static RememberIncludeFileResult
-remember_include_file(Context& ctx,
-                      const std::string& path,
-                      Hash& cpp_hash,
-                      bool system,
-                      Hash* depend_mode_hash)
-{
-  if (!do_remember_include_file(
-        ctx, path, cpp_hash, system, depend_mode_hash)) {
-    if (is_precompiled_header(path)) {
-      return RememberIncludeFileResult::cannot_use_pch;
-    } else if (ctx.config.direct_mode()) {
-      LOG_RAW("Disabling direct mode");
-      ctx.config.set_direct_mode(false);
-    }
-  }
+  ctx.included_files.emplace(path, file_digest);
 
-  return RememberIncludeFileResult::ok;
+  return {};
 }
 
 static void
@@ -627,10 +564,7 @@
         hash.hash(inc_path);
       }
 
-      if (remember_include_file(ctx, inc_path, hash, system, nullptr)
-          == RememberIncludeFileResult::cannot_use_pch) {
-        return tl::unexpected(Statistic::could_not_use_precompiled_header);
-      }
+      TRY(remember_include_file(ctx, inc_path, hash, system, nullptr));
       p = q; // Everything of interest between p and q has been hashed now.
     } else if (strncmp(q, incbin_directive, sizeof(incbin_directive)) == 0
                && ((q[7] == ' '
@@ -672,7 +606,7 @@
     std::string pch_path =
       Util::make_relative_path(ctx, ctx.args_info.included_pch_file);
     hash.hash(pch_path);
-    remember_include_file(ctx, pch_path, hash, false, nullptr);
+    TRY(remember_include_file(ctx, pch_path, hash, false, nullptr));
   }
 
   bool debug_included = getenv("CCACHE_DEBUG_INCLUDED");
@@ -685,7 +619,7 @@
 
 // Extract the used includes from the dependency file. Note that we cannot
 // distinguish system headers from other includes here.
-static std::optional<Hash::Digest>
+static tl::expected<Hash::Digest, Failure>
 result_key_from_depfile(Context& ctx, Hash& hash)
 {
   // Make sure that result hash will always be different from the manifest hash
@@ -699,7 +633,7 @@
     LOG("Failed to read dependency file {}: {}",
         ctx.args_info.output_dep,
         file_content.error());
-    return std::nullopt;
+    return tl::unexpected(Statistic::bad_input_file);
   }
 
   for (std::string_view token : Depfile::tokenize(*file_content)) {
@@ -707,7 +641,7 @@
       continue;
     }
     std::string path = Util::make_relative_path(ctx, token);
-    remember_include_file(ctx, path, hash, false, &hash);
+    TRY(remember_include_file(ctx, path, hash, false, &hash));
   }
 
   // Explicitly check the .gch/.pch/.pth file as it may not be mentioned in the
@@ -716,7 +650,7 @@
     std::string pch_path =
       Util::make_relative_path(ctx, ctx.args_info.included_pch_file);
     hash.hash(pch_path);
-    remember_include_file(ctx, pch_path, hash, false, nullptr);
+    TRY(remember_include_file(ctx, pch_path, hash, false, nullptr));
   }
 
   bool debug_included = getenv("CCACHE_DEBUG_INCLUDED");
@@ -759,14 +693,14 @@
 
 // Extract the used includes from /showIncludes output in stdout. Note that we
 // cannot distinguish system headers from other includes here.
-static std::optional<Hash::Digest>
+static tl::expected<Hash::Digest, Failure>
 result_key_from_includes(Context& ctx, Hash& hash, std::string_view 
stdout_data)
 {
   for (std::string_view include : core::MsvcShowIncludesOutput::get_includes(
          stdout_data, ctx.config.msvc_dep_prefix())) {
     const std::string path = Util::make_relative_path(
       ctx, Util::normalize_abstract_absolute_path(include));
-    remember_include_file(ctx, path, hash, false, &hash);
+    TRY(remember_include_file(ctx, path, hash, false, &hash));
   }
 
   // Explicitly check the .pch file as it is not mentioned in the
@@ -775,7 +709,7 @@
     std::string pch_path =
       Util::make_relative_path(ctx, ctx.args_info.included_pch_file);
     hash.hash(pch_path);
-    remember_include_file(ctx, pch_path, hash, false, nullptr);
+    TRY(remember_include_file(ctx, pch_path, hash, false, nullptr));
   }
 
   const bool debug_included = getenv("CCACHE_DEBUG_INCLUDED");
@@ -872,7 +806,7 @@
 
   MTR_SCOPE("manifest", "manifest_put");
 
-  // ctime() may be 0, so we have to check time_of_compilation against
+  // ctime() may be 0, so we have to check time_of_invocation against
   // MAX(mtime, ctime).
   //
   // ccache only reads mtime/ctime if file_stat_matches sloppiness is enabled,
@@ -887,7 +821,7 @@
       DirEntry de(path, DirEntry::LogOnError::yes);
       bool cache_time =
         save_timestamp
-        && ctx.time_of_compilation > std::max(de.mtime(), de.ctime());
+        && ctx.time_of_invocation > std::max(de.mtime(), de.ctime());
       return core::Manifest::FileStats{
         de.size(),
         de.is_regular_file() && cache_time ? de.mtime() : util::TimePoint(),
@@ -1072,6 +1006,59 @@
   }
 }
 
+static std::string
+format_epoch_time(const util::TimePoint& tp)
+{
+  return FMT("{}.{:09}", tp.sec(), tp.nsec_decimal_part());
+}
+
+static bool
+source_file_is_too_new(const Context& ctx, const fs::path& path)
+{
+  const bool sloppy_ctime =
+    ctx.config.sloppiness().contains(core::Sloppy::include_file_ctime);
+  const bool sloppy_mtime =
+    ctx.config.sloppiness().contains(core::Sloppy::include_file_mtime);
+
+  if ((sloppy_mtime && sloppy_ctime) || util::is_dev_null_path(path)) {
+    return false;
+  }
+
+  // It's not enough to check if mtime/ctime >= ctx.time_of_invocation since
+  // filesystem timestamps are granular. See the comment for
+  // InodeCache::InodeCache for details.
+  //
+  // A relatively small safety margin is used in this case to make things safe
+  // on common filesystems while also not bailing out when creating a source
+  // file reasonably close in time before the compilation.
+  const util::Duration min_age(0, 100'000'000); // 0.1 s
+  util::TimePoint deadline = ctx.time_of_invocation + min_age;
+
+  DirEntry dir_entry(path);
+
+  if (!sloppy_mtime && dir_entry.mtime() >= deadline) {
+    LOG(
+      "{} was modified near or after invocation (mtime {}, invocation time 
{})",
+      dir_entry.path(),
+      format_epoch_time(dir_entry.mtime()),
+      format_epoch_time(ctx.time_of_invocation));
+    return true;
+  }
+
+  // The same logic as above applies to the change time of the file.
+  if (!sloppy_ctime && dir_entry.ctime() >= deadline) {
+    LOG(
+      "{} had status change near or after invocation (ctime {}, invocation"
+      " time {})",
+      dir_entry.path(),
+      format_epoch_time(dir_entry.ctime()),
+      format_epoch_time(ctx.time_of_invocation));
+    return true;
+  }
+
+  return false;
+}
+
 // Run the real compiler and put the result in cache. Returns the result key.
 static tl::expected<Hash::Digest, Failure>
 to_cache(Context& ctx,
@@ -1139,7 +1126,6 @@
     depend_mode_args.insert(1, depend_extra_args);
     add_prefix(ctx, depend_mode_args, ctx.config.prefix_command());
 
-    ctx.time_of_compilation = util::TimePoint::now();
     result = do_execute(ctx, depend_mode_args);
   }
   MTR_END("execute", "compiler");
@@ -1179,22 +1165,36 @@
   if (ctx.config.depend_mode()) {
     ASSERT(depend_mode_hash);
     if (ctx.args_info.generating_dependencies) {
-      result_key = result_key_from_depfile(ctx, *depend_mode_hash);
+      auto key = result_key_from_depfile(ctx, *depend_mode_hash);
+      if (!key) {
+        return tl::unexpected(key.error());
+      }
+      result_key = *key;
     } else if (ctx.args_info.generating_includes) {
-      result_key = result_key_from_includes(
+      auto key = result_key_from_includes(
         ctx, *depend_mode_hash, util::to_string_view(result->stdout_data));
+      if (!key) {
+        return tl::unexpected(key.error());
+      }
+      result_key = *key;
     } else {
       ASSERT(false);
     }
-    if (!result_key) {
-      return tl::unexpected(Statistic::internal_error);
-    }
     LOG_RAW("Got result key from dependency file");
     LOG("Result key: {}", util::format_digest(*result_key));
   }
 
   ASSERT(result_key);
 
+  if (source_file_is_too_new(ctx, ctx.args_info.input_file)) {
+    return tl::unexpected(Statistic::modified_input_file);
+  }
+  for (const auto& [path, digest] : ctx.included_files) {
+    if (source_file_is_too_new(ctx, path)) {
+      return tl::unexpected(Statistic::modified_input_file);
+    }
+  }
+
   if (ctx.args_info.generating_dependencies) {
     Depfile::make_paths_relative_in_output_dep(ctx);
   }
@@ -1239,8 +1239,6 @@
 static tl::expected<Hash::Digest, Failure>
 get_result_key_from_cpp(Context& ctx, Args& args, Hash& hash)
 {
-  ctx.time_of_compilation = util::TimePoint::now();
-
   std::string preprocessed_path;
   util::Bytes cpp_stderr_data;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ccache-4.9/src/core/AtomicFile.cpp 
new/ccache-4.9.1/src/core/AtomicFile.cpp
--- old/ccache-4.9/src/core/AtomicFile.cpp      2023-12-30 16:08:02.000000000 
+0100
+++ new/ccache-4.9.1/src/core/AtomicFile.cpp    2024-02-05 20:29:52.000000000 
+0100
@@ -1,4 +1,4 @@
-// Copyright (C) 2019-2023 Joel Rosdahl and other contributors
+// Copyright (C) 2019-2024 Joel Rosdahl and other contributors
 //
 // See doc/AUTHORS.adoc for a complete list of contributors.
 //
@@ -32,7 +32,7 @@
 AtomicFile::AtomicFile(const fs::path& path, Mode mode) : m_path(path)
 {
   auto tmp_file =
-    util::value_or_throw<core::Fatal>(util::TemporaryFile::create(path));
+    util::value_or_throw<core::Error>(util::TemporaryFile::create(path));
   m_stream = fdopen(tmp_file.fd.release(), mode == Mode::binary ? "w+b" : 
"w+");
   m_tmp_path = std::move(tmp_file.path);
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ccache-4.9/src/core/Statistic.hpp 
new/ccache-4.9.1/src/core/Statistic.hpp
--- old/ccache-4.9/src/core/Statistic.hpp       2023-12-30 16:08:02.000000000 
+0100
+++ new/ccache-4.9.1/src/core/Statistic.hpp     2024-02-05 20:29:52.000000000 
+0100
@@ -1,4 +1,4 @@
-// Copyright (C) 2021-2023 Joel Rosdahl and other contributors
+// Copyright (C) 2021-2024 Joel Rosdahl and other contributors
 //
 // See doc/AUTHORS.adoc for a complete list of contributors.
 //
@@ -79,7 +79,9 @@
   subdir_size_kibibyte_base = 65,
 
   disabled = 81,
-  END = 82
+  bad_input_file = 82,
+  modified_input_file = 83,
+  END = 84
 };
 
 } // namespace core
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ccache-4.9/src/core/Statistics.cpp 
new/ccache-4.9.1/src/core/Statistics.cpp
--- old/ccache-4.9/src/core/Statistics.cpp      2023-12-30 16:08:02.000000000 
+0100
+++ new/ccache-4.9.1/src/core/Statistics.cpp    2024-02-05 20:29:52.000000000 
+0100
@@ -1,4 +1,4 @@
-// Copyright (C) 2021-2023 Joel Rosdahl and other contributors
+// Copyright (C) 2021-2024 Joel Rosdahl and other contributors
 //
 // See doc/AUTHORS.adoc for a complete list of contributors.
 //
@@ -76,6 +76,9 @@
   // option argument.
   FIELD(bad_compiler_arguments, "Bad compiler arguments", FLAG_UNCACHEABLE),
 
+  // An input file could not be read or parsed (see the debug log for details).
+  FIELD(bad_input_file, "Could not read or parse input file", FLAG_ERROR),
+
   // The output path specified with -o could not be written to.
   FIELD(bad_output_file, "Could not write to output file", FLAG_ERROR),
 
@@ -173,6 +176,10 @@
   // cache while another instance removed the file as part of cache cleanup.
   FIELD(missing_cache_file, "Missing cache file", FLAG_ERROR),
 
+  // An input file was modified during compilation.
+  FIELD(
+    modified_input_file, "Input file modified during compilation", FLAG_ERROR),
+
   // The compiler was called to compile multiple source files in one go. This 
is
   // not supported by ccache.
   FIELD(multiple_source_files, "Multiple source files", FLAG_UNCACHEABLE),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ccache-4.9/src/core/mainoptions.cpp 
new/ccache-4.9.1/src/core/mainoptions.cpp
--- old/ccache-4.9/src/core/mainoptions.cpp     2023-12-30 16:08:02.000000000 
+0100
+++ new/ccache-4.9.1/src/core/mainoptions.cpp   2024-02-05 20:29:52.000000000 
+0100
@@ -1,4 +1,4 @@
-// Copyright (C) 2021-2023 Joel Rosdahl and other contributors
+// Copyright (C) 2021-2024 Joel Rosdahl and other contributors
 //
 // See doc/AUTHORS.adoc for a complete list of contributors.
 //
@@ -82,7 +82,7 @@
 Features: {2}
 
 Copyright (C) 2002-2007 Andrew Tridgell
-Copyright (C) 2009-2023 Joel Rosdahl and other contributors
+Copyright (C) 2009-2024 Joel Rosdahl and other contributors
 
 See <https://ccache.dev/credits.html> for a complete list of contributors.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ccache-4.9/src/execute.cpp 
new/ccache-4.9.1/src/execute.cpp
--- old/ccache-4.9/src/execute.cpp      2023-12-30 16:08:02.000000000 +0100
+++ new/ccache-4.9.1/src/execute.cpp    2024-02-05 20:29:52.000000000 +0100
@@ -170,7 +170,8 @@
       // process is killed.
       JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobInfo = {};
       jobInfo.BasicLimitInformation.LimitFlags =
-        JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
+        JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
+        | JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK;
       BOOL job_success = SetInformationJobObject(
         job, JobObjectExtendedLimitInformation, &jobInfo, sizeof(jobInfo));
       if (!job_success) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ccache-4.9/src/storage/Storage.cpp 
new/ccache-4.9.1/src/storage/Storage.cpp
--- old/ccache-4.9/src/storage/Storage.cpp      2023-12-30 16:08:02.000000000 
+0100
+++ new/ccache-4.9.1/src/storage/Storage.cpp    2024-02-05 20:29:52.000000000 
+0100
@@ -1,4 +1,4 @@
-// Copyright (C) 2021-2023 Joel Rosdahl and other contributors
+// Copyright (C) 2021-2024 Joel Rosdahl and other contributors
 //
 // See doc/AUTHORS.adoc for a complete list of contributors.
 //
@@ -132,7 +132,7 @@
   // now to avoid exceptions later.
   Url url(url_string);
   try {
-    std::ignore = url.scheme();
+    std::ignore = url.str();
   } catch (const std::exception& e) {
     return tl::unexpected(FMT("Cannot parse URL {}: {}", url_string, 
e.what()));
   }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ccache-4.9/src/util/path.hpp 
new/ccache-4.9.1/src/util/path.hpp
--- old/ccache-4.9/src/util/path.hpp    2023-12-30 16:08:02.000000000 +0100
+++ new/ccache-4.9.1/src/util/path.hpp  2024-02-05 20:29:52.000000000 +0100
@@ -1,4 +1,4 @@
-// Copyright (C) 2021-2023 Joel Rosdahl and other contributors
+// Copyright (C) 2021-2024 Joel Rosdahl and other contributors
 //
 // See doc/AUTHORS.adoc for a complete list of contributors.
 //
@@ -45,7 +45,7 @@
 const char* get_dev_null_path();
 
 // Return whether `path` is /dev/null or (on Windows) NUL.
-bool is_dev_null_path(std::string_view path);
+bool is_dev_null_path(const std::filesystem::path& path);
 
 // Return whether `path` includes at least one directory separator.
 bool is_full_path(std::string_view path);
@@ -61,11 +61,11 @@
 // --- Inline implementations ---
 
 inline bool
-is_dev_null_path(const std::string_view path)
+is_dev_null_path(const std::filesystem::path& path)
 {
   return path == "/dev/null"
 #ifdef _WIN32
-         || util::to_lowercase(path) == "nul"
+         || util::to_lowercase(path.string()) == "nul"
 #endif
     ;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ccache-4.9/test/suites/base.bash 
new/ccache-4.9.1/test/suites/base.bash
--- old/ccache-4.9/test/suites/base.bash        2023-12-30 16:08:02.000000000 
+0100
+++ new/ccache-4.9.1/test/suites/base.bash      2024-02-05 20:29:52.000000000 
+0100
@@ -282,6 +282,48 @@
     rm -rf src
 
     # -------------------------------------------------------------------------
+    TEST "Too new source file"
+
+    touch new.c
+    touch -t 203801010000 new.c
+
+    $CCACHE_COMPILE -c new.c
+    expect_stat modified_input_file 1
+    expect_stat cache_miss 0
+
+    CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS include_file_mtime" $CCACHE_COMPILE 
-c new.c
+    expect_stat modified_input_file 1
+    expect_stat cache_miss 1
+
+    # -------------------------------------------------------------------------
+    TEST "Too new include file"
+
+    cat <<EOF >new.c
+#include "new.h"
+EOF
+    cat <<EOF >new.h
+int test;
+EOF
+    touch -t 203801010000 new.h
+
+    $CCACHE_COMPILE -c new.c
+    expect_stat modified_input_file 1
+    expect_stat cache_miss 0
+
+    CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS include_file_mtime" $CCACHE_COMPILE 
-c new.c
+    expect_stat modified_input_file 1
+    expect_stat cache_miss 1
+
+    # -------------------------------------------------------------------------
+    TEST "Too new source file ignored if sloppy"
+
+    touch new.c
+    touch -t 203801010000 new.c
+
+    CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS include_file_mtime" $CCACHE_COMPILE 
-c new.c
+    expect_stat cache_miss 1
+
+    # -------------------------------------------------------------------------
     TEST "LANG"
 
     $CCACHE_COMPILE -c test1.c
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ccache-4.9/test/suites/direct.bash 
new/ccache-4.9.1/test/suites/direct.bash
--- old/ccache-4.9/test/suites/direct.bash      2023-12-30 16:08:02.000000000 
+0100
+++ new/ccache-4.9.1/test/suites/direct.bash    2024-02-05 20:29:52.000000000 
+0100
@@ -1073,27 +1073,6 @@
     expect_stat cache_miss 1
 
     # -------------------------------------------------------------------------
-    TEST "Too new include file disables direct mode"
-
-    cat <<EOF >new.c
-#include "new.h"
-EOF
-    cat <<EOF >new.h
-int test;
-EOF
-    touch -t 203801010000 new.h
-
-    $CCACHE_COMPILE -c new.c
-    expect_stat direct_cache_hit 0
-    expect_stat preprocessed_cache_hit 0
-    expect_stat cache_miss 1
-
-    $CCACHE_COMPILE -c new.c
-    expect_stat direct_cache_hit 0
-    expect_stat preprocessed_cache_hit 1
-    expect_stat cache_miss 1
-
-    # -------------------------------------------------------------------------
     TEST "__DATE__ in header file results in direct cache hit as the date 
remains the same"
 
     cat <<EOF >test_date2.c
@@ -1116,27 +1095,6 @@
     expect_stat direct_cache_hit 1
     expect_stat preprocessed_cache_hit 0
     expect_stat cache_miss 1
-
-    # -------------------------------------------------------------------------
-    TEST "New include file ignored if sloppy"
-
-    cat <<EOF >new.c
-#include "new.h"
-EOF
-    cat <<EOF >new.h
-int test;
-EOF
-    touch -t 203801010000 new.h
-
-    CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS include_file_mtime" $CCACHE_COMPILE 
-c new.c
-    expect_stat direct_cache_hit 0
-    expect_stat preprocessed_cache_hit 0
-    expect_stat cache_miss 1
-
-    CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS include_file_mtime" $CCACHE_COMPILE 
-c new.c
-    expect_stat direct_cache_hit 1
-    expect_stat preprocessed_cache_hit 0
-    expect_stat cache_miss 1
 
     # -------------------------------------------------------------------------
     TEST "Sloppy Clang index store"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ccache-4.9/test/suites/pch.bash 
new/ccache-4.9.1/test/suites/pch.bash
--- old/ccache-4.9/test/suites/pch.bash 2023-12-30 16:08:02.000000000 +0100
+++ new/ccache-4.9.1/test/suites/pch.bash       2024-02-05 20:29:52.000000000 
+0100
@@ -631,14 +631,6 @@
     # -------------------------------------------------------------------------
     TEST "Too new PCH file"
 
-    # If the precompiled header is too new we shouldn't cache the result at all
-    # since:
-    #
-    # - the precompiled header content must be included in the hash, but
-    # - we don't trust the precompiled header content so we can't hash it
-    #   ourselves, and
-    # - the preprocessed output doesn't contain the preprocessed header 
content.
-
     touch lib.h
     touch main.c
 
@@ -646,10 +638,7 @@
     touch -d "@$(($(date +%s) + 60))" lib.h.gch # 1 minute in the future
 
     CCACHE_SLOPPINESS="$DEFAULT_SLOPPINESS pch_defines,time_macros" 
$CCACHE_COMPILE -include lib.h -c main.c
-    expect_stat direct_cache_hit 0
-    expect_stat preprocessed_cache_hit 0
-    expect_stat cache_miss 0
-    expect_stat could_not_use_precompiled_header 1
+    expect_stat modified_input_file 1
 }
 
 pch_suite_clang() {

Reply via email to