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:
Aparajita Fishman
2013-05-03 12:12:15 -04:00
parent 9dd642395f
commit d723c7306a
4 changed files with 241 additions and 273 deletions
@@ -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);
+2 -6
View File
@@ -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
+92 -110
View File
@@ -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
+142 -152
View File
@@ -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;
}