- Notifications
You must be signed in to change notification settings - Fork 135
Description
- I have tried with the latest version of my channel (Stable or Edge)
- I have submitted Diagnostics
- I have included the Diagnostics ID in this Issue
- macOS Version: 10.13.4 (17E199)
Expected behavior
When multiple processes are running in a tight loop that is checking if a file exists and reading it, the file should never be reported as not existing, assuming that the file is not accidentally deleted by another process.
Actual behavior
Node code (and likely other code as well, though I haven't yet tested other languages) that does what's described above will occasionally see that the file in question does not exist, even though it definitely does.
Information
This bug was observed when I was trying to compile the same EJS template in several worker processes at once. I observed that occasionally, one of the .ejs files that was included from the main template I was rendering would be reported as not existing, even though it definitely did. The included template was being used many times in the file, and so EJS was frequently checking if it existed and reading it.
Eventually, I determined that this failure only occurred if the following conditions
were met:
- The code is being run inside a Docker container
- Docker is being run on a Mac
- The file that we're trying to check the existence of is on a mounted volume.
If either of those conditions are broken (the code was run directly on the host, the file exists in the image itself, or Docker is run on a Windows/Linux machine), then the bug disappears. For this reason, I believe the bug is with Docker for Mac, and not Node or EJS.
Diagnostic ID: 15D5E555-47BB-4C80-9B0C-BEFAF3F272AF
Docker for Mac: version: 18.03.1-ce-mac65 (dd2831d4b7421cf559a0881cc7a5fdebeb8c2b98) macOS: version 10.13.4 (build: 17E199) logs: /tmp/15D5E555-47BB-4C80-9B0C-BEFAF3F272AF/20180502-163929.tar.gz [OK] vpnkit [OK] vmnetd [OK] dns [OK] driver.amd64-linux [OK] virtualization VT-X [OK] app [OK] moby [OK] system [OK] moby-syslog [OK] kubernetes [OK] files [OK] env [OK] virtualization kern.hv_support [OK] osxfs [OK] moby-console [OK] logs [OK] docker-cli [OK] disk Steps to reproduce the behavior
I was able to reproduce this case with a simple program that spawns two children with the threads package. Each child repeatedly checks if a file exists and reads the file in a tight loop. On my Mac, I observe that the file sometimes appears to not exist.
Given that the reproducible case requires more than just a simple Dockerfile (several other files, dependencies, and a specific folder), I have set up a self-contained example in the repo at https://github.com/nwalters512/docker-file-bug. I've copy-pasted the Dockerfile and Node code here.
Dockerfile
FROM node:carbon WORKDIR /usr/src/app COPY package*.json ./ RUN npm install COPY . . CMD [ "node", "index.js" ] index.js
const Pool = require('threads').Pool; const pool = new Pool(); pool.run((opts, done) => { const fs = require('fs'); const file = '/volume/exist.data'; for (let i = 0; i < 100; i++) { if (!fs.existsSync(file)) { console.log('File does not exist!'); } else { console.log('File exists.') } fs.readFileSync(file); } done(); }); for (let i = 0; i < 2; i++) { pool.send('test'); } pool.on('finished', () => pool.killAll());