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