fix: Squirrel.Mac crash when zip extraction fails (#47300)
* fix: Squirrel.Mac crash when zip extraction process fails to launch Co-authored-by: Niklas Wenzel <dev@nikwen.de> * chore: add end-to-end test Co-authored-by: Niklas Wenzel <dev@nikwen.de> --------- Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com> Co-authored-by: Niklas Wenzel <dev@nikwen.de>
This commit is contained in:
parent
1487f5d8b4
commit
2a707ffbd8
4 changed files with 81 additions and 0 deletions
|
@ -7,3 +7,4 @@ fix_abort_installation_attempt_at_the_final_mile_if_the_app_is.patch
|
||||||
feat_add_ability_to_prevent_version_downgrades.patch
|
feat_add_ability_to_prevent_version_downgrades.patch
|
||||||
refactor_use_non-deprecated_nskeyedarchiver_apis.patch
|
refactor_use_non-deprecated_nskeyedarchiver_apis.patch
|
||||||
chore_turn_off_launchapplicationaturl_deprecation_errors_in_squirrel.patch
|
chore_turn_off_launchapplicationaturl_deprecation_errors_in_squirrel.patch
|
||||||
|
fix_crash_when_process_to_extract_zip_cannot_be_launched.patch
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Niklas Wenzel <dev@nikwen.de>
|
||||||
|
Date: Tue, 27 May 2025 02:03:54 +0200
|
||||||
|
Subject: fix: crash when process to extract zip cannot be launched
|
||||||
|
|
||||||
|
Fixes https://github.com/electron/electron/issues/47270
|
||||||
|
|
||||||
|
diff --git a/Squirrel/SQRLZipArchiver.m b/Squirrel/SQRLZipArchiver.m
|
||||||
|
index 68f5dac8e553638f41306956df9d38eeda18f8f2..a9cd676df63e19edf9e20473d27b85591c7cb49e 100644
|
||||||
|
--- a/Squirrel/SQRLZipArchiver.m
|
||||||
|
+++ b/Squirrel/SQRLZipArchiver.m
|
||||||
|
@@ -153,7 +153,17 @@ - (RACSignal *)launchWithArguments:(NSArray *)arguments {
|
||||||
|
setNameWithFormat:@"-launchWithArguments: %@", arguments];
|
||||||
|
|
||||||
|
self.dittoTask.arguments = arguments;
|
||||||
|
- [self.dittoTask launch];
|
||||||
|
+
|
||||||
|
+ NSError *launchError = nil;
|
||||||
|
+
|
||||||
|
+ if (![self.dittoTask launchAndReturnError:&launchError]) {
|
||||||
|
+ NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
|
||||||
|
+ userInfo[NSLocalizedDescriptionKey] = launchError.localizedDescription;
|
||||||
|
+
|
||||||
|
+ NSLog(@"Starting ditto task failed with error: %@", launchError.localizedDescription);
|
||||||
|
+
|
||||||
|
+ return [RACSignal error:[NSError errorWithDomain:SQRLZipArchiverErrorDomain code:SQRLZipArchiverShellTaskFailed userInfo:userInfo]];
|
||||||
|
+ }
|
||||||
|
|
||||||
|
return signal;
|
||||||
|
}
|
|
@ -42,6 +42,16 @@ ifdescribe(shouldRunCodesignTests)('autoUpdater behavior', function () {
|
||||||
return cp.spawn(path.resolve(appPath, 'Contents/MacOS/Electron'), args);
|
return cp.spawn(path.resolve(appPath, 'Contents/MacOS/Electron'), args);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const launchAppSandboxed = (appPath: string, profilePath: string, args: string[] = []) => {
|
||||||
|
return spawn('/usr/bin/sandbox-exec', [
|
||||||
|
'-f',
|
||||||
|
profilePath,
|
||||||
|
path.resolve(appPath, 'Contents/MacOS/Electron'),
|
||||||
|
...args,
|
||||||
|
'--no-sandbox'
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
const getRunningShipIts = async (appPath: string) => {
|
const getRunningShipIts = async (appPath: string) => {
|
||||||
const processes = await psList();
|
const processes = await psList();
|
||||||
const activeShipIts = processes.filter(p => p.cmd?.includes('Squirrel.framework/Resources/ShipIt com.github.Electron.ShipIt') && p.cmd!.startsWith(appPath));
|
const activeShipIts = processes.filter(p => p.cmd?.includes('Squirrel.framework/Resources/ShipIt com.github.Electron.ShipIt') && p.cmd!.startsWith(appPath));
|
||||||
|
@ -740,6 +750,41 @@ ifdescribe(shouldRunCodesignTests)('autoUpdater behavior', function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should hit the download endpoint when an update is available and fail when the zip extraction process fails to launch', async () => {
|
||||||
|
await withUpdatableApp({
|
||||||
|
nextVersion: '2.0.0',
|
||||||
|
startFixture: 'update',
|
||||||
|
endFixture: 'update'
|
||||||
|
}, async (appPath, updateZipPath) => {
|
||||||
|
server.get('/update-file', (req, res) => {
|
||||||
|
res.download(updateZipPath);
|
||||||
|
});
|
||||||
|
server.get('/update-check', (req, res) => {
|
||||||
|
res.json({
|
||||||
|
url: `http://localhost:${port}/update-file`,
|
||||||
|
name: 'My Release Name',
|
||||||
|
notes: 'Theses are some release notes innit',
|
||||||
|
pub_date: (new Date()).toString()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
const launchResult = await launchAppSandboxed(
|
||||||
|
appPath,
|
||||||
|
path.resolve(__dirname, 'fixtures/auto-update/sandbox/block-ditto.sb'),
|
||||||
|
[`http://localhost:${port}/update-check`]
|
||||||
|
);
|
||||||
|
logOnError(launchResult, () => {
|
||||||
|
expect(launchResult).to.have.property('code', 1);
|
||||||
|
expect(launchResult.out).to.include('Starting ditto task failed with error:');
|
||||||
|
expect(launchResult.out).to.include('SQRLZipArchiverErrorDomain');
|
||||||
|
expect(requests).to.have.lengthOf(2);
|
||||||
|
expect(requests[0]).to.have.property('url', '/update-check');
|
||||||
|
expect(requests[1]).to.have.property('url', '/update-file');
|
||||||
|
expect(requests[0].header('user-agent')).to.include('Electron/');
|
||||||
|
expect(requests[1].header('user-agent')).to.include('Electron/');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should hit the download endpoint when an update is available and update successfully when the zip is provided with JSON update mode', async () => {
|
it('should hit the download endpoint when an update is available and update successfully when the zip is provided with JSON update mode', async () => {
|
||||||
await withUpdatableApp({
|
await withUpdatableApp({
|
||||||
nextVersion: '2.0.0',
|
nextVersion: '2.0.0',
|
||||||
|
|
5
spec/fixtures/auto-update/sandbox/block-ditto.sb
vendored
Normal file
5
spec/fixtures/auto-update/sandbox/block-ditto.sb
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
(version 1)
|
||||||
|
(allow default)
|
||||||
|
(deny process-exec
|
||||||
|
(literal "/usr/bin/ditto")
|
||||||
|
)
|
Loading…
Add table
Add a link
Reference in a new issue