{"record":{"id":"a232d9f41080b2d7","repo":"Tencent/tinker","slug":"tinker-exception-filelockhelper-lock-file-failed-a232d9","errorCode":null,"errorMessage":"Tinker Exception:FileLockHelper lock file failed: {}","messagePattern":"Tinker Exception:FileLockHelper lock file failed: (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/shareutil/ShareFileLockHelper.java","lineNumber":66,"sourceCode":"                if (isGetLockSuccess) {\n                    break;\n                }\n\n            } catch (Exception e) {\n                saveException = e;\n                ShareTinkerLog.e(TAG, \"getInfoLock Thread failed time:\" + LOCK_WAIT_EACH_TIME);\n            }\n\n            //it can just sleep 0, afraid of cpu scheduling\n            try {\n                Thread.sleep(LOCK_WAIT_EACH_TIME);\n            } catch (Exception ignore) {\n                ShareTinkerLog.e(TAG, \"getInfoLock Thread sleep exception\", ignore);\n            }\n        }\n\n        if (localFileLock == null) {\n            throw new IOException(\"Tinker Exception:FileLockHelper lock file failed: \" + lockFile.getAbsolutePath(), saveException);\n        }\n        fileLock = localFileLock;\n    }\n\n    public static ShareFileLockHelper getFileLock(File lockFile) throws IOException {\n        return new ShareFileLockHelper(lockFile);\n    }\n\n    @Override\n    public void close() throws IOException {\n        try {\n            if (fileLock != null) {\n                fileLock.release();\n            }\n        } finally {\n            if (outputStream != null) {\n                outputStream.close();\n            }","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/Tencent/tinker/blob/1b7ea02c239840f563ea64fb5bd286eb98d4011e/tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/shareutil/ShareFileLockHelper.java#L48-L84","documentation":"ShareFileLockHelper acquires an exclusive java.nio FileLock on a lock file, retrying with sleeps; if localFileLock is still null after all attempts it throws IOException(\"Tinker Exception:FileLockHelper lock file failed: <path>\") with the last saveException as cause. FileLock.tryLock can fail on filesystems that do not support POSIX locks or when another process/thread holds the lock.","triggerScenarios":"ShareFileLockHelper.getFileLock(lockFile) when tryLock() repeatedly throws IOException (e.g. lock held elsewhere, or the FS does not support locking) until the retry budget is exhausted.","commonSituations":"Patch info read/rewrite while a previous Tinker operation crashed holding the lock on some devices; multi-process apps where two processes patch simultaneously; certain OEM filesystems/emulated storage where FileLock is unsupported; lock file on a read-only or corrupted directory.","solutions":["Ensure only one process performs patch operations (guard with a process-level lock or route patching to the main process).","Make sure the lock file's parent directory exists and is writable before acquiring.","If a stale lock persists after a crash, reboot or clear the app's tinker directory so the lock file is recreated.","Catch IOException around getFileLock callers (readAndCheckPropertyWithLock / rewritePatchInfoFileWithLock) and surface a retryable patch failure instead of crashing.","Upgrade Tinker — newer versions tune lock wait/retry behavior."],"exampleFix":"// before\nfileLock = ShareFileLockHelper.getFileLock(lockFile);\n// after\ntry {\n    fileLock = ShareFileLockHelper.getFileLock(lockFile);\n} catch (IOException e) {\n    ShareTinkerLog.w(TAG, \"lock busy, retry patch later\", e);\n    return false;\n}","handlingStrategy":"retry","validationCode":"File lockParent = lockFile.getParentFile();\nif (lockParent == null || (!lockParent.exists() && !lockParent.mkdirs())) {\n    // cannot lock: fix directory before calling getFileLock\n}\nif (!lockParent.canWrite()) {\n    // read-only storage: patch ops will fail\n}","typeGuard":null,"tryCatchPattern":"try {\n    ShareFileLockHelper lock = ShareFileLockHelper.getFileLock(lockFile);\n    try { /* critical section */ } finally { lock.close(); }\n} catch (IOException e) {\n    // lock acquisition failed after retries: back off and retry the whole op later\n}","preventionTips":["Restrict patch loading/apply to a single process.","Always close ShareFileLockHelper in a finally block.","On persistent lock failure, clean the tinker lock files and retry once after process restart."],"tags":["android","tinker","file-lock","concurrency","io"],"backgroundTag":null,"analyzedSha":"1b7ea02c239840f563ea64fb5bd286eb98d4011e","analyzedAt":"2026-08-14T15:16:52.110Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}