Nightly monitoring of the zucchini rollout revealed a surge in SERVICE_STILL_APPLYING_ON_FAILURE, READ_ERROR and WRITE_ERROR during updates. This commit aims to address READ_ERROR and WRITE_ERROR on all platforms, and to address SERVICE_STILL_APPLYING_ON_FAILURE on Windows. Addressing SERVICE_STILL_APPLYING_ON_FAILURE on Linux and macOS is done in the follow-up commit. SERVICE_STILL_APPLYING_ON_FAILURE means the updater process exited without writing update.status, likely crashing. There are two potential sources of crashes in zucchini. First, Chromium CHECK macros call ImmediateCrash() (int3/ud2), which kills the process before WriteStatusFile can run. More likely, std::bad_alloc from non-fallible allocations in zucchini's disassembler (e.g. std::make_unique, std::deque::push_back when parsing a large PE like xul.dll) would also crash the process. Both cases can be caught by via SEH on Windows. READ_ERROR and WRITE_ERROR can mask OOMs from CreateFileMapping / MapViewOfFile failures (or mmap on POSIX) when zucchini tries to memory-map large files. Unlike bspatch which uses sequential I/O, zucchini memory-maps both the patch file and the output file, requiring significantly more virtual address space. This commit: 1. Adds an SEH exception filter (FilterZucchiniException) around zucchini's Load and ApplyUnsafe calls that catches EXCEPTION_IN_PAGE_ERROR (existing), EXCEPTION_BREAKPOINT / EXCEPTION_ILLEGAL_INSTRUCTION (CHECK failures), and 0xE06D7363 (std::bad_alloc). All are recoverable exceptions where the process state is sound. Exceptions indicating corrupt state (EXCEPTION_ACCESS_VIOLATION, etc.) are left unhandled. This improves crash recovery and OOM detection on Windows. 2. Introduces kStatusOutOfMemory in zucchini's status codes, mapped to BSPATCH_MEM_ERROR (12) in the updater. OOMs from the SEH exception path and from the mapping-failure path (via is_oom() from the previous commit) both flow through this code, which lets the update service knows that we are currently under memory pressure. 3. Eagerly resets mPatchFileDecoder in PatchFile::Execute() after Apply returns, so memory-mapped patch files are released between sequential patch actions rather than accumulating until the ActionList is destroyed. Differential Revision: https://phabricator.services.mozilla.com/D288918
307 lines
5.6 KiB
TOML
307 lines
5.6 KiB
TOML
[DEFAULT]
|
|
run-if = [
|
|
"os != 'android'",
|
|
]
|
|
tags = "appupdate base"
|
|
head = "head_no_service.js"
|
|
skip-if = [
|
|
"msix", # Our updater is disabled in MSIX builds
|
|
"os == 'win' && ccov",
|
|
]
|
|
support-files = [
|
|
"../data/shared.js",
|
|
"../data/sharedUpdateXML.js",
|
|
"../data/xpcshellUtilsAUS.js",
|
|
]
|
|
|
|
["invalidArgCallbackFileNotInInstallDirFailure.js"]
|
|
|
|
["invalidArgCallbackFilePathTooLongFailure.js"]
|
|
|
|
["invalidArgInstallDirPathTooLongFailure.js"]
|
|
|
|
["invalidArgInstallDirPathTraversalFailure.js"]
|
|
|
|
["invalidArgInstallWorkingDirPathNotSameFailure_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["invalidArgPatchDirPathTraversalFailure.js"]
|
|
|
|
["invalidArgStageDirNotInInstallDirFailure_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["invalidArgWorkingDirPathLocalUNCFailure_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["invalidArgWorkingDirPathRelativeFailure.js"]
|
|
|
|
["marAppApplyDirLockedStageFailure_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marAppApplyUpdateAppBinInUseStageSuccess_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marAppApplyUpdateSkippedWriteAccess_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marAppApplyUpdateStageOldVersionFailure.js"]
|
|
|
|
["marAppApplyUpdateStageSuccess.js"]
|
|
|
|
["marAppApplyUpdateSuccess.js"]
|
|
|
|
["marAppInUseBackgroundTaskFailure_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marAppInUseStageFailureComplete_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marAppInUseStageSuccessComplete_unix.js"]
|
|
run-if = [
|
|
"os != 'win'", # not a Windows test
|
|
]
|
|
|
|
["marAppInUseSuccessComplete.js"]
|
|
|
|
["marCallbackAppStageSuccessComplete_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marCallbackAppStageSuccessPartialZucchini_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marCallbackAppStageSuccessPartial_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marCallbackAppSuccessComplete_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marCallbackAppSuccessPartialZucchini_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marCallbackAppSuccessPartial_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marCallbackUmask_unix.js"]
|
|
run-if = [
|
|
"os != 'win'", # not a Windows test
|
|
]
|
|
reason = "Unix only test"
|
|
|
|
["marFailurePartial.js"]
|
|
|
|
["marFailurePartialZucchini.js"]
|
|
|
|
["marFailurePartialZucchiniBadAlloc_win.js"]
|
|
skip-if = [
|
|
"os != 'win'",
|
|
"tsan", # TSan intercepts operator new and aborts on OOM before bad_alloc
|
|
"asan", # Same issue with ASan
|
|
]
|
|
reason = "Windows only test, POSIX planned for bug 2043122"
|
|
|
|
["marFailurePartialZucchiniCheck_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test, POSIX planned for bug 2043122"
|
|
|
|
["marFailurePartialZucchiniCheckDestructor_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test, POSIX planned for bug 2043122"
|
|
|
|
["marFileInUseStageFailureComplete_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marFileInUseStageFailurePartialZucchini_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marFileInUseStageFailurePartial_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marFileInUseSuccessComplete_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marFileInUseSuccessPartialZucchini_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marFileInUseSuccessPartial_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marFileLockedFailureComplete_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marFileLockedFailurePartialZucchini_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marFileLockedFailurePartial_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marFileLockedStageFailureComplete_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marFileLockedStageFailurePartialZucchini_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marFileLockedStageFailurePartial_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marMissingUpdateSettings.js"]
|
|
|
|
["marMissingUpdateSettingsStage.js"]
|
|
|
|
["marPIDPersistsSuccessComplete_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marPostUpdateEnvironment.js"]
|
|
run-if = [
|
|
"os == 'mac'",
|
|
"os == 'win'",
|
|
]
|
|
reason = "Post-update only supported on Windows and macOS"
|
|
|
|
["marRMRFDirFileInUseStageFailureComplete_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marRMRFDirFileInUseStageFailurePartialZucchini_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marRMRFDirFileInUseStageFailurePartial_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marRMRFDirFileInUseSuccessComplete_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marRMRFDirFileInUseSuccessPartialZucchini_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marRMRFDirFileInUseSuccessPartial_win.js"]
|
|
run-if = [
|
|
"os == 'win'",
|
|
]
|
|
reason = "Windows only test"
|
|
|
|
["marStageFailurePartial.js"]
|
|
|
|
["marStageFailurePartialZucchini.js"]
|
|
|
|
["marStageSuccessComplete.js"]
|
|
run-sequentially = ["os == 'linux'"] # frequent fail in parallel on Linux
|
|
|
|
["marStageSuccessPartial.js"]
|
|
|
|
["marStageSuccessPartialZucchini.js"]
|
|
|
|
["marSuccessComplete.js"]
|
|
|
|
["marSuccessPartial.js"]
|
|
|
|
["marSuccessPartialWhileBackgroundTaskRunning.js"]
|
|
|
|
["marSuccessPartialZucchini.js"]
|
|
|
|
["marSuccessPartialZucchiniWhileBackgroundTaskRunning.js"]
|
|
|
|
["marVersionDowngrade.js"]
|
|
|
|
["marWrongChannel.js"]
|
|
|
|
["marWrongChannelStage.js"]
|