ccache / ccache

ccache – a fast compiler cache
https://ccache.dev
Other
2.31k stars 496 forks source link

Test readonly.ccache fails on WSL #510

Closed AlexanderLanin closed 4 years ago

AlexanderLanin commented 4 years ago

How to reproduce

  1. Open WSL with Ubuntu 18
  2. /mnt/c/Git/ccache$ git checkout origin/master

    HEAD is now at d4b6659 Include “Co-authored-by” attributions when calculating authors

  3. /mnt/c/Git/ccache$ git clean -dxf
  4. /mnt/c/Git/ccache$ ./autogen.sh

    Now run ./configure and make

  5. /mnt/c/Git/ccache$ ./configure

    configure: configuring ccache configure: developer mode enabled checking build system type... x86_64-pc-linux-gnu checking host system type... x86_64-pc-linux-gnu checking for gcc... gcc checking whether the C compiler works... yes checking for C compiler default output file name... a.out checking for suffix of executables... checking whether we are cross compiling... no checking for suffix of object files... o checking whether we are using the GNU C compiler... yes checking whether gcc accepts -g... yes checking for gcc option to accept ISO C89... none needed checking for g++... g++ checking whether we are using the GNU C++ compiler... yes checking whether g++ accepts -g... yes checking whether g++ supports C++11 features with -std=c++11... yes checking whether we are using the clang C compiler... no checking for a BSD-compatible install... /usr/bin/install -c checking whether C compiler accepts -mavx2... yes checking for a sed that does not truncate output... /bin/sed checking how to run the C preprocessor... gcc -E checking for grep that handles long lines and -e... /bin/grep checking for egrep... /bin/grep -E checking whether gcc is Clang... no checking whether pthreads work with -pthread... yes checking for joinable pthread attribute... PTHREAD_CREATE_JOINABLE checking whether more special flags are required for pthreads... no checking for PTHREAD_PRIO_INHERIT... yes checking for bash... /bin/bash checking for dirent.h that defines DIR... yes checking for library containing opendir... none required checking whether time.h and sys/time.h may both be included... yes checking for sys/wait.h that is POSIX.1 compatible... yes checking for ANSI C header files... yes checking for sys/types.h... yes checking for sys/stat.h... yes checking for stdlib.h... yes checking for string.h... yes checking for memory.h... yes checking for strings.h... yes checking for inttypes.h... yes checking for stdint.h... yes checking for unistd.h... yes checking for long long... yes checking ctype.h usability... yes checking ctype.h presence... yes checking for ctype.h... yes checking pwd.h usability... yes checking pwd.h presence... yes checking for pwd.h... yes checking for stdlib.h... (cached) yes checking for string.h... (cached) yes checking for strings.h... (cached) yes checking sys/time.h usability... yes checking sys/time.h presence... yes checking for sys/time.h... yes checking sys/mman.h usability... yes checking sys/mman.h presence... yes checking for sys/mman.h... yes checking syslog.h usability... yes checking syslog.h presence... yes checking for syslog.h... yes checking termios.h usability... yes checking termios.h presence... yes checking for termios.h... yes checking sys/ioctl.h usability... yes checking sys/ioctl.h presence... yes checking for sys/ioctl.h... yes checking linux/fs.h usability... yes checking linux/fs.h presence... yes checking for linux/fs.h... yes checking sys/clonefile.h usability... no checking sys/clonefile.h presence... no checking for sys/clonefile.h... no checking for asctime_r... yes checking for gethostname... yes checking for getopt_long... yes checking for getpwuid... yes checking for gettimeofday... yes checking for localtime_r... yes checking for mkstemp... yes checking for realpath... yes checking for setenv... yes checking for strndup... yes checking for strtok_r... yes checking for syslog... yes checking for unsetenv... yes checking for utimes... yes checking for compar_fn_t in stdlib.h... yes checking for library containing cos... -lm checking for ZSTD_versionNumber in -lzstd... yes checking for blake2b in -lb2... yes checking whether byte ordering is bigendian... no checking for inline... inline checking for extern inline... no configure: creating ./config.status config.status: creating dev.mk config.status: creating Makefile config.status: creating config.h configure: now build ccache by running make`

  6. make test -j8

Actual behavior

... CXX unittest/test_legacy_util.o CXX unittest/test_lockfile.o CXX unittest/test_stats.o LD ccache LD unittest/run TEST unittest/run

All tests passed (1377 assertions in 42 test cases)

PASSED: 384 assertions, 89 tests, 9 suites TEST ./test/run Compiler: gcc (/usr/bin/gcc) Compiler version: gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0 CUDA compiler: not available

Running test suite base...................................................................... Running test suite nocpp2...................................................................... Running test suite cpp1. Skipped test suite multi_arch [multiple -arch options not supported on Linux] Skipped test suite serialize_diagnostics [--serialize-diagnostics not supported by compiler] Skipped test suite sanitize_blacklist [-fsanitize-blacklist not supported by compiler] Running test suite debug_prefix_map.. Running test suite split_dwarf.... Running test suite masquerading. Running test suite hardlink.... Skipped test suite fileclone [file system doesn't support file cloning] Running test suite direct.......................................... Running test suite direct_gcc..... Running test suite depend...... Running test suite basedir...... Running test suite no_compression.... Running test suite readonly.ccache: error: failed to rename /mnt/c/Git/ccache/testdir.16087/.ccache/1/stats.tmp.Rehbock.28597.KHGUJs to /mnt/c/Git/ccache/testdir.16087/.ccache/1/stats

FAILED

Test suite: readonly Test case: Cache hit Failure reason: Failure when compiling test.c read-only

ccache -s: cache directory /mnt/c/Git/ccache/testdir.16087/.ccache primary config /mnt/c/Git/ccache/testdir.16087/ccache.conf secondary config (readonly) stats updated Thu Jan 16 11:06:40 2020 cache hit (direct) 0 cache hit (preprocessed) 0 cache miss 2 cache hit rate 0.00 % cleanups performed 0 files in cache 1 cache size 0.0 MB max cache size 5.0 GB

Test data and log file have been left in testdir.16087 Makefile:180: recipe for target 'test' failed make: *** [test] Error 1

Expected behavior

Some green result :-)

Environment

current ccache from github master, WSL1 with Ubuntu 18.04.1 LTS

AlexanderLanin commented 4 years ago

testdir.16087.zip

jrosdahl commented 4 years ago

The second compilation (the one after "Check that read-only mode finds the cached result") in the Cache hit test case in SUITE_readonly is expected to log something like this:

[2020-01-19T19:58:57.329469 23099] Result: cache hit (preprocessed) [2020-01-19T19:58:57.329556 23099] lockfile_acquire: symlink /path/to/.ccache/0/stats.lock: Permission denied [2020-01-19T19:58:57.329597 23099] Failed to acquire lock /path/to/.ccache/0/stats.lock

But in your case it's

[2020-01-16T11:06:40.227522 28597] Result: cache hit (preprocessed) [2020-01-16T11:06:40.227738 28597] Acquired lock /mnt/c/Git/ccache/testdir.16087/.ccache/1/stats.lock

followed by

ccache: error: failed to rename /mnt/c/Git/ccache/testdir.16087/.ccache/1/stats.tmp.Rehbock.28597.KHGUJs to /mnt/c/Git/ccache/testdir.16087/.ccache/1/stats

to stdout. So it looks like WSL either lies about the symlink creation in lockfile_acquire or it actually creates a symlink even though the directory is (should be) read-only. In any case, ccache believes that it acquired the lock, proceeds to write a temporary file (which succeeds) and then fails when trying to rename it to the (existing) .ccache/1/stats file, which I guess is read-only.

I don't know anything about WSL (I had to DuckDuckGo it), but from the observations above I guess that chmod -R dir only makes existing files in dir read-only, not directories? If so, it's a bad file system emulation.

Since I don't have handy access to a Windows machine, could you check if #516 fixes the problem you see?

AlexanderLanin commented 4 years ago

With #516:

Running test suite readonly... FAILED

Test suite: readonly Test case: Cache hit, direct Failure reason: Read-only mode + direct mode stored files in the cache

[...]

I guess those are the lines in question:

Result: cache hit (preprocessed) Acquired lock /mnt/c/Git/ccache/testdir.1814/.ccache/1/stats.lock Error: failed to rename /mnt/c/Git/ccache/testdir.1814/.ccache/1/stats.tmp.Rehbock.14665.M4SLDf to /mnt/c/Git/ccache/testdir.1814/.ccache/1/stats Releasing lock /mnt/c/Git/ccache/testdir.1814/.ccache/1/stats.lock Unlink /mnt/c/Git/ccache/testdir.1814/.ccache/1/stats.lock === CCACHE 3.7.1+336_gb2f22c2 STARTED =========================================

However your chmod remark was interesting, so I just tried it with surprising results. In default WSL1 settings (which is what everyone has at the moment) chmod is a no-op. Yeah really!

This was already fixed, but not made default as documented in https://devblogs.microsoft.com/commandline/chmod-chown-wsl-improvements/

With this the test suite runs through!

So I'd suggest to take up 1-2 approaches:

AlexanderLanin commented 4 years ago

After some thought it should probably behave as other tests which are skipped when not executable?!

if(WSL detected and chmod failed) skip_readonly_test

jrosdahl commented 4 years ago

Right, so bad file system emulation it is. :slightly_smiling_face:

Yes, skipping the test if the chmod didn't actually make the cache read-only sounds good.