From d723c7306aaaefbaf4b4de8320c15cd40e40e81b Mon Sep 17 00:00:00 2001 From: Aparajita Fishman Date: Fri, 3 May 2013 12:12:15 -0400 Subject: [PATCH] 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. --- .../XcodeCapp/Lumberjack/DDASLLogger.m | 10 +- Tools/XcodeCapp/XcodeCapp/Lumberjack/DDLog.h | 8 +- Tools/XcodeCapp/XcodeCapp/Lumberjack/DDLog.m | 202 ++++++------ .../XcodeCapp/Lumberjack/DDTTYLogger.m | 294 +++++++++--------- 4 files changed, 241 insertions(+), 273 deletions(-) diff --git a/Tools/XcodeCapp/XcodeCapp/Lumberjack/DDASLLogger.m b/Tools/XcodeCapp/XcodeCapp/Lumberjack/DDASLLogger.m index 0c35f2fcf..4ec1e7cbf 100755 --- a/Tools/XcodeCapp/XcodeCapp/Lumberjack/DDASLLogger.m +++ b/Tools/XcodeCapp/XcodeCapp/Lumberjack/DDASLLogger.m @@ -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); diff --git a/Tools/XcodeCapp/XcodeCapp/Lumberjack/DDLog.h b/Tools/XcodeCapp/XcodeCapp/Lumberjack/DDLog.h index 5da184938..57c2f096c 100755 --- a/Tools/XcodeCapp/XcodeCapp/Lumberjack/DDLog.h +++ b/Tools/XcodeCapp/XcodeCapp/Lumberjack/DDLog.h @@ -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 )logFormatter; - (void)setLogFormatter:(id )formatter; -// For thread-safety assertions -- (BOOL)isOnGlobalLoggingQueue; -- (BOOL)isOnInternalLoggerQueue; - @end diff --git a/Tools/XcodeCapp/XcodeCapp/Lumberjack/DDLog.m b/Tools/XcodeCapp/XcodeCapp/Lumberjack/DDLog.m index 1cc0895f1..7d75d8121 100755 --- a/Tools/XcodeCapp/XcodeCapp/Lumberjack/DDLog.m +++ b/Tools/XcodeCapp/XcodeCapp/Lumberjack/DDLog.m @@ -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 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 result; + + dispatch_sync(globalLoggingQueue, ^{ + dispatch_sync(loggerQueue, ^{ + result = formatter; + }); }); - }); - - return result; + + return result; + } } - (void)setLogFormatter:(id )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 diff --git a/Tools/XcodeCapp/XcodeCapp/Lumberjack/DDTTYLogger.m b/Tools/XcodeCapp/XcodeCapp/Lumberjack/DDTTYLogger.m index 8b4c097d4..3157d84e9 100755 --- a/Tools/XcodeCapp/XcodeCapp/Lumberjack/DDTTYLogger.m +++ b/Tools/XcodeCapp/XcodeCapp/Lumberjack/DDTTYLogger.m @@ -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; }