mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-08-25 21:17:03 +00:00
Fixed: XCC was crashing on startup in OS X 10.6
The Lumberjack logging library was using a function not present in 10.6. This commit reverts to an earlier release that works with 10.6.
This commit is contained in:
@@ -76,15 +76,15 @@ static DDASLLogger *sharedInstance;
|
||||
const char *msg = [logMsg UTF8String];
|
||||
|
||||
int aslLogLevel;
|
||||
switch (logMessage->logFlag)
|
||||
switch (logMessage->logLevel)
|
||||
{
|
||||
// Note: By default ASL will filter anything above level 5 (Notice).
|
||||
// So our mappings shouldn't go above that level.
|
||||
|
||||
case LOG_FLAG_ERROR : aslLogLevel = ASL_LEVEL_CRIT; break;
|
||||
case LOG_FLAG_WARN : aslLogLevel = ASL_LEVEL_ERR; break;
|
||||
case LOG_FLAG_INFO : aslLogLevel = ASL_LEVEL_WARNING; break;
|
||||
default : aslLogLevel = ASL_LEVEL_NOTICE; break;
|
||||
case 1 : aslLogLevel = ASL_LEVEL_CRIT; break;
|
||||
case 2 : aslLogLevel = ASL_LEVEL_ERR; break;
|
||||
case 3 : aslLogLevel = ASL_LEVEL_WARNING; break;
|
||||
default : aslLogLevel = ASL_LEVEL_NOTICE; break;
|
||||
}
|
||||
|
||||
asl_log(client, NULL, aslLogLevel, "%s", msg);
|
||||
|
||||
@@ -252,7 +252,7 @@ NSString *DDExtractFileNameWithoutExtension(const char *filePath, BOOL copy);
|
||||
/**
|
||||
* The THIS_METHOD macro gives you the name of the current objective-c method.
|
||||
*
|
||||
* For example: DDLogWarn(@"%@ - Requires non-nil strings", THIS_METHOD) -> @"setMake:model: requires non-nil strings"
|
||||
* For example: DDLogWarn(@"%@ - Requires non-nil strings") -> @"setMake:model: requires non-nil strings"
|
||||
*
|
||||
* Note: This does NOT work in straight C functions (non objective-c).
|
||||
* Instead you should use the predefined __FUNCTION__ macro.
|
||||
@@ -489,7 +489,7 @@ NSString *DDExtractFileNameWithoutExtension(const char *filePath, BOOL copy);
|
||||
|
||||
enum {
|
||||
DDLogMessageCopyFile = 1 << 0,
|
||||
DDLogMessageCopyFunction = 1 << 1
|
||||
DDLogMessageCopyFunction = 1 << 1,
|
||||
};
|
||||
typedef int DDLogMessageOptions;
|
||||
|
||||
@@ -594,8 +594,4 @@ typedef int DDLogMessageOptions;
|
||||
- (id <DDLogFormatter>)logFormatter;
|
||||
- (void)setLogFormatter:(id <DDLogFormatter>)formatter;
|
||||
|
||||
// For thread-safety assertions
|
||||
- (BOOL)isOnGlobalLoggingQueue;
|
||||
- (BOOL)isOnInternalLoggerQueue;
|
||||
|
||||
@end
|
||||
|
||||
@@ -22,6 +22,31 @@
|
||||
#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
|
||||
#endif
|
||||
|
||||
// Does ARC support support GCD objects?
|
||||
// It does if the minimum deployment target is iOS 6+ or Mac OS X 8+
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
|
||||
// Compiling for iOS
|
||||
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 60000 // iOS 6.0 or later
|
||||
#define NEEDS_DISPATCH_RETAIN_RELEASE 0
|
||||
#else // iOS 5.X or earlier
|
||||
#define NEEDS_DISPATCH_RETAIN_RELEASE 1
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
// Compiling for Mac OS X
|
||||
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 // Mac OS X 10.8 or later
|
||||
#define NEEDS_DISPATCH_RETAIN_RELEASE 0
|
||||
#else
|
||||
#define NEEDS_DISPATCH_RETAIN_RELEASE 1 // Mac OS X 10.7 or earlier
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// We probably shouldn't be using DDLog() statements within the DDLog implementation.
|
||||
// But we still want to leave our log statements for any future debugging,
|
||||
// and to allow other developers to trace the implementation (which is a great learning tool).
|
||||
@@ -46,14 +71,6 @@
|
||||
|
||||
#define LOG_MAX_QUEUE_SIZE 1000 // Should not exceed INT32_MAX
|
||||
|
||||
// The "global logging queue" refers to [DDLog loggingQueue].
|
||||
// It is the queue that all log statements go through.
|
||||
//
|
||||
// The logging queue sets a flag via dispatch_queue_set_specific using this key.
|
||||
// We can check for this key via dispatch_get_specific() to see if we're on the "global logging queue".
|
||||
|
||||
static void *const GlobalLoggingQueueIdentityKey = (void *)&GlobalLoggingQueueIdentityKey;
|
||||
|
||||
|
||||
@interface DDLoggerNode : NSObject {
|
||||
@public
|
||||
@@ -122,9 +139,6 @@ static unsigned int numProcessors;
|
||||
loggingQueue = dispatch_queue_create("cocoa.lumberjack", NULL);
|
||||
loggingGroup = dispatch_group_create();
|
||||
|
||||
void *nonNullValue = GlobalLoggingQueueIdentityKey; // Whatever, just not null
|
||||
dispatch_queue_set_specific(loggingQueue, GlobalLoggingQueueIdentityKey, nonNullValue, NULL);
|
||||
|
||||
queueSemaphore = dispatch_semaphore_create(LOG_MAX_QUEUE_SIZE);
|
||||
|
||||
// Figure out how many processors are available.
|
||||
@@ -150,7 +164,7 @@ static unsigned int numProcessors;
|
||||
NSString *notificationName = @"NSApplicationWillTerminateNotification";
|
||||
#endif
|
||||
|
||||
[NSNotificationCenter.defaultCenter addObserver:self
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(applicationWillTerminate:)
|
||||
name:notificationName
|
||||
object:nil];
|
||||
@@ -429,7 +443,6 @@ static unsigned int numProcessors;
|
||||
// So we can allocate our buffer, and get pointers to all the class definitions.
|
||||
|
||||
Class *classes = (Class *)malloc(sizeof(Class) * numClasses);
|
||||
if (classes == NULL) return nil;
|
||||
|
||||
numClasses = objc_getClassList(classes, numClasses);
|
||||
|
||||
@@ -781,7 +794,7 @@ NSString *DDExtractFileNameWithoutExtension(const char *filePath, BOOL copy)
|
||||
|
||||
if (aLoggerQueue) {
|
||||
loggerQueue = aLoggerQueue;
|
||||
#if !OS_OBJECT_USE_OBJC
|
||||
#if NEEDS_DISPATCH_RETAIN_RELEASE
|
||||
dispatch_retain(loggerQueue);
|
||||
#endif
|
||||
}
|
||||
@@ -796,7 +809,7 @@ NSString *DDExtractFileNameWithoutExtension(const char *filePath, BOOL copy)
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
#if !OS_OBJECT_USE_OBJC
|
||||
#if NEEDS_DISPATCH_RETAIN_RELEASE
|
||||
if (loggerQueue) dispatch_release(loggerQueue);
|
||||
#endif
|
||||
}
|
||||
@@ -815,7 +828,6 @@ static char *dd_str_copy(const char *str)
|
||||
|
||||
size_t length = strlen(str);
|
||||
char * result = malloc(length + 1);
|
||||
if (result == NULL) return NULL;
|
||||
strncpy(result, str, length);
|
||||
result[length] = 0;
|
||||
|
||||
@@ -848,7 +860,7 @@ static char *dd_str_copy(const char *str)
|
||||
file = (char *)aFile;
|
||||
|
||||
if (options & DDLogMessageCopyFunction)
|
||||
function = dd_str_copy(aFunction);
|
||||
file = dd_str_copy(aFunction);
|
||||
else
|
||||
function = (char *)aFunction;
|
||||
|
||||
@@ -856,24 +868,7 @@ static char *dd_str_copy(const char *str)
|
||||
|
||||
machThreadID = pthread_mach_thread_np(pthread_self());
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
// The documentation for dispatch_get_current_queue() states:
|
||||
//
|
||||
// > [This method is] "recommended for debugging and logging purposes only"...
|
||||
//
|
||||
// Well that's exactly how we're using it here. Literally for logging purposes only.
|
||||
// However, Apple has decided to deprecate this method anyway.
|
||||
// However they have not given us an alternate version of dispatch_queue_get_label() that
|
||||
// automatically uses the current queue, thus dispatch_get_current_queue() is still required.
|
||||
//
|
||||
// If dispatch_get_current_queue() disappears, without a dispatch_queue_get_label() alternative,
|
||||
// Apple will have effectively taken away our ability to properly log the name of executing dispatch queue.
|
||||
|
||||
dispatch_queue_t currentQueue = dispatch_get_current_queue();
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
queueLabel = dd_str_copy(dispatch_queue_get_label(currentQueue));
|
||||
queueLabel = dd_str_copy(dispatch_queue_get_label(dispatch_get_current_queue()));
|
||||
|
||||
threadName = [[NSThread currentThread] name];
|
||||
}
|
||||
@@ -929,32 +924,13 @@ static char *dd_str_copy(const char *str)
|
||||
}
|
||||
|
||||
loggerQueue = dispatch_queue_create(loggerQueueName, NULL);
|
||||
|
||||
// We're going to use dispatch_queue_set_specific() to "mark" our loggerQueue.
|
||||
// Later we can use dispatch_get_specific() to determine if we're executing on our loggerQueue.
|
||||
// The documentation states:
|
||||
//
|
||||
// > Keys are only compared as pointers and are never dereferenced.
|
||||
// > Thus, you can use a pointer to a static variable for a specific subsystem or
|
||||
// > any other value that allows you to identify the value uniquely.
|
||||
// > Specifying a pointer to a string constant is not recommended.
|
||||
//
|
||||
// So we're going to use the very convenient key of "self",
|
||||
// which also works when multiple logger classes extend this class, as each will have a different "self" key.
|
||||
//
|
||||
// This is used primarily for thread-safety assertions (via the isOnInternalLoggerQueue method below).
|
||||
|
||||
void *key = (__bridge void *)self;
|
||||
void *nonNullValue = (__bridge void *)self;
|
||||
|
||||
dispatch_queue_set_specific(loggerQueue, key, nonNullValue, NULL);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
#if !OS_OBJECT_USE_OBJC
|
||||
#if NEEDS_DISPATCH_RETAIN_RELEASE
|
||||
if (loggerQueue) dispatch_release(loggerQueue);
|
||||
#endif
|
||||
}
|
||||
@@ -974,70 +950,78 @@ static char *dd_str_copy(const char *str)
|
||||
//
|
||||
// They would expect formatter to equal myFormatter.
|
||||
// This functionality must be ensured by the getter and setter method.
|
||||
//
|
||||
//
|
||||
// The thread safety must not come at a cost to the performance of the logMessage method.
|
||||
// This method is likely called sporadically, while the logMessage method is called repeatedly.
|
||||
// This means, the implementation of this method:
|
||||
// - Must NOT require the logMessage method to acquire a lock.
|
||||
// - Must NOT require the logMessage method to access an atomic property (also a lock of sorts).
|
||||
//
|
||||
//
|
||||
// Thread safety is ensured by executing access to the formatter variable on the loggerQueue.
|
||||
// This is the same queue that the logMessage method operates on.
|
||||
//
|
||||
//
|
||||
// Note: The last time I benchmarked the performance of direct access vs atomic property access,
|
||||
// direct access was over twice as fast on the desktop and over 6 times as fast on the iPhone.
|
||||
//
|
||||
// Furthermore, consider the following code:
|
||||
//
|
||||
//
|
||||
// loggerQueue : Our own private internal queue that the logMessage method runs on.
|
||||
// Operations are added to this queue from the global loggingQueue.
|
||||
//
|
||||
// loggingQueue : The queue that all log messages go through before they arrive in our loggerQueue.
|
||||
//
|
||||
// It is important to note that, while the loggerQueue is used to create thread-safety for our formatter,
|
||||
// changes to the formatter variable are queued through the loggingQueue.
|
||||
//
|
||||
// Since this will obviously confuse the hell out of me later, here is a better description.
|
||||
// Imagine the following code:
|
||||
//
|
||||
// DDLogVerbose(@"log msg 1");
|
||||
// DDLogVerbose(@"log msg 2");
|
||||
// [logger setFormatter:myFormatter];
|
||||
// DDLogVerbose(@"log msg 3");
|
||||
//
|
||||
//
|
||||
// Our intuitive requirement means that the new formatter will only apply to the 3rd log message.
|
||||
// This must remain true even when using asynchronous logging.
|
||||
// We must keep in mind the various queue's that are in play here:
|
||||
// But notice what happens if we have asynchronous logging enabled for verbose mode.
|
||||
//
|
||||
// loggerQueue : Our own private internal queue that the logMessage method runs on.
|
||||
// Operations are added to this queue from the global loggingQueue.
|
||||
// Log msg 1 starts executing asynchronously on the loggingQueue.
|
||||
// The loggingQueue executes the log statement on each logger concurrently.
|
||||
// That means it executes log msg 1 on our loggerQueue.
|
||||
// While log msg 1 is executing, log msg 2 gets added to the loggingQueue.
|
||||
// Then the user requests that we change our formatter.
|
||||
// So at this exact moment, our queues look like this:
|
||||
//
|
||||
// globalLoggingQueue : The queue that all log messages go through before they arrive in our loggerQueue.
|
||||
// loggerQueue : executing log msg 1, nil
|
||||
// loggingQueue : executing log msg 1, log msg 2, nil
|
||||
//
|
||||
// All log statements go through the serial gloabalLoggingQueue before they arrive at our loggerQueue.
|
||||
// Thus this method also goes through the serial globalLoggingQueue to ensure intuitive operation.
|
||||
// So direct access to the formatter is only available if requested from the loggerQueue.
|
||||
// In all other circumstances we need to go through the loggingQueue to get the proper value.
|
||||
|
||||
// IMPORTANT NOTE:
|
||||
//
|
||||
// Methods within the DDLogger implementation MUST access the formatter ivar directly.
|
||||
// This method is designed explicitly for external access.
|
||||
//
|
||||
// Using "self." syntax to go through this method will cause immediate deadlock.
|
||||
// This is the intended result. Fix it by accessing the ivar directly.
|
||||
// Great strides have been take to ensure this is safe to do. Plus it's MUCH faster.
|
||||
|
||||
NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
|
||||
NSAssert(![self isOnInternalLoggerQueue], @"MUST access ivar directly, NOT via self.* syntax.");
|
||||
|
||||
dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
|
||||
|
||||
__block id <DDLogFormatter> result;
|
||||
|
||||
dispatch_sync(globalLoggingQueue, ^{
|
||||
dispatch_sync(loggerQueue, ^{
|
||||
result = formatter;
|
||||
dispatch_queue_t currentQueue = dispatch_get_current_queue();
|
||||
if (currentQueue == loggerQueue)
|
||||
{
|
||||
return formatter;
|
||||
}
|
||||
else
|
||||
{
|
||||
dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
|
||||
NSAssert(currentQueue != globalLoggingQueue, @"Core architecture requirement failure");
|
||||
|
||||
__block id <DDLogFormatter> result;
|
||||
|
||||
dispatch_sync(globalLoggingQueue, ^{
|
||||
dispatch_sync(loggerQueue, ^{
|
||||
result = formatter;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return result;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setLogFormatter:(id <DDLogFormatter>)logFormatter
|
||||
{
|
||||
// The design of this method is documented extensively in the logFormatter message (above in code).
|
||||
|
||||
NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
|
||||
NSAssert(![self isOnInternalLoggerQueue], @"MUST access ivar directly, NOT via self.* syntax.");
|
||||
|
||||
dispatch_block_t block = ^{ @autoreleasepool {
|
||||
|
||||
if (formatter != logFormatter)
|
||||
@@ -1045,7 +1029,7 @@ static char *dd_str_copy(const char *str)
|
||||
if ([formatter respondsToSelector:@selector(willRemoveFromLogger:)]) {
|
||||
[formatter willRemoveFromLogger:self];
|
||||
}
|
||||
|
||||
|
||||
formatter = logFormatter;
|
||||
|
||||
if ([formatter respondsToSelector:@selector(didAddToLogger:)]) {
|
||||
@@ -1054,11 +1038,20 @@ static char *dd_str_copy(const char *str)
|
||||
}
|
||||
}};
|
||||
|
||||
dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
|
||||
|
||||
dispatch_async(globalLoggingQueue, ^{
|
||||
dispatch_async(loggerQueue, block);
|
||||
});
|
||||
dispatch_queue_t currentQueue = dispatch_get_current_queue();
|
||||
if (currentQueue == loggerQueue)
|
||||
{
|
||||
block();
|
||||
}
|
||||
else
|
||||
{
|
||||
dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
|
||||
NSAssert(currentQueue != globalLoggingQueue, @"Core architecture requirement failure");
|
||||
|
||||
dispatch_async(globalLoggingQueue, ^{
|
||||
dispatch_async(loggerQueue, block);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
- (dispatch_queue_t)loggerQueue
|
||||
@@ -1071,15 +1064,4 @@ static char *dd_str_copy(const char *str)
|
||||
return NSStringFromClass([self class]);
|
||||
}
|
||||
|
||||
- (BOOL)isOnGlobalLoggingQueue
|
||||
{
|
||||
return (dispatch_get_specific(GlobalLoggingQueueIdentityKey) != NULL);
|
||||
}
|
||||
|
||||
- (BOOL)isOnInternalLoggerQueue
|
||||
{
|
||||
void *key = (__bridge void *)self;
|
||||
return (dispatch_get_specific(key) != NULL);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -125,6 +125,7 @@
|
||||
|
||||
@implementation DDTTYLogger
|
||||
|
||||
static BOOL isaTTY;
|
||||
static BOOL isaColorTTY;
|
||||
static BOOL isaColor256TTY;
|
||||
static BOOL isaXcodeColorTTY;
|
||||
@@ -769,6 +770,8 @@ static DDTTYLogger *sharedInstance;
|
||||
{
|
||||
initialized = YES;
|
||||
|
||||
isaTTY = isatty(STDERR_FILENO);
|
||||
|
||||
char *term = getenv("TERM");
|
||||
if (term)
|
||||
{
|
||||
@@ -819,42 +822,42 @@ static DDTTYLogger *sharedInstance;
|
||||
|
||||
if ((self = [super init]))
|
||||
{
|
||||
calendar = [NSCalendar autoupdatingCurrentCalendar];
|
||||
|
||||
calendarUnitFlags = 0;
|
||||
calendarUnitFlags |= NSYearCalendarUnit;
|
||||
calendarUnitFlags |= NSMonthCalendarUnit;
|
||||
calendarUnitFlags |= NSDayCalendarUnit;
|
||||
calendarUnitFlags |= NSHourCalendarUnit;
|
||||
calendarUnitFlags |= NSMinuteCalendarUnit;
|
||||
calendarUnitFlags |= NSSecondCalendarUnit;
|
||||
|
||||
// Initialze 'app' variable (char *)
|
||||
|
||||
appName = [[NSProcessInfo processInfo] processName];
|
||||
|
||||
appLen = [appName lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
|
||||
app = (char *)malloc(appLen + 1);
|
||||
if (app == NULL) return nil;
|
||||
|
||||
[appName getCString:app maxLength:(appLen+1) encoding:NSUTF8StringEncoding];
|
||||
|
||||
// Initialize 'pid' variable (char *)
|
||||
|
||||
processID = [NSString stringWithFormat:@"%i", (int)getpid()];
|
||||
|
||||
pidLen = [processID lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
|
||||
pid = (char *)malloc(pidLen + 1);
|
||||
if (pid == NULL) return nil;
|
||||
|
||||
BOOL processedID = [processID getCString:pid maxLength:(pidLen+1) encoding:NSUTF8StringEncoding];
|
||||
if (NO == processedID) return nil;
|
||||
|
||||
// Initialize color stuff
|
||||
|
||||
colorsEnabled = NO;
|
||||
colorProfilesArray = [[NSMutableArray alloc] initWithCapacity:8];
|
||||
colorProfilesDict = [[NSMutableDictionary alloc] initWithCapacity:8];
|
||||
if (isaTTY)
|
||||
{
|
||||
calendar = [NSCalendar autoupdatingCurrentCalendar];
|
||||
|
||||
calendarUnitFlags = 0;
|
||||
calendarUnitFlags |= NSYearCalendarUnit;
|
||||
calendarUnitFlags |= NSMonthCalendarUnit;
|
||||
calendarUnitFlags |= NSDayCalendarUnit;
|
||||
calendarUnitFlags |= NSHourCalendarUnit;
|
||||
calendarUnitFlags |= NSMinuteCalendarUnit;
|
||||
calendarUnitFlags |= NSSecondCalendarUnit;
|
||||
|
||||
// Initialze 'app' variable (char *)
|
||||
|
||||
appName = [[NSProcessInfo processInfo] processName];
|
||||
|
||||
appLen = [appName lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
|
||||
app = (char *)malloc(appLen + 1);
|
||||
|
||||
[appName getCString:app maxLength:(appLen+1) encoding:NSUTF8StringEncoding];
|
||||
|
||||
// Initialize 'pid' variable (char *)
|
||||
|
||||
processID = [NSString stringWithFormat:@"%i", (int)getpid()];
|
||||
|
||||
pidLen = [processID lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
|
||||
pid = (char *)malloc(pidLen + 1);
|
||||
|
||||
[processID getCString:pid maxLength:(pidLen+1) encoding:NSUTF8StringEncoding];
|
||||
|
||||
// Initialize color stuff
|
||||
|
||||
colorsEnabled = NO;
|
||||
colorProfilesArray = [[NSMutableArray alloc] initWithCapacity:8];
|
||||
colorProfilesDict = [[NSMutableDictionary alloc] initWithCapacity:8];
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -868,29 +871,28 @@ static DDTTYLogger *sharedInstance;
|
||||
- (BOOL)colorsEnabled
|
||||
{
|
||||
// The design of this method is taken from the DDAbstractLogger implementation.
|
||||
// For extensive documentation please refer to the DDAbstractLogger implementation.
|
||||
// For documentation please refer to the DDAbstractLogger implementation.
|
||||
|
||||
// Note: The internal implementation MUST access the colorsEnabled variable directly,
|
||||
// This method is designed explicitly for external access.
|
||||
//
|
||||
// Using "self." syntax to go through this method will cause immediate deadlock.
|
||||
// This is the intended result. Fix it by accessing the ivar directly.
|
||||
// Great strides have been take to ensure this is safe to do. Plus it's MUCH faster.
|
||||
|
||||
NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
|
||||
NSAssert(![self isOnInternalLoggerQueue], @"MUST access ivar directly, NOT via self.* syntax.");
|
||||
|
||||
dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
|
||||
|
||||
__block BOOL result;
|
||||
|
||||
dispatch_sync(globalLoggingQueue, ^{
|
||||
dispatch_sync(loggerQueue, ^{
|
||||
result = colorsEnabled;
|
||||
dispatch_queue_t currentQueue = dispatch_get_current_queue();
|
||||
if (currentQueue == loggerQueue)
|
||||
{
|
||||
return colorsEnabled;
|
||||
}
|
||||
else
|
||||
{
|
||||
dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
|
||||
NSAssert(currentQueue != globalLoggingQueue, @"Core architecture requirement failure");
|
||||
|
||||
__block BOOL result;
|
||||
|
||||
dispatch_sync(globalLoggingQueue, ^{
|
||||
dispatch_sync(loggerQueue, ^{
|
||||
result = colorsEnabled;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return result;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setColorsEnabled:(BOOL)newColorsEnabled
|
||||
@@ -904,24 +906,23 @@ static DDTTYLogger *sharedInstance;
|
||||
}
|
||||
}};
|
||||
|
||||
// The design of this method is taken from the DDAbstractLogger implementation.
|
||||
// For extensive documentation please refer to the DDAbstractLogger implementation.
|
||||
// The design of the setter logic below is taken from the DDAbstractLogger implementation.
|
||||
// For documentation please refer to the DDAbstractLogger implementation.
|
||||
|
||||
// Note: The internal implementation MUST access the colorsEnabled variable directly,
|
||||
// This method is designed explicitly for external access.
|
||||
//
|
||||
// Using "self." syntax to go through this method will cause immediate deadlock.
|
||||
// This is the intended result. Fix it by accessing the ivar directly.
|
||||
// Great strides have been take to ensure this is safe to do. Plus it's MUCH faster.
|
||||
|
||||
NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
|
||||
NSAssert(![self isOnInternalLoggerQueue], @"MUST access ivar directly, NOT via self.* syntax.");
|
||||
|
||||
dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
|
||||
|
||||
dispatch_async(globalLoggingQueue, ^{
|
||||
dispatch_async(loggerQueue, block);
|
||||
});
|
||||
dispatch_queue_t currentQueue = dispatch_get_current_queue();
|
||||
if (currentQueue == loggerQueue)
|
||||
{
|
||||
block();
|
||||
}
|
||||
else
|
||||
{
|
||||
dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
|
||||
NSAssert(currentQueue != globalLoggingQueue, @"Core architecture requirement failure");
|
||||
|
||||
dispatch_async(globalLoggingQueue, ^{
|
||||
dispatch_async(loggerQueue, block);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setForegroundColor:(OSColor *)txtColor backgroundColor:(OSColor *)bgColor forFlag:(int)mask
|
||||
@@ -961,14 +962,15 @@ static DDTTYLogger *sharedInstance;
|
||||
// The design of the setter logic below is taken from the DDAbstractLogger implementation.
|
||||
// For documentation please refer to the DDAbstractLogger implementation.
|
||||
|
||||
if ([self isOnInternalLoggerQueue])
|
||||
dispatch_queue_t currentQueue = dispatch_get_current_queue();
|
||||
if (currentQueue == loggerQueue)
|
||||
{
|
||||
block();
|
||||
}
|
||||
else
|
||||
{
|
||||
dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
|
||||
NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
|
||||
NSAssert(currentQueue != globalLoggingQueue, @"Core architecture requirement failure");
|
||||
|
||||
dispatch_async(globalLoggingQueue, ^{
|
||||
dispatch_async(loggerQueue, block);
|
||||
@@ -996,14 +998,15 @@ static DDTTYLogger *sharedInstance;
|
||||
// The design of the setter logic below is taken from the DDAbstractLogger implementation.
|
||||
// For documentation please refer to the DDAbstractLogger implementation.
|
||||
|
||||
if ([self isOnInternalLoggerQueue])
|
||||
dispatch_queue_t currentQueue = dispatch_get_current_queue();
|
||||
if (currentQueue == loggerQueue)
|
||||
{
|
||||
block();
|
||||
}
|
||||
else
|
||||
{
|
||||
dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
|
||||
NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
|
||||
NSAssert(currentQueue != globalLoggingQueue, @"Core architecture requirement failure");
|
||||
|
||||
dispatch_async(globalLoggingQueue, ^{
|
||||
dispatch_async(loggerQueue, block);
|
||||
@@ -1040,14 +1043,15 @@ static DDTTYLogger *sharedInstance;
|
||||
// The design of the setter logic below is taken from the DDAbstractLogger implementation.
|
||||
// For documentation please refer to the DDAbstractLogger implementation.
|
||||
|
||||
if ([self isOnInternalLoggerQueue])
|
||||
dispatch_queue_t currentQueue = dispatch_get_current_queue();
|
||||
if (currentQueue == loggerQueue)
|
||||
{
|
||||
block();
|
||||
}
|
||||
else
|
||||
{
|
||||
dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
|
||||
NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
|
||||
NSAssert(currentQueue != globalLoggingQueue, @"Core architecture requirement failure");
|
||||
|
||||
dispatch_async(globalLoggingQueue, ^{
|
||||
dispatch_async(loggerQueue, block);
|
||||
@@ -1067,14 +1071,15 @@ static DDTTYLogger *sharedInstance;
|
||||
// The design of the setter logic below is taken from the DDAbstractLogger implementation.
|
||||
// For documentation please refer to the DDAbstractLogger implementation.
|
||||
|
||||
if ([self isOnInternalLoggerQueue])
|
||||
dispatch_queue_t currentQueue = dispatch_get_current_queue();
|
||||
if (currentQueue == loggerQueue)
|
||||
{
|
||||
block();
|
||||
}
|
||||
else
|
||||
{
|
||||
dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
|
||||
NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
|
||||
NSAssert(currentQueue != globalLoggingQueue, @"Core architecture requirement failure");
|
||||
|
||||
dispatch_async(globalLoggingQueue, ^{
|
||||
dispatch_async(loggerQueue, block);
|
||||
@@ -1092,14 +1097,15 @@ static DDTTYLogger *sharedInstance;
|
||||
// The design of the setter logic below is taken from the DDAbstractLogger implementation.
|
||||
// For documentation please refer to the DDAbstractLogger implementation.
|
||||
|
||||
if ([self isOnInternalLoggerQueue])
|
||||
dispatch_queue_t currentQueue = dispatch_get_current_queue();
|
||||
if (currentQueue == loggerQueue)
|
||||
{
|
||||
block();
|
||||
}
|
||||
else
|
||||
{
|
||||
dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
|
||||
NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
|
||||
NSAssert(currentQueue != globalLoggingQueue, @"Core architecture requirement failure");
|
||||
|
||||
dispatch_async(globalLoggingQueue, ^{
|
||||
dispatch_async(loggerQueue, block);
|
||||
@@ -1117,14 +1123,15 @@ static DDTTYLogger *sharedInstance;
|
||||
// The design of the setter logic below is taken from the DDAbstractLogger implementation.
|
||||
// For documentation please refer to the DDAbstractLogger implementation.
|
||||
|
||||
if ([self isOnInternalLoggerQueue])
|
||||
dispatch_queue_t currentQueue = dispatch_get_current_queue();
|
||||
if (currentQueue == loggerQueue)
|
||||
{
|
||||
block();
|
||||
}
|
||||
else
|
||||
{
|
||||
dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
|
||||
NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
|
||||
NSAssert(currentQueue != globalLoggingQueue, @"Core architecture requirement failure");
|
||||
|
||||
dispatch_async(globalLoggingQueue, ^{
|
||||
dispatch_async(loggerQueue, block);
|
||||
@@ -1143,14 +1150,15 @@ static DDTTYLogger *sharedInstance;
|
||||
// The design of the setter logic below is taken from the DDAbstractLogger implementation.
|
||||
// For documentation please refer to the DDAbstractLogger implementation.
|
||||
|
||||
if ([self isOnInternalLoggerQueue])
|
||||
dispatch_queue_t currentQueue = dispatch_get_current_queue();
|
||||
if (currentQueue == loggerQueue)
|
||||
{
|
||||
block();
|
||||
}
|
||||
else
|
||||
{
|
||||
dispatch_queue_t globalLoggingQueue = [DDLog loggingQueue];
|
||||
NSAssert(![self isOnGlobalLoggingQueue], @"Core architecture requirement failure");
|
||||
NSAssert(currentQueue != globalLoggingQueue, @"Core architecture requirement failure");
|
||||
|
||||
dispatch_async(globalLoggingQueue, ^{
|
||||
dispatch_async(loggerQueue, block);
|
||||
@@ -1160,6 +1168,8 @@ static DDTTYLogger *sharedInstance;
|
||||
|
||||
- (void)logMessage:(DDLogMessage *)logMessage
|
||||
{
|
||||
if (!isaTTY) return;
|
||||
|
||||
NSString *logMsg = logMessage->logMsg;
|
||||
BOOL isFormatted = NO;
|
||||
|
||||
@@ -1204,14 +1214,8 @@ static DDTTYLogger *sharedInstance;
|
||||
|
||||
char msgStack[useStack ? (msgLen + 1) : 1]; // Analyzer doesn't like zero-size array, hence the 1
|
||||
char *msg = useStack ? msgStack : (char *)malloc(msgLen + 1);
|
||||
if (msg == NULL) return;
|
||||
|
||||
BOOL logMsgEnc = [logMsg getCString:msg maxLength:(msgLen + 1) encoding:NSUTF8StringEncoding];
|
||||
if (!logMsgEnc)
|
||||
{
|
||||
if (!useStack && msg != NULL) free(msg);
|
||||
return;
|
||||
}
|
||||
[logMsg getCString:msg maxLength:(msgLen + 1) encoding:NSUTF8StringEncoding];
|
||||
|
||||
// Write the log message to STDERR
|
||||
|
||||
@@ -1219,38 +1223,32 @@ static DDTTYLogger *sharedInstance;
|
||||
{
|
||||
// The log message has already been formatted.
|
||||
|
||||
struct iovec v[5];
|
||||
struct iovec v[4];
|
||||
|
||||
if (colorProfile)
|
||||
{
|
||||
v[0].iov_base = colorProfile->fgCode;
|
||||
v[0].iov_len = colorProfile->fgCodeLen;
|
||||
|
||||
v[1].iov_base = colorProfile->bgCode;
|
||||
v[1].iov_len = colorProfile->bgCodeLen;
|
||||
|
||||
v[4].iov_base = colorProfile->resetCode;
|
||||
v[4].iov_len = colorProfile->resetCodeLen;
|
||||
|
||||
v[3].iov_base = colorProfile->resetCode;
|
||||
v[3].iov_len = colorProfile->resetCodeLen;
|
||||
}
|
||||
else
|
||||
{
|
||||
v[0].iov_base = "";
|
||||
v[0].iov_len = 0;
|
||||
|
||||
v[1].iov_base = "";
|
||||
v[1].iov_len = 0;
|
||||
|
||||
v[4].iov_base = "";
|
||||
v[4].iov_len = 0;
|
||||
v[3].iov_base = "";
|
||||
v[3].iov_len = 0;
|
||||
}
|
||||
|
||||
v[2].iov_base = (char *)msg;
|
||||
v[2].iov_len = msgLen;
|
||||
v[1].iov_base = (char *)msg;
|
||||
v[1].iov_len = msgLen;
|
||||
|
||||
v[3].iov_base = "\n";
|
||||
v[3].iov_len = (msg[msgLen] == '\n') ? 0 : 1;
|
||||
v[2].iov_base = "\n";
|
||||
v[2].iov_len = (msg[msgLen] == '\n') ? 0 : 1;
|
||||
|
||||
writev(STDERR_FILENO, v, 5);
|
||||
writev(STDERR_FILENO, v, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1292,62 +1290,56 @@ static DDTTYLogger *sharedInstance;
|
||||
|
||||
// Here is our format: "%s %s[%i:%s] %s", timestamp, appName, processID, threadID, logMsg
|
||||
|
||||
struct iovec v[13];
|
||||
struct iovec v[12];
|
||||
|
||||
if (colorProfile)
|
||||
{
|
||||
v[0].iov_base = colorProfile->fgCode;
|
||||
v[0].iov_len = colorProfile->fgCodeLen;
|
||||
|
||||
v[1].iov_base = colorProfile->bgCode;
|
||||
v[1].iov_len = colorProfile->bgCodeLen;
|
||||
|
||||
v[12].iov_base = colorProfile->resetCode;
|
||||
v[12].iov_len = colorProfile->resetCodeLen;
|
||||
|
||||
v[11].iov_base = colorProfile->resetCode;
|
||||
v[11].iov_len = colorProfile->resetCodeLen;
|
||||
}
|
||||
else
|
||||
{
|
||||
v[0].iov_base = "";
|
||||
v[0].iov_len = 0;
|
||||
|
||||
v[1].iov_base = "";
|
||||
v[1].iov_len = 0;
|
||||
|
||||
v[12].iov_base = "";
|
||||
v[12].iov_len = 0;
|
||||
|
||||
v[11].iov_base = "";
|
||||
v[11].iov_len = 0;
|
||||
}
|
||||
|
||||
v[2].iov_base = ts;
|
||||
v[2].iov_len = tsLen;
|
||||
v[1].iov_base = ts;
|
||||
v[1].iov_len = tsLen;
|
||||
|
||||
v[3].iov_base = " ";
|
||||
v[3].iov_len = 1;
|
||||
v[2].iov_base = " ";
|
||||
v[2].iov_len = 1;
|
||||
|
||||
v[4].iov_base = app;
|
||||
v[4].iov_len = appLen;
|
||||
v[3].iov_base = app;
|
||||
v[3].iov_len = appLen;
|
||||
|
||||
v[5].iov_base = "[";
|
||||
v[5].iov_len = 1;
|
||||
v[4].iov_base = "[";
|
||||
v[4].iov_len = 1;
|
||||
|
||||
v[6].iov_base = pid;
|
||||
v[6].iov_len = pidLen;
|
||||
v[5].iov_base = pid;
|
||||
v[5].iov_len = pidLen;
|
||||
|
||||
v[7].iov_base = ":";
|
||||
v[7].iov_len = 1;
|
||||
v[6].iov_base = ":";
|
||||
v[6].iov_len = 1;
|
||||
|
||||
v[8].iov_base = tid;
|
||||
v[8].iov_len = MIN((size_t)8, tidLen); // snprintf doesn't return what you might think
|
||||
v[7].iov_base = tid;
|
||||
v[7].iov_len = MIN((size_t)8, tidLen); // snprintf doesn't return what you might think
|
||||
|
||||
v[9].iov_base = "] ";
|
||||
v[9].iov_len = 2;
|
||||
v[8].iov_base = "] ";
|
||||
v[8].iov_len = 2;
|
||||
|
||||
v[10].iov_base = (char *)msg;
|
||||
v[10].iov_len = msgLen;
|
||||
v[9].iov_base = (char *)msg;
|
||||
v[9].iov_len = msgLen;
|
||||
|
||||
v[11].iov_base = "\n";
|
||||
v[11].iov_len = (msg[msgLen] == '\n') ? 0 : 1;
|
||||
v[10].iov_base = "\n";
|
||||
v[10].iov_len = (msg[msgLen] == '\n') ? 0 : 1;
|
||||
|
||||
writev(STDERR_FILENO, v, 13);
|
||||
writev(STDERR_FILENO, v, 12);
|
||||
}
|
||||
|
||||
if (!useStack) {
|
||||
@@ -1405,9 +1397,8 @@ static DDTTYLogger *sharedInstance;
|
||||
NSUInteger len1 = [escapeSeq lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
|
||||
NSUInteger len2 = [fgCodeRaw lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
|
||||
|
||||
BOOL escapeSeqEnc = [escapeSeq getCString:(fgCode) maxLength:(len1+1) encoding:NSUTF8StringEncoding];
|
||||
BOOL fgCodeRawEsc = [fgCodeRaw getCString:(fgCode+len1) maxLength:(len2+1) encoding:NSUTF8StringEncoding];
|
||||
if (!escapeSeqEnc || !fgCodeRawEsc) return nil;
|
||||
[escapeSeq getCString:(fgCode) maxLength:(len1+1) encoding:NSUTF8StringEncoding];
|
||||
[fgCodeRaw getCString:(fgCode+len1) maxLength:(len2+1) encoding:NSUTF8StringEncoding];
|
||||
|
||||
fgCodeLen = len1+len2;
|
||||
}
|
||||
@@ -1440,9 +1431,8 @@ static DDTTYLogger *sharedInstance;
|
||||
NSUInteger len1 = [escapeSeq lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
|
||||
NSUInteger len2 = [bgCodeRaw lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
|
||||
|
||||
BOOL escapeSeqEnc = [escapeSeq getCString:(bgCode) maxLength:(len1+1) encoding:NSUTF8StringEncoding];
|
||||
BOOL bgCodeRawEsc = [bgCodeRaw getCString:(bgCode+len1) maxLength:(len2+1) encoding:NSUTF8StringEncoding];
|
||||
if (!escapeSeqEnc || !bgCodeRawEsc) return nil;
|
||||
[escapeSeq getCString:(bgCode) maxLength:(len1+1) encoding:NSUTF8StringEncoding];
|
||||
[bgCodeRaw getCString:(bgCode+len1) maxLength:(len2+1) encoding:NSUTF8StringEncoding];
|
||||
|
||||
bgCodeLen = len1+len2;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user