Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cc866da3 authored by Christopher Tate's avatar Christopher Tate
Browse files

Fix cross-process race in initial files/cache dir creation

Apps that run components in separate processes, especially that
host providers in separate processes, can hit a race condition
where two processes simultaneously discover that the files/cache
dir must be created, then each calls mkdirs().  One of these will
fail not because the dir couldn't be created, but because it lost
the race and mkdirs() returned false to signal that it already
existed -- and this was assumed to be a hard failure.

We now recheck existence after a mkdirs() failure to discern this
case and proceed appropriately.

Bug 10515463

Change-Id: I13fbdd838921223f75ab11faa47291c82b21c650
parent 9ca82d33
Loading
Loading
Loading
Loading
+23 −12
Original line number Diff line number Diff line
@@ -817,6 +817,10 @@ class ContextImpl extends Context {
            }
            if (!mFilesDir.exists()) {
                if(!mFilesDir.mkdirs()) {
                    if (mFilesDir.exists()) {
                        // spurious failure; probably racing with another process for this app
                        return mFilesDir;
                    }
                    Log.w(TAG, "Unable to create files directory " + mFilesDir.getPath());
                    return null;
                }
@@ -879,6 +883,10 @@ class ContextImpl extends Context {
            }
            if (!mCacheDir.exists()) {
                if(!mCacheDir.mkdirs()) {
                    if (mCacheDir.exists()) {
                        // spurious failure; probably racing with another process for this app
                        return mCacheDir;
                    }
                    Log.w(TAG, "Unable to create cache directory " + mCacheDir.getAbsolutePath());
                    return null;
                }
@@ -2136,6 +2144,8 @@ class ContextImpl extends Context {
            File dir = dirs[i];
            if (!dir.exists()) {
                if (!dir.mkdirs()) {
                    // recheck existence in case of cross-process race
                    if (!dir.exists()) {
                        // Failing to mkdir() may be okay, since we might not have
                        // enough permissions; ask vold to create on our behalf.
                        final IMountService mount = IMountService.Stub.asInterface(
@@ -2151,6 +2161,7 @@ class ContextImpl extends Context {
                        }
                    }
                }
            }
            result[i] = dir;
        }
        return result;