Skip to content

Commit

Permalink
Create lockfile for improved compatibility with 3rd party updaters
Browse files Browse the repository at this point in the history
  • Loading branch information
core-code authored and vitorgalvao committed Sep 16, 2020
1 parent 7233bb9 commit cfd9630
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 1 deletion.
8 changes: 8 additions & 0 deletions Sparkle.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,8 @@
767B61AC1972D488004E0C3C /* SUGuidedPackageInstaller.h in Headers */ = {isa = PBXBuildFile; fileRef = 767B61AA1972D488004E0C3C /* SUGuidedPackageInstaller.h */; };
767B61AD1972D488004E0C3C /* SUGuidedPackageInstaller.m in Sources */ = {isa = PBXBuildFile; fileRef = 767B61AB1972D488004E0C3C /* SUGuidedPackageInstaller.m */; };
767B61AE1972D488004E0C3C /* SUGuidedPackageInstaller.m in Sources */ = {isa = PBXBuildFile; fileRef = 767B61AB1972D488004E0C3C /* SUGuidedPackageInstaller.m */; };
A3AD648C24D283F400058938 /* SUGlobalUpdateLock.m in Sources */ = {isa = PBXBuildFile; fileRef = A3AD648A24D283F400058938 /* SUGlobalUpdateLock.m */; };
A3AD648D24D283F400058938 /* SUGlobalUpdateLock.h in Headers */ = {isa = PBXBuildFile; fileRef = A3AD648B24D283F400058938 /* SUGlobalUpdateLock.h */; };
A5BF4F1D1BC7668B007A052A /* SUTestWebServer.m in Sources */ = {isa = PBXBuildFile; fileRef = A5BF4F1C1BC7668B007A052A /* SUTestWebServer.m */; };
B2D3F865245CEA24009BA78C /* URL+Hashing.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2D3F864245CEA24009BA78C /* URL+Hashing.swift */; };
C23E885B1BE7B24F0050BB73 /* SparkleTestCodeSignApp.enc.dmg in Resources */ = {isa = PBXBuildFile; fileRef = C23E88591BE7AF890050BB73 /* SparkleTestCodeSignApp.enc.dmg */; };
Expand Down Expand Up @@ -962,6 +964,8 @@
767B61AB1972D488004E0C3C /* SUGuidedPackageInstaller.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SUGuidedPackageInstaller.m; sourceTree = "<group>"; };
8DC2EF5A0486A6940098B216 /* Sparkle-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Sparkle-Info.plist"; sourceTree = "<group>"; };
8DC2EF5B0486A6940098B216 /* Sparkle.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Sparkle.framework; sourceTree = BUILT_PRODUCTS_DIR; };
A3AD648A24D283F400058938 /* SUGlobalUpdateLock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SUGlobalUpdateLock.m; sourceTree = "<group>"; };
A3AD648B24D283F400058938 /* SUGlobalUpdateLock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SUGlobalUpdateLock.h; sourceTree = "<group>"; };
A5BF4F1B1BC7668B007A052A /* SUTestWebServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SUTestWebServer.h; sourceTree = "<group>"; };
A5BF4F1C1BC7668B007A052A /* SUTestWebServer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SUTestWebServer.m; sourceTree = "<group>"; };
B2D3F864245CEA24009BA78C /* URL+Hashing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+Hashing.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1553,6 +1557,8 @@
61299A2E09CA2DAB00B7442F /* SUSignatureVerifier.m */,
729924711DF3478A00DBCDF5 /* SUUpdateValidator.h */,
729924721DF3478A00DBCDF5 /* SUUpdateValidator.m */,
A3AD648B24D283F400058938 /* SUGlobalUpdateLock.h */,
A3AD648A24D283F400058938 /* SUGlobalUpdateLock.m */,
);
name = Support;
sourceTree = "<group>";
Expand Down Expand Up @@ -1670,6 +1676,7 @@
611142E910FB1BE5009810AA /* bspatch.h in Headers */,
5AB8F185214D564C00A1187F /* ed25519.h in Headers */,
5AB8F184214D564C00A1187F /* fe.h in Headers */,
A3AD648D24D283F400058938 /* SUGlobalUpdateLock.h in Headers */,
5AB8F18A214D564C00A1187F /* fixedint.h in Headers */,
5AB8F18B214D564C00A1187F /* ge.h in Headers */,
5AB8F187214D564C00A1187F /* precomp_data.h in Headers */,
Expand Down Expand Up @@ -2450,6 +2457,7 @@
6196CFFA09C72149000DC222 /* SUStatusController.m in Sources */,
61A2279D0D1CEE7600430CCD /* SUSystemProfiler.m in Sources */,
72316BE41E0E1C7F0039EFD9 /* SUSystemUpdateInfo.m in Sources */,
A3AD648C24D283F400058938 /* SUGlobalUpdateLock.m in Sources */,
E1545EC61E1D7E0200FAECE8 /* SUTouchBarButtonGroup.m in Sources */,
61B93A3D0DD02D7000DCD2F8 /* SUUIBasedUpdateDriver.m in Sources */,
61299A8E09CA790200B7442F /* SUUnarchiver.m in Sources */,
Expand Down
7 changes: 7 additions & 0 deletions Sparkle/SUBasicUpdateDriver.m
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#import "SUUpdater.h"
#import "SUAppcast.h"
#import "SUAppcastItem.h"
#import "SUGlobalUpdateLock.h"

