Skip to content

Commit

Permalink
Change internal locking while swizzling
Browse files Browse the repository at this point in the history
  • Loading branch information
HazAT committed Jun 14, 2017
1 parent c850a40 commit f4c7f40
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 79 deletions.
85 changes: 7 additions & 78 deletions Sources/Sentry/SentrySwizzle.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,78 +16,7 @@
#endif

#import <objc/runtime.h>
#include <dlfcn.h>

// Use os_unfair_lock over OSSpinLock when building with the following SDKs: iOS 10, macOS 10.12 and any tvOS and watchOS
#define DEPLOYMENT_TARGET_HIGHER_THAN_10 TARGET_OS_WATCH || TARGET_OS_TV || (TARGET_OS_IOS &&__IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_ALLOWED >= 101200)

#define BASE_SDK_HIGHER_THAN_10 (TARGET_OS_WATCH || TARGET_OS_TV || (TARGET_OS_IOS &&__IPHONE_OS_VERSION_MAX_ALLOWED >= 100000) || (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MAX_ALLOWED >= 101200))


#if BASE_SDK_HIGHER_THAN_10
#import <os/lock.h>
#else
// Below iOS 10, OS_UNFAIR_LOCK_INIT will not exist. Note that this type works with OSSpinLock
#define OS_UNFAIR_LOCK_INIT ((os_unfair_lock){0})

typedef struct _os_unfair_lock_s {
uint32_t _os_unfair_lock_opaque;
} os_unfair_lock, *os_unfair_lock_t;
#endif


#if !DEPLOYMENT_TARGET_HIGHER_THAN_10

#import <libkern/OSAtomic.h>

#endif


// NSDimension was introduced at the same time that os_unfair_lock_lock was made public, ie. iOS 10
#define DEVICE_HIGHER_THAN_10 objc_getClass("NSDimension")


#pragma mark Locking

// This function will lock a lock using os_unfair_lock_lock (on ios10/macos10.12) or OSSpinLockLock (9 and lower).
static void chooseLock(os_unfair_lock *lock) {
#if DEPLOYMENT_TARGET_HIGHER_THAN_10
// iOS 10+, os_unfair_lock_lock is available
os_unfair_lock_lock(lock);
#else
if (DEVICE_HIGHER_THAN_10) {
// Attempt to use os_unfair_lock_lock().
void (*os_unfair_lock_lock)(void *lock) = dlsym(dlopen(NULL, RTLD_NOW | RTLD_GLOBAL), "os_unfair_lock_lock");
if (os_unfair_lock_lock != NULL) {
os_unfair_lock_lock(lock);
return;
}
}

// Unfair locks are not available on iOS 9 and lower, using deprecated OSSpinLock.
OSSpinLockLock((void *) lock);
#endif
}

// This function will unlock a lock using os_unfair_lock_unlock (on ios10/macos10.12) or OSSpinLockUnlock (9 and lower).
static void chooseUnlock(os_unfair_lock *lock) {
#if DEPLOYMENT_TARGET_HIGHER_THAN_10
// iOS 10+, os_unfair_lock_unlock is available
os_unfair_lock_unlock(lock);
#else
if (DEVICE_HIGHER_THAN_10) {
// Attempt to use os_unfair_lock_unlock().
void (*os_unfair_lock_unlock)(void *lock) = dlsym(dlopen(NULL, RTLD_NOW | RTLD_GLOBAL), "os_unfair_lock_unlock");
if (os_unfair_lock_unlock != NULL) {
os_unfair_lock_unlock(lock);
return;
}
}

// Unfair locks are not available on iOS 9 and lower, using deprecated OSSpinUnlock.
OSSpinLockUnlock((void *) lock);
#endif
}
#include <pthread.h>

#pragma mark - Swizzling

Expand Down Expand Up @@ -126,7 +55,7 @@ static void swizzle(Class classToSwizzle,
class_isMetaClass(classToSwizzle) ? @"class" : @"instance",
classToSwizzle);

__block os_unfair_lock lock = OS_UNFAIR_LOCK_INIT;
static pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;

// To keep things thread-safe, we fill in the originalIMP later,
// with the result of the class_replaceMethod call below.
Expand All @@ -138,19 +67,19 @@ static void swizzle(Class classToSwizzle,
// class_replaceMethod and its return value being set.
// So to be sure originalIMP has the right value, we need a lock.


chooseLock(&lock);
pthread_mutex_lock(&gLock);

IMP imp = originalIMP;

chooseUnlock(&lock);
pthread_mutex_unlock(&gLock);

if (NULL == imp) {
// If the class does not implement the method
// we need to find an implementation in one of the superclasses.
Class superclass = class_getSuperclass(classToSwizzle);
imp = method_getImplementation(class_getInstanceMethod(superclass, selector));
}

return imp;
};

Expand All @@ -177,11 +106,11 @@ static void swizzle(Class classToSwizzle,
// We need a lock to be sure that originalIMP has the right value in the
// originalImpProvider block above.

chooseLock(&lock);
pthread_mutex_lock(&gLock);

originalIMP = class_replaceMethod(classToSwizzle, selector, newIMP, methodType);

chooseUnlock(&lock);
pthread_mutex_unlock(&gLock);
}


Expand Down
2 changes: 1 addition & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ it in your `Cartfile`:
Run ``carthage update`` to download the framework and drag the built
`Sentry.framework` into your Xcode project.

*Please note that with Carthage we had to bundle KSCrash into the `Sentry.framework` to make everything work.*
*Please note that for Carthage we had to bundle KSCrash into the ``Sentry.framework`` to make everything work. So you will always get KSCrash with Sentry when using Carthage.*

We also provide a prebuilt version for every release which can be downloaded at `releases on github
<https://github.com/getsentry/sentry-cocoa/releases>`__.
Expand Down

0 comments on commit f4c7f40

Please sign in to comment.