diff --git a/cmake/ConfigureChecks.cmake b/cmake/ConfigureChecks.cmake index b10ef64ff..af7edd37b 100644 --- a/cmake/ConfigureChecks.cmake +++ b/cmake/ConfigureChecks.cmake @@ -74,15 +74,21 @@ include(CheckCXXSourceCompiles) include(CheckTypeSize) include(CMakePushCheckState) check_cxx_symbol_exists(backtrace_symbols execinfo.h HAVE_BACKTRACE_SYMBOLS) -check_cxx_symbol_exists(clock_gettime time.h HAVE_CLOCK_GETTIME) + +# workaround for lousy mtime precision on a Linux kernel +if (CMAKE_SYSTEM_NAME MATCHES "Linux|Android") + check_cxx_symbol_exists(clock_gettime time.h HAVE_CLOCK_GETTIME) + check_cxx_symbol_exists(futimens sys/stat.h HAVE_FUTIMENS) + if ((HAVE_CLOCK_GETTIME) AND (HAVE_FUTIMENS)) + set(UVAR_FILE_SET_MTIME_HACK 1) + endif() +endif() + check_cxx_symbol_exists(ctermid_r stdio.h HAVE_CTERMID_R) check_struct_has_member("struct dirent" d_type dirent.h HAVE_STRUCT_DIRENT_D_TYPE LANGUAGE CXX) check_cxx_symbol_exists(dirfd "sys/types.h;dirent.h" HAVE_DIRFD) check_include_file_cxx(execinfo.h HAVE_EXECINFO_H) check_cxx_symbol_exists(flock sys/file.h HAVE_FLOCK) -# futimens is new in OS X 10.13 but is a weak symbol. -# Don't assume it exists just because we can link - it may be null. -check_cxx_symbol_exists(futimens sys/stat.h HAVE_FUTIMENS) check_cxx_symbol_exists(getifaddrs ifaddrs.h HAVE_GETIFADDRS) check_cxx_symbol_exists(getpwent pwd.h HAVE_GETPWENT) check_cxx_symbol_exists(getrusage sys/resource.h HAVE_GETRUSAGE) @@ -110,7 +116,6 @@ check_struct_has_member("struct stat" st_mtim.tv_nsec "sys/stat.h" HAVE_STRUCT_S check_include_file_cxx(sys/ioctl.h HAVE_SYS_IOCTL_H) check_include_file_cxx(sys/select.h HAVE_SYS_SELECT_H) check_include_files("sys/types.h;sys/sysctl.h" HAVE_SYS_SYSCTL_H) -check_include_file_cxx(termios.h HAVE_TERMIOS_H) # Needed for TIOCGWINSZ check_cxx_symbol_exists(eventfd sys/eventfd.h HAVE_EVENTFD) check_cxx_symbol_exists(pipe2 unistd.h HAVE_PIPE2) diff --git a/config_cmake.h.in b/config_cmake.h.in index f2eb4b248..46a7499f4 100644 --- a/config_cmake.h.in +++ b/config_cmake.h.in @@ -4,9 +4,6 @@ /* Define to 1 if compiled on WSL */ #cmakedefine WSL 1 -/* Define to 1 if you have the `clock_gettime' function. */ -#cmakedefine HAVE_CLOCK_GETTIME 1 - /* Define to 1 if you have the `ctermid_r' function. */ #cmakedefine HAVE_CTERMID_R 1 @@ -22,9 +19,6 @@ /* Define to 1 if you have the `flock' function. */ #cmakedefine HAVE_FLOCK 1 -/* Define to 1 if you have the `futimens' function. */ -#cmakedefine HAVE_FUTIMENS 1 - /* Define to 1 if you have the `getifaddrs' function. */ #cmakedefine HAVE_GETIFADDRS 1 @@ -97,9 +91,6 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_SYSCTL_H 1 -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_TERMIOS_H 1 - /* Define to 1 if you have the header file. */ #cmakedefine HAVE_TERM_H 1 @@ -130,6 +121,9 @@ /* Define to 1 if std::make_unique is available. */ #cmakedefine HAVE_STD__MAKE_UNIQUE 1 +/* Define to use clock_gettime and futimens to hack around Linux mtime issue */ +#cmakedefine UVAR_FILE_SET_MTIME_HACK 1 + /* Define to 1 to disable ncurses macros that conflict with the STL */ #define NCURSES_NOMACROS 1 diff --git a/src/common.cpp b/src/common.cpp index ae5f7c071..0c2c2aa51 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -56,9 +56,10 @@ #include "wutil.h" // IWYU pragma: keep // Keep after "common.h" -#ifdef __BSD__ +#ifdef HAVE_SYS_SYSCTL_H #include -#elif defined(__APPLE__) +#endif +#if defined(__APPLE__) #include #endif diff --git a/src/env_universal_common.cpp b/src/env_universal_common.cpp index bb7e60061..b74c7bf30 100644 --- a/src/env_universal_common.cpp +++ b/src/env_universal_common.cpp @@ -709,9 +709,13 @@ bool env_universal_t::save(const wcstring &directory, const wcstring &vars_path) // necessary because Linux aggressively reuses inodes, causing the ABA problem; on other // platforms we tend to notice the file has changed due to a different inode (or file size!) // + // The current time within the Linux kernel is cached, and generally only updated on a timer + // interrupt. So if the timer interrupt is running at 10 milliseconds, the cached time will + // only be updated once every 10 milliseconds. + // // It's probably worth finding a simpler solution to this. The tests ran into this, but it's // unlikely to affect users. -#if HAVE_CLOCK_GETTIME && HAVE_FUTIMENS +#if defined(UVAR_FILE_SET_MTIME_HACK) struct timespec times[2] = {}; times[0].tv_nsec = UTIME_OMIT; // don't change ctime if (0 == clock_gettime(CLOCK_REALTIME, ×[1])) {