#import "SPUURLRequest.h"
#import "SPUDownloaderDeprecated.h"
Expand Down Expand Up @@ -301,6 +302,9 @@ - (void)downloadUpdate
[[NSFileManager defaultManager] removeItemAtPath:appCachePath error:NULL];
}

// Ensure no other thirdparty app-updater is concurrently updating this app.
[[SUGlobalUpdateLock sharedLock] lock];

id<SUUpdaterPrivate> updater = self.updater;

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[self.updateItem fileURL]];
Expand Down Expand Up @@ -677,6 +681,9 @@ - (void)installerForHost:(SUHost *)aHost failedWithError:(NSError *)error

- (void)abortUpdate
{
// Remove lockfile to prevent 3rd party updaters from updating this app if the update is not going to happen anyway
[[SUGlobalUpdateLock sharedLock] unlock];

[self cleanUpDownload];
[[NSNotificationCenter defaultCenter] removeObserver:self];
self.updateItem = nil;
Expand Down
26 changes: 26 additions & 0 deletions Sparkle/SUGlobalUpdateLock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// SUGlobalUpdateLock.h
// Sparkle
//
// Created by Bibhas Acharya on 7/12/20.
// Copyright © 2020 Sparkle Project. All rights reserved.
//

#ifndef SUGLOBALUPDATELOCK_H
#define SUGLOBALUPDATELOCK_H

#if __has_feature(modules)
@import Foundation;
#else
#import <Foundation/Foundation.h>
#endif

@interface SUGlobalUpdateLock : NSObject

+ (SUGlobalUpdateLock *)sharedLock;
- (void)lock;
- (void)unlock;

@end

#endif
65 changes: 65 additions & 0 deletions Sparkle/SUGlobalUpdateLock.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//
// SUGlobalUpdateFileLock.m
// Sparkle
//
// Created by Bibhas Acharya on 7/12/20.
// Copyright © 2020 Sparkle Project. All rights reserved.
//

#import "SUGlobalUpdateLock.h"
#import "SULog.h"


@implementation SUGlobalUpdateLock

+ (SUGlobalUpdateLock *)sharedLock
{
static dispatch_once_t once;
static SUGlobalUpdateLock *sharedInstance = nil;
dispatch_once(&once, ^{
sharedInstance = [self new];
});
return sharedInstance;
}

- (void)lock
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *fileLockPath = [self fileLockPath];

BOOL success = [fileManager createFileAtPath:fileLockPath contents:nil attributes:nil];
if (!success) {
SULog(SULogLevelDefault, @"Couldn't create lockfile at: %@", fileLockPath);
}
}

- (void)unlock
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *fileLockPath = [self fileLockPath];

if ([fileManager fileExistsAtPath:fileLockPath]) {
NSError *error = nil;
[fileManager removeItemAtPath:fileLockPath error:&error];
if (error != nil) {
SULog(SULogLevelError, @"Couldn't remove lockfile at: %@ [%@]", fileLockPath, [error localizedDescription]);
}
}
}

- (NSString *)identifier
{
NSString *resp = [[NSBundle mainBundle] bundleIdentifier];
if (resp == nil) {
// If there's no bundle identifier, use the executable path
resp = [[[NSBundle mainBundle] executablePath] stringByReplacingOccurrencesOfString:@"/" withString:@"."];
}
return resp;
}

- (NSString *)fileLockPath
{
return [NSString stringWithFormat:@"/private/var/tmp/%@.Sparkle.pid", [self identifier]];
}

@end
2 changes: 1 addition & 1 deletion Sparkle/SUPlainInstaller.m
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ - (BOOL)performInstallationToURL:(NSURL *)installationURL fromUpdateAtURL:(NSURL
if (progress) {
progress(9/10.0);
}

// Try to preserve Finder tags. Failure can be accepted without complaint as previous Sparkle versions did not do this at all
if (SUAVAILABLE(10, 9)) {
NSArray *resourceTags;
Expand Down
3 changes: 3 additions & 0 deletions Sparkle/SUUpdater.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#import "SUSystemUpdateInfo.h"
#import "SUSignatures.h"
#import "SUOperatingSystem.h"
#import "SUGlobalUpdateLock.h"

NSString *const SUUpdaterDidFinishLoadingAppCastNotification = @"SUUpdaterDidFinishLoadingAppCastNotification";
NSString *const SUUpdaterDidFindValidUpdateNotification = @"SUUpdaterDidFindValidUpdateNotification";
Expand Down Expand Up @@ -222,6 +223,8 @@ - (void)startUpdateCycle
[self.host setBool:NO forUserDefaultsKey:SUUpdateRelaunchingMarkerKey];
}

[[SUGlobalUpdateLock sharedLock] unlock]; // For safety, remove active lock if present in any case and not just when relaunching from an app update

if (shouldPrompt) {
NSArray<NSDictionary<NSString *, NSString *> *> *profileInfo = [SUSystemProfiler systemProfileArrayForHost:self.host];
// Always say we're sending the system profile here so that the delegate displays the parameters it would send.
Expand Down

0 comments on commit cfd9630

Please sign in to comment.