Vuo 2.4.4
Loading...
Searching...
No Matches
VuoLog.cc
Go to the documentation of this file.
1
11#include <asl.h>
12#include <assert.h>
13#include <cxxabi.h>
14#include <dlfcn.h>
15#include <execinfo.h>
16#include <libgen.h>
17#include <mach/mach_time.h>
18#include <mach-o/dyld.h>
19#include <math.h>
20#include <objc/objc-runtime.h>
21#include <os/log.h>
22#include <regex.h>
23#include <stdbool.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <sys/sysctl.h>
27#include <sys/time.h>
28#include <sys/types.h>
29#include <unistd.h>
30#include <xlocale.h>
31
32#include <CoreFoundation/CoreFoundation.h>
33
34#include <CoreGraphics/CoreGraphics.h>
35#include <CoreText/CoreText.h>
36
37#include "VuoLog.h"
38#include "VuoHeap.h"
39#include "VuoStringUtilities.hh"
40
42static std::terminate_handler nextTerminateHandler = nullptr;
43
44dispatch_queue_t VuoLog_utf8LocaleQueue = NULL;
45locale_t VuoLog_utf8Locale = NULL;
46
51extern "C" [[noreturn]] void VuoTerminateHandler()
52{
53 if (auto ep = std::current_exception())
54 try
55 {
56 std::rethrow_exception(ep);
57 }
58 catch (std::exception const &e)
59 {
60 int status;
61 const char *typeName = typeid(e).name();
62 char *unmangled = abi::__cxa_demangle(typeName, 0, 0, &status);
63 if (status == 0)
64 typeName = unmangled;
65
66 VUserLog("Terminating due to uncaught %s: \"%s\"", typeName, e.what());
67 }
68 catch (...)
69 {
70 VUserLog("Terminating due to uncaught exception of unknown type");
71 }
72 else
73 // Could still be due to an exception:
74 // https://b33p.net/kosada/node/16404
75 VUserLog("Terminating because std::terminate was called (no exception data available)");
76
78 abort();
79}
80
84double VuoLogGetTime(void)
85{
86 static mach_timebase_info_data_t info = {0,0};
87 if (info.denom == 0)
88 {
89 kern_return_t ret = mach_timebase_info(&info);
90 if (ret != KERN_SUCCESS)
91 {
92 VUserLog("Failed to get mach timebase: %d", ret);
93 // Default to 1/1, which is correct on at least some machines.
94 info.numer = 1;
95 info.denom = 1;
96 }
97 }
98
99 return (double)mach_absolute_time() * info.numer / (info.denom * NSEC_PER_SEC);
100}
101
103
104const int VuoLogHistoryItems = 20;
106dispatch_queue_t VuoLogHistoryQueue;
107
108#ifdef VUO_PROFILE
109#include <map>
110#include <string>
112typedef struct
113{
114 double total;
115 double min;
116 double max;
117 uint64_t count;
118} VuoLogProfileEntry;
119typedef std::map<std::string, VuoLogProfileEntry> VuoLogProfileType;
120static VuoLogProfileType *VuoLogProfile;
121static dispatch_queue_t VuoLogProfileQueue;
122#endif
123
124static pthread_t VuoLog_mainThread = nullptr;
125static const char *VuoLog_executableName = nullptr;
126
130static void __attribute__((constructor)) VuoLog_init(void)
131{
132 // Store the time at which this module was loaded, for use by @ref VuoLogGetElapsedTime().
134
135 nextTerminateHandler = std::set_terminate(&VuoTerminateHandler);
136
137 VuoLog_mainThread = pthread_self();
138
139 char executablePath[PATH_MAX + 1];
140 uint32_t size = sizeof(executablePath);
141 if (!_NSGetExecutablePath(executablePath, &size))
142 VuoLog_executableName = basename_r(executablePath, (char *)malloc(size));
143
144 VuoLog_utf8LocaleQueue = dispatch_queue_create("org.vuo.VuoLog.locale.utf8", NULL);
145 VuoLog_utf8Locale = newlocale(LC_ALL_MASK, "en_US.UTF-8", NULL);
146
147#ifdef VUO_PROFILE
148 VuoLogProfileQueue = dispatch_queue_create("VuoLogProfile", NULL);
149 VuoLogProfile = new VuoLogProfileType;
150#endif
151}
152
153#if defined(VUO_PROFILE) || defined(DOXYGEN)
157void VuoLog_recordTime(const char *name, double time)
158{
159 dispatch_sync(VuoLogProfileQueue, ^{
160 VuoLogProfileType::iterator i = VuoLogProfile->find(name);
161 if (i != VuoLogProfile->end())
162 {
163 i->second.total += time;
164 if (time < i->second.min)
165 i->second.min = time;
166 if (time > i->second.max)
167 i->second.max = time;
168 ++i->second.count;
169 }
170 else
171 (*VuoLogProfile)[name] = (VuoLogProfileEntry){time, time, time, 1};
172 });
173}
174
178extern "C" void __attribute__((destructor)) VuoLog_dumpProfile(void)
179{
180 dispatch_sync(VuoLogProfileQueue, ^{
181 double totalRuntime = VuoLogGetElapsedTime();
182 for (VuoLogProfileType::iterator i = VuoLogProfile->begin(); i != VuoLogProfile->end(); ++i)
183 fprintf(stderr, "%30s %12.9f s (%7.4f%%) (min %12.9f, max %12.9f, avg %12.9f, count %lld)\n",
184 i->first.c_str(),
185 i->second.total,
186 i->second.total * 100. / totalRuntime,
187 i->second.min,
188 i->second.max,
189 i->second.total / i->second.count,
190 i->second.count);
191 });
192}
193#endif
194
199{
201}
202
204#define VuoCrashReport_alignment __attribute__((aligned(8)))
205
213typedef struct {
214 unsigned int version VuoCrashReport_alignment;
216 char *signature VuoCrashReport_alignment;
217 char *backtrace VuoCrashReport_alignment;
219 void *reserved VuoCrashReport_alignment;
220 void *reserved2 VuoCrashReport_alignment;
222
224VuoCrashReport_infoType VuoCrashReport __attribute__((section("__DATA,__crash_info"))) = { 4, NULL, NULL, NULL, NULL, NULL, NULL };
225
226void VuoLog_statusF(const char *moduleName, const char *file, const unsigned int linenumber, const char *function, const char *format, ...)
227{
228 static dispatch_once_t statusInitialized = 0;
229 static dispatch_queue_t statusQueue;
230 dispatch_once(&statusInitialized, ^{
231 statusQueue = dispatch_queue_create("VuoLogStatus", NULL);
232 });
233
234 char *message = nullptr;
235 if (format)
236 {
237 va_list args;
238 va_start(args, format);
239 vasprintf(&message, format, args);
240 va_end(args);
241 }
242
243 dispatch_sync(statusQueue, ^{
244 if (VuoCrashReport.signature)
245 free(VuoCrashReport.signature);
246
247 if (format)
248 VuoCrashReport.signature = message;
249 else
250 VuoCrashReport.signature = nullptr;
251 });
252}
253
258{
259 long majorVersion;
260 long minorVersion;
261 long patchVersion;
262};
263
268{
269 Class NSProcessInfoClass = objc_getClass("NSProcessInfo");
270 id processInfo = ((id(*)(id, SEL))objc_msgSend)((id)NSProcessInfoClass, sel_getUid("processInfo"));
271 typedef NSOperatingSystemVersion (*operatingSystemVersionType)(id receiver, SEL selector);
272#if __x86_64__
273 operatingSystemVersionType operatingSystemVersionFunc = (operatingSystemVersionType)objc_msgSend_stret;
274#elif __arm64__
275 operatingSystemVersionType operatingSystemVersionFunc = (operatingSystemVersionType)objc_msgSend;
276#endif
277 NSOperatingSystemVersion operatingSystemVersion = operatingSystemVersionFunc(processInfo, sel_getUid("operatingSystemVersion"));
278 return operatingSystemVersion;
279}
280
282
286static void VuoLog_dylibLoaded(const struct mach_header *mh32, intptr_t vmaddr_slide)
287{
289 return;
290
291 const struct mach_header_64 *mh = reinterpret_cast<const mach_header_64 *>(mh32);
292
293 // Ignore system libraries.
294 if (mh->flags & MH_DYLIB_IN_CACHE)
295 return;
296
297 // Get the file path of the current dylib.
298 Dl_info info{"", nullptr, "", nullptr};
299 dladdr((void *)vmaddr_slide, &info);
300
301 // Check whether it's the dylib we're looking for.
302 if (strstr(info.dli_fname, "/DVTInstrumentsFoundation.framework/"))
304}
305
311{
312 // Detect LLDB.
313 {
314 // Based on https://developer.apple.com/library/archive/qa/qa1361/_index.html
315 int mib[4];
316 mib[0] = CTL_KERN;
317 mib[1] = KERN_PROC;
318 mib[2] = KERN_PROC_PID;
319 mib[3] = getpid();
320
321 struct kinfo_proc info;
322 info.kp_proc.p_flag = 0;
323 size_t size = sizeof(info);
324 if (sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) == 0
325 && info.kp_proc.p_flag & P_TRACED)
326 return true;
327 }
328
329 // Detect Instruments.
330 {
331 static once_flag once;
332 call_once(once, []() {
333 _dyld_register_func_for_add_image(VuoLog_dylibLoaded);
334 });
336 return true;
337 }
338
339 return false;
340}
341
342extern struct mach_header __dso_handle;
343
344void VuoLog(const char *moduleName, const char *file, const unsigned int linenumber, const char *function, const char *format, ...)
345{
346 if (!VuoHeap_isPointerReadable(moduleName))
347 {
348 fprintf(stderr, "VuoLog() error: Invalid 'moduleName' argument (%p). You may need to rebuild the module calling VuoLog().\n", moduleName);
350 return;
351 }
352 if (!VuoHeap_isPointerReadable(file))
353 {
354 fprintf(stderr, "VuoLog() error: Invalid 'file' argument (%p). You may need to rebuild the module calling VuoLog().\n", file);
356 return;
357 }
358 if (!VuoHeap_isPointerReadable(function))
359 {
360 fprintf(stderr, "VuoLog() error: Invalid 'function' argument (%p). You may need to rebuild the module calling VuoLog().\n", function);
362 return;
363 }
364 if (!VuoHeap_isPointerReadable(format))
365 {
366 fprintf(stderr, "VuoLog() error: Invalid 'format' argument (%p). You may need to rebuild the module calling VuoLog().\n", format);
368 return;
369 }
370
371 va_list args;
372
373 va_start(args, format);
374 int size = vsnprintf(NULL, 0, format, args);
375 va_end(args);
376
377 char *formattedString = (char *)malloc(size+1);
378 va_start(args, format);
379 vsnprintf(formattedString, size+1, format, args);
380 va_end(args);
381
382 char *formattedFunction = NULL;
383
384 // This may be a mangled function name of the form `__6+[f g]_block_invoke`.
385 // Trim the prefix and suffix, since the line number is sufficient to locate the code within the function+block.
386 if (function && function[0] == '_' && function[1] == '_')
387 {
388 int actualFunctionLength = atoi(function + 2);
389 if (actualFunctionLength)
390 formattedFunction = strndup(function + 3 + (int)log10(actualFunctionLength), actualFunctionLength);
391 else
392 formattedFunction = strndup(function + 2, strrchr(function + 2, '_') - (function + 2));
393
394 // We may now be left with a C++-mangled symbol followed by `_block`,
395 // such as `_ZN9VuoRunner18replaceCompositionESsSsSs_block`.
396 // Extract just the method name (the last length-specified section).
397 if (strncmp(formattedFunction, "_ZN", 3) == 0)
398 {
399 int pos = 3;
400 int len, priorLen = 0;
401 while ((len = atoi(formattedFunction + pos)))
402 {
403 pos += 1 + (int)log10(len) + len;
404 priorLen = len;
405 }
406 char *f2 = strndup(formattedFunction + pos - priorLen, priorLen);
407 free(formattedFunction);
408 formattedFunction = f2;
409 }
410 }
411 else
412 {
413 const char *blockInvokePos = strstr(function, "_block_invoke");
414 if (blockInvokePos)
415 formattedFunction = strndup(function, blockInvokePos - function);
416 }
417
418 // Add a trailing `()`, unless it's an Objective-C method.
419 if (function)
420 {
421 const char *f = formattedFunction ? formattedFunction : function;
422 size_t fLen = strlen(f);
423 if (f[fLen - 1] != ']')
424 {
425 size_t mallocSize = fLen + 2 + 1;
426 char *f2 = (char *)malloc(mallocSize);
427 strlcpy(f2, f, mallocSize);
428 strlcat(f2, "()", mallocSize);
429 if (formattedFunction)
430 free(formattedFunction);
431 formattedFunction = f2;
432 }
433 }
434
435 const char *formattedFile = file;
436
437 if (!VuoHeap_isPointerReadable(formattedFile))
438 formattedFile = "(unknown)";
439
440 // Trim the path, if present.
441 if (const char *lastSlash = strrchr(formattedFile, '/'))
442 formattedFile = lastSlash + 1;
443
444 double time = VuoLogGetElapsedTime();
445
446 // If it's been a while since the last log, add a separator.
447 static double priorTime = 0;
448 const char *separator = "";
449 if (priorTime > 0 && time - priorTime > 0.5)
450 separator = "\n";
451 priorTime = time;
452
453 // Decide on a name for the thread emitting the log message.
454 pthread_t thread = pthread_self();
455 char threadName[256];
456 if (pthread_equal(thread, VuoLog_mainThread))
457 strcpy(threadName, "main");
458 else
459 {
460 bzero(threadName, 256);
461 int ret = pthread_getname_np(thread, threadName, 256);
462 if (!(ret == 0 && strlen(threadName)))
463 snprintf(threadName, 256, "%llx", (uint64_t)thread);
464 }
465
466 // Use a bright color for the main text.
467 const char *mainColor = "\033[97m";
468 // Use a medium color for the metadata.
469 const char *metadataColor = "\033[38;5;249m";
470 // Use a darker color for separators.
471 const char *separatorColor = "\033[90m";
472 // Try to give each process a unique color, to distinguish the host and the running composition(s).
473 // ANSI-256's 6x6x6 color cube begins at index 16 and spans 216 indices.
474 // Skip the first 72 indices, which are darker (illegible against a black terminal background).
475 int pidColor = getpid() % 144 + 88;
476 // Color the main thread the same as the process; choose a unique color for each other thread.
477 int threadColor = pthread_equal(thread, VuoLog_mainThread)
478 ? pidColor
479 : ((uint64_t)thread) % 144 + 88;
480
481 fprintf(stderr, "%s%s[%s%8.3fs%s] %s%12.12s%s:%s%-12.12s %s[\033[38;5;%dm%5d%s:\033[38;5;%dm%-8.8s%s] %s%20.20s%s:%s%-4u %32.32s %s%s\033[0m\n",
482 separator,
483 separatorColor,
484 metadataColor,
485 time,
486 separatorColor,
487 metadataColor,
489 separatorColor,
490 metadataColor,
491 moduleName ? moduleName : "Vuo",
492 separatorColor,
493 pidColor,
494 getpid(),
495 separatorColor,
496 threadColor,
497 threadName,
498 separatorColor,
499 metadataColor,
500 formattedFile,
501 separatorColor,
502 metadataColor,
503 linenumber,
504 formattedFunction ? formattedFunction : function,
505 mainColor,
506 formattedString);
507
508
509 // Also send it to the macOS Console.
510 {
511 // Can't just call this directly because it relies on Apple-specific compiler extensions that aren't available in Clang 3.2.
512 // os_log(OS_LOG_DEFAULT, "...", ...);
513
514 typedef void (*vuoMacOsLogInternalType)(void *dso, void *log, uint8_t type, const char *message, ...);
515 typedef void (*vuoMacOsLogImplType)(void *dso, void *log, uint8_t type, const char *format, uint8_t *buf, uint32_t size);
516 static vuoMacOsLogInternalType vuoMacOsLogInternal = NULL;
517 static vuoMacOsLogImplType vuoMacOsLogImpl = NULL;
518 static dispatch_once_t once = 0;
519 static bool debuggerAttached = false;
520 dispatch_once(&once, ^{
521 debuggerAttached = VuoLog_isDebuggerAttached();
522 NSOperatingSystemVersion operatingSystemVersion = VuoLog_getOSVersion();
523 if (operatingSystemVersion.majorVersion == 10 && operatingSystemVersion.minorVersion == 12)
524 // _os_log_impl doesn't work on macOS 10.12.
525 vuoMacOsLogInternal = (vuoMacOsLogInternalType)dlsym(RTLD_SELF, "_os_log_internal");
526 else if ((operatingSystemVersion.majorVersion == 10 && operatingSystemVersion.minorVersion > 12)
527 || operatingSystemVersion.majorVersion > 10)
528 // _os_log_internal doesn't work on macOS 10.13+.
529 vuoMacOsLogImpl = (vuoMacOsLogImplType)dlsym(RTLD_SELF, "_os_log_impl");
530 });
531
532 if (!debuggerAttached)
533 {
534 void *log = os_log_create("org.vuo", formattedFile);
535
536 if (vuoMacOsLogInternal)
537 vuoMacOsLogInternal(&__dso_handle, log, 0 /*OS_LOG_TYPE_DEFAULT*/, "%{public}41s:%-4u %{public}s", formattedFunction ? formattedFunction : function, linenumber, formattedString);
538 else if (vuoMacOsLogImpl)
539 {
540 char *formattedForOsLog;
541 asprintf(&formattedForOsLog, "%41s:%-4u %s", formattedFunction ? formattedFunction : function, linenumber, formattedString);
542
543 // https://reviews.llvm.org/rC284990#C2197511NL2613
544 uint8_t logFormatDescriptor[12] = {
545 2, // "summary" = HasNonScalarItems (a C string)
546 1, // "numArgs" = one C string
547 34, // "argDescriptor" = 2 (IsPublic) + 2 (StringKind) << 4
548 8, // "argSize" = one C string (a 64-bit pointer)
549 };
550 // …followed by the pointer itself.
551 memcpy(logFormatDescriptor + 4, &formattedForOsLog, 8);
552
553 vuoMacOsLogImpl(&__dso_handle, log, 0 /*OS_LOG_TYPE_DEFAULT*/, "%{public}s", logFormatDescriptor, sizeof(logFormatDescriptor));
554
555 free(formattedForOsLog);
556 }
557
558 os_release(log);
559 }
560 }
561
562
563 static dispatch_once_t historyInitialized = 0;
564 dispatch_once(&historyInitialized, ^{
565 for (int i = 0; i < VuoLogHistoryItems; ++i)
566 VuoLogHistory[i] = NULL;
567 VuoLogHistoryQueue = dispatch_queue_create("VuoLogHistory", NULL);
568 });
569
570 dispatch_sync(VuoLogHistoryQueue, ^{
571 // Keep the most recent messages in VuoLogHistory.
572 {
573 char *formattedPrefixedString;
574 asprintf(&formattedPrefixedString, "t=%8.4fs %27.27s:%-4u %41.41s %s", time, formattedFile, linenumber, formattedFunction ? formattedFunction : function, formattedString);
575 free(formattedString);
576 if (formattedFunction)
577 free(formattedFunction);
578
579 // Find the first open history slot.
580 int i;
581 for (i = 0; i < VuoLogHistoryItems; ++i)
582 if (!VuoLogHistory[i])
583 break;
584
585 if (i >= VuoLogHistoryItems)
586 {
587 // No open slots; expire 1 and rotate the rest.
588 free(VuoLogHistory[0]);
589 for (int i = 0; i < VuoLogHistoryItems-1; ++i)
591 i = VuoLogHistoryItems - 1;
592 }
593
594 VuoLogHistory[i] = formattedPrefixedString;
595 }
596
597 // Combine VuoLogHistory into a single string for the crash report.
598 {
599 if (VuoCrashReport.backtrace)
600 free(VuoCrashReport.backtrace);
601
602 long size = 0;
603 for (int i = 0; i < VuoLogHistoryItems; ++i)
604 if (VuoLogHistory[i])
605 size += strlen(VuoLogHistory[i]) + 1 /* \n */;
606 size += 1 /* null terminator */;
607
608 char *message = (char *)malloc(size);
609 strlcpy(message, VuoLogHistory[0], size);
610 for (int i = 1; i < VuoLogHistoryItems; ++i)
611 if (VuoLogHistory[i])
612 {
613 strlcat(message, "\n", size);
614 strlcat(message, VuoLogHistory[i], size);
615 }
616
617 VuoCrashReport.backtrace = message;
618 }
619 });
620}
621
631{
632 static dispatch_once_t checked = 0;
633 static bool debug = false;
634 dispatch_once(&checked, ^{
635 debug = CFPreferencesGetAppBooleanValue(CFSTR("debug"), CFSTR("org.vuo.Editor"), NULL);
636 });
637 return debug;
638}
639
644{
645 vector<string> backtrace = VuoLog_getBacktrace();
646
647 // Skip the VuoLog_backtrace() function.
648 backtrace.erase(backtrace.begin());
649
650 int i = 1;
651 for (auto line : backtrace)
652 fprintf(stderr, "%3d %s\n", i++, line.c_str());
653}
654
660void VuoLog_replaceString(char *wholeString, const char *substringToRemove, const char *replacement)
661{
662 dispatch_sync(VuoLog_utf8LocaleQueue, ^{
663 size_t replacementLen = strlen(replacement);
664 regex_t regex;
665 regcomp_l(&regex, substringToRemove, REG_EXTENDED, VuoLog_utf8Locale);
666 size_t nmatch = 1;
667 regmatch_t pmatch[nmatch];
668 while (!regexec(&regex, wholeString, nmatch, pmatch, 0))
669 {
670 strncpy(wholeString + pmatch[0].rm_so, replacement, replacementLen);
671 memmove(wholeString + pmatch[0].rm_so + replacementLen, wholeString + pmatch[0].rm_eo, strlen(wholeString + pmatch[0].rm_eo) + 1);
672 }
673 regfree(&regex);
674 });
675}
676
680vector<string> VuoLog_getBacktrace(void)
681{
682 void *array[100];
683 size_t size = backtrace(array, 100);
684 char **strings = backtrace_symbols(array, size);
685 vector<string> outputStrings;
686
687 // Start at 1 to skip the VuoLog_getBacktrace() function.
688 for (size_t i = 1; i < size; i++)
689 {
690 // Trim off the line number, since callees may want to skip additional stack frames.
691 const int lineNumberLen = 4;
692 string trimmedLine = strings[i] + lineNumberLen;
693
694 const int libraryLen = 36;
695 const int addressLen = 19;
696 string symbol = strings[i] + lineNumberLen + libraryLen + addressLen;
697 string instructionOffset = symbol.substr(symbol.find(' '));
698 symbol = symbol.substr(0, symbol.find(' '));
699
700 int status;
701 char *unmangled = abi::__cxa_demangle(symbol.c_str(), nullptr, nullptr, &status);
702 if (status == 0)
703 {
704 // Boil down the C++ standard library's bloviation.
705 VuoLog_replaceString(unmangled, "std::__1::", "");
706 VuoLog_replaceString(unmangled, "basic_string<char, char_traits<char>, allocator<char> >", "string");
707 VuoLog_replaceString(unmangled, ", less<[^>]*>, allocator<pair<[^>]*, [^>]*> > >", ">"); // map<…>
708 VuoLog_replaceString(unmangled, ", less<[^>]*>, allocator<[^>]*> >", ">"); // set<…>
709 VuoLog_replaceString(unmangled, ", allocator<[^>]*> >", ">"); // vector<…>
710
711 outputStrings.push_back(trimmedLine.substr(0, libraryLen + addressLen) + unmangled + instructionOffset);
712 free(unmangled);
713 }
714 else
715 outputStrings.push_back(trimmedLine);
716 }
717
718 // Hide uninformative stack frames.
719 {
720 // If the last stack frame is something like "??? 0x0000000000000010 0x0 + 16",
721 // the stack parser's gone off the rails.
722 auto last = outputStrings.back();
723 if (last.substr(0, 4) == "??? "
724 && last.find(" 0x0 + ") != string::npos)
725 outputStrings.pop_back();
726
727 last = outputStrings.back();
728 if (last.substr(0, 13) == "libdyld.dylib"
729 && last.find(" start + ") != string::npos)
730 outputStrings.pop_back();
731
732 outputStrings.erase(
733 remove_if(outputStrings.begin(), outputStrings.end(),
734 [](const string &s) {
735 return s.find("_dispatch_queue_override_invoke") != string::npos
736 || s.find("_dispatch_root_queue_drain") != string::npos
737 || s.find("_dispatch_worker_thread2") != string::npos
738 || s.find("_dispatch_lane_serial_drain") != string::npos
739 || s.find("_dispatch_lane_barrier_sync_invoke_and_complete") != string::npos
740 || s.find("_dispatch_lane_invoke") != string::npos
741 || s.find("_dispatch_workloop_worker_thread") != string::npos
742 || s.find("_dispatch_continuation_pop") != string::npos
743 || s.find("_dispatch_main_queue_callback_4CF") != string::npos
744 || s.find("__CFRunLoopDoObservers") != string::npos
745 || s.find("__CFRunLoopDoSource0") != string::npos
746 || s.find("__CFRunLoopDoSources0") != string::npos
747 || s.find("__CFRunLoopRun") != string::npos
748 || s.find("__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__") != string::npos
749 || s.find("__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__") != string::npos
750 || s.find("__CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__") != string::npos
751 || s.find("_CFXRegistrationPost") != string::npos
752 || s.find("_CFXNotification") != string::npos
753 || s.find("_NSWindowSendWindowDidMove") != string::npos
754 || s.find("_NSSendEventToObservers") != string::npos
755 || s.find("NSCarbonMenuImpl") != string::npos
756 || s.find("NSSLMMenuEventHandler") != string::npos
757 || s.find("CopyCarbonUIElementAttributeValue") != string::npos
758 || s.find("NSApplication(NSEvent) _") != string::npos
759 || s.find("NSApplication(NSAppleEventHandling) _") != string::npos
760 || s.find("withWindowOrderingObserverHeuristic") != string::npos
761 || s.find("aeProcessAppleEvent") != string::npos
762 || s.find("dispatchEventAndSendReply") != string::npos
763 || s.find("aeDispatchAppleEvent") != string::npos
764 || s.find("_NSAppleEventManagerGenericHandler") != string::npos
765 || s.find("NSWindow _") != string::npos
766 || s.find("HIServices") != string::npos
767 || s.find("HIToolbox") != string::npos
768 || s.find("RunCurrentEventLoopInMode") != string::npos
769 || s.find("ReceiveNextEventCommon") != string::npos
770 || s.find("_BlockUntilNextEventMatchingListInModeWithFilter") != string::npos
771 || s.find("_DPSNextEvent") != string::npos
772 || s.find("_pthread_wqthread") != string::npos
773 || s.find("qt_plugin_instance") != string::npos
774 || s.find("QWindowSystemInterface::") != string::npos
775 || s.find("QWidgetPrivate::") != string::npos
776 || s.find("QApplicationPrivate::") != string::npos
777 || s.find("QGuiApplicationPrivate::") != string::npos
778 || s.find("QCoreApplication::notifyInternal2") != string::npos
779 || s.find("QCoreApplicationPrivate::") != string::npos;
780 }),
781 outputStrings.end());
782 }
783
784 free(strings);
785 return outputStrings;
786}