Skip to content

Commit

Permalink
fix CacheDir race
Browse files Browse the repository at this point in the history
  • Loading branch information
David Siroky committed Dec 30, 2017
1 parent a3f0e74 commit 212fc5e
Showing 1 changed file with 46 additions and 49 deletions.
95 changes: 46 additions & 49 deletions src/engine/SCons/CacheDir.py
Expand Up @@ -32,6 +32,7 @@
import os
import stat
import sys
import threading

import SCons.Action
import SCons.Warnings
Expand Down Expand Up @@ -132,6 +133,8 @@ def CachePushFunc(target, source, env):
# upgrading.
warned = dict()

cache_lock = threading.Lock()

class CacheDir(object):

def __init__(self, path):
Expand All @@ -141,56 +144,50 @@ def __init__(self, path):
self.config = dict()
if path is None:
return
# See if there's a config file in the cache directory. If there is,
# use it. If there isn't, and the directory exists and isn't empty,
# produce a warning. If the directory doesn't exist or is empty,
# write a config file.
config_file = os.path.join(path, 'config')
if not os.path.exists(config_file):
# A note: There is a race hazard here, if two processes start and
# attempt to create the cache directory at the same time. However,
# python doesn't really give you the option to do exclusive file
# creation (it doesn't even give you the option to error on opening
# an existing file for writing...). The ordering of events here
# as an attempt to alleviate this, on the basis that it's a pretty
# unlikely occurence (it'd require two builds with a brand new cache
# directory)
if os.path.isdir(path) and len(os.listdir(path)) != 0:
self.config['prefix_len'] = 1
# When building the project I was testing this on, the warning
# was output over 20 times. That seems excessive
global warned
if self.path not in warned:
msg = "Please upgrade your cache by running " +\
" scons-configure-cache.py " + self.path
SCons.Warnings.warn(SCons.Warnings.CacheVersionWarning, msg)
warned[self.path] = True

with cache_lock:
# See if there's a config file in the cache directory. If there is,
# use it. If there isn't, and the directory exists and isn't empty,
# produce a warning. If the directory doesn't exist or is empty,
# write a config file.
config_file = os.path.join(path, 'config')
if not os.path.exists(config_file):
if os.path.isdir(path) and len(os.listdir(path)) != 0:
self.config['prefix_len'] = 1
# When building the project I was testing this on, the warning
# was output over 20 times. That seems excessive
global warned
if self.path not in warned:
msg = "Please upgrade your cache by running " +\
" scons-configure-cache.py " + self.path
SCons.Warnings.warn(SCons.Warnings.CacheVersionWarning, msg)
warned[self.path] = True
else:
if not os.path.isdir(path):
try:
os.makedirs(path)
except OSError:
# If someone else is trying to create the directory at
# the same time as me, bad things will happen
msg = "Failed to create cache directory " + path
raise SCons.Errors.EnvironmentError(msg)

self.config['prefix_len'] = 2
if not os.path.exists(config_file):
try:
with open(config_file, 'w') as config:
json.dump(self.config, config)
except:
msg = "Failed to write cache configuration for " + path
raise SCons.Errors.EnvironmentError(msg)
else:
if not os.path.isdir(path):
try:
os.makedirs(path)
except OSError:
# If someone else is trying to create the directory at
# the same time as me, bad things will happen
msg = "Failed to create cache directory " + path
raise SCons.Errors.EnvironmentError(msg)

self.config['prefix_len'] = 2
if not os.path.exists(config_file):
try:
with open(config_file, 'w') as config:
json.dump(self.config, config)
except:
msg = "Failed to write cache configuration for " + path
raise SCons.Errors.EnvironmentError(msg)
else:
try:
with open(config_file) as config:
self.config = json.load(config)
except ValueError:
msg = "Failed to read cache configuration for " + path
raise SCons.Errors.EnvironmentError(msg)

try:
with open(config_file) as config:
self.config = json.load(config)
except ValueError:
msg = "Failed to read cache configuration for " + path
raise SCons.Errors.EnvironmentError(msg)


def CacheDebug(self, fmt, target, cachefile):
if cache_debug != self.current_cache_debug:
Expand Down

0 comments on commit 212fc5e

Please sign in to comment.