2024年5月7日发(作者:)
// later).
return;
}
// If we already called lock() but didn't succeed in getting the lock, it's possible the
// app caught the exception and tried again later. As above, there's no real advantage
// to failing here, so only open the lock file if we didn't already open it before.
if (sLockFile == null) {
String dataPath = aDirectory();
File lockFile = new File(dataPath, EXCLUSIVE_LOCK_FILE);
try {
// Note that the file is kept open intentionally.
sLockFile = new RandomAccessFile(lockFile, "rw");
} catch (IOException e) {
// Failing to create the lock file is always fatal; even if multiple processes
// are using the same data directory we should always be able to access the file
// itself.
throw new RuntimeException("Failed to create lock file " + lockFile, e);
}
}
// Android versions before 11 have edge cases where a new instance of an app process can
// be started while an existing one is still in the process of being killed. This can
// still happen on Android 11+ because the platform has a timeout for waiting, but it's
// much less likely. Retry the lock a few times to give the old process time to fully go
// away.
for (int attempts = 1; attempts <= LOCK_RETRIES; ++attempts) {
try {
sExclusiveFileLock = nnel().tryLock();
} catch (IOException e) {
// Older versions of Android incorrectly throw IOException when the flock()
// call fails with EAGAIN, instead of returning null. Just ignore it.
}
if (sExclusiveFileLock != null) {
// We got the lock; write out info for debugging.
writeCurrentProcessInfo(sLockFile);
return;
}
// If we're not out of retries, sleep and try again.
if (attempts == LOCK_RETRIES) break;
try {
(LOCK_SLEEP_MS);
} catch (InterruptedException e) {
}
}
// We failed to get the lock even after retrying.
// Many existing apps rely on this even though it's known to be unsafe.
// Make it fatal when on P for apps that target P or higher
String error = getLockFailureReason(sLockFile);
boolean dieOnFailure = _INT >= N_CODES.P
&& licationInfo().targetSdkVersion >= N_CODES.P;
if (dieOnFailure) {
throw new RuntimeException(error);
} else {
Log.w(TAG, error);
}
}
}
private static void writeCurrentProcessInfo(final RandomAccessFile file) {
try {
// Truncate the file first to get rid of old data.
gth(0);
nt(());
TF(cessName());
} catch (IOException e) {
// Don't crash just because something failed here, as it's only for debugging.
Log.w(TAG, "Failed to write info to lock file", e);
}
}
private static String getLockFailureReason(final RandomAccessFile file) {
final StringBuilder error = new StringBuilder("Using WebView from more than one process at "
+ "once with the same data directory is not supported. /558377 "
+ ": Current process ");
(cessName());
(" (pid ").append(()).append("), lock owner ");
try {
发布评论