Vuo  2.4.0
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
278{
279 // Detect LLDB.
280 {
281 int mib[4];
282 mib[0] = CTL_KERN;
283 mib[1] = KERN_PROC;
284 mib[2] = KERN_PROC_PID;
285 mib[3] = getpid();
286
287 struct kinfo_proc info;
288 info.kp_proc.p_flag = 0;
289 size_t size = sizeof(info);
290 if (sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) == 0
291 && info.kp_proc.p_flag & P_TRACED)
292 return true;
293 }
294
295 // Detect Instruments.
296 {
297 uint32_t imageCount = _dyld_image_count();
298 for (uint32_t i = 0; i < imageCount; ++i)
299 if (strstr(_dyld_get_image_name(i), "/DVTInstrumentsFoundation.framework/"))
300 return true;
301 }
302
303 return false;
304}
305
306extern struct mach_header __dso_handle;
307
308void VuoLog(const char *moduleName, const char *file, const unsigned int linenumber, const char *function, const char *format, ...)
309{
310 if (!VuoHeap_isPointerReadable(moduleName))
311 {
312 fprintf(stderr, "VuoLog() error: Invalid 'moduleName' argument (%p). You may need to rebuild the module calling VuoLog().\n", moduleName);
314 return;
315 }
316 if (!VuoHeap_isPointerReadable(file))
317 {
318 fprintf(stderr, "VuoLog() error: Invalid 'file' argument (%p). You may need to rebuild the module calling VuoLog().\n", file);
320 return;
321 }
322 if (!VuoHeap_isPointerReadable(function))
323 {
324 fprintf(stderr, "VuoLog() error: Invalid 'function' argument (%p). You may need to rebuild the module calling VuoLog().\n", function);
326 return;
327 }
328 if (!VuoHeap_isPointerReadable(format))
329 {
330 fprintf(stderr, "VuoLog() error: Invalid 'format' argument (%p). You may need to rebuild the module calling VuoLog().\n", format);
332 return;
333 }
334
335 va_list args;
336
337 va_start(args, format);
338 int size = vsnprintf(NULL, 0, format, args);
339 va_end(args);
340
341 char *formattedString = (char *)malloc(size+1);
342 va_start(args, format);
343 vsnprintf(formattedString, size+1, format, args);
344 va_end(args);
345
346 char *formattedFunction = NULL;
347
348 // This may be a mangled function name of the form `__6+[f g]_block_invoke`.
349 // Trim the prefix and suffix, since the line number is sufficient to locate the code within the function+block.
350 if (function && function[0] == '_' && function[1] == '_')
351 {
352 int actualFunctionLength = atoi(function + 2);
353 if (actualFunctionLength)
354 formattedFunction = strndup(function + 3 + (int)log10(actualFunctionLength), actualFunctionLength);
355 else
356 formattedFunction = strndup(function + 2, strrchr(function + 2, '_') - (function + 2));
357
358 // We may now be left with a C++-mangled symbol followed by `_block`,
359 // such as `_ZN9VuoRunner18replaceCompositionESsSsSs_block`.
360 // Extract just the method name (the last length-specified section).
361 if (strncmp(formattedFunction, "_ZN", 3) == 0)
362 {
363 int pos = 3;
364 int len, priorLen = 0;
365 while ((len = atoi(formattedFunction + pos)))
366 {
367 pos += 1 + (int)log10(len) + len;
368 priorLen = len;
369 }
370 char *f2 = strndup(formattedFunction + pos - priorLen, priorLen);
371 free(formattedFunction);
372 formattedFunction = f2;
373 }
374 }
375 else
376 {
377 const char *blockInvokePos = strstr(function, "_block_invoke");
378 if (blockInvokePos)
379 formattedFunction = strndup(function, blockInvokePos - function);
380 }
381
382 // Add a trailing `()`, unless it's an Objective-C method.
383 if (function)
384 {
385 const char *f = formattedFunction ? formattedFunction : function;
386 size_t fLen = strlen(f);
387 if (f[fLen - 1] != ']')
388 {
389 size_t mallocSize = fLen + 2 + 1;
390 char *f2 = (char *)malloc(mallocSize);
391 strlcpy(f2, f, mallocSize);
392 strlcat(f2, "()", mallocSize);
393 if (formattedFunction)
394 free(formattedFunction);
395 formattedFunction = f2;
396 }
397 }
398
399 const char *formattedFile = file;
400
401 if (!VuoHeap_isPointerReadable(formattedFile))
402 formattedFile = "(unknown)";
403
404 // Trim the path, if present.
405 if (const char *lastSlash = strrchr(formattedFile, '/'))
406 formattedFile = lastSlash + 1;
407
408 double time = VuoLogGetElapsedTime();
409
410 // If it's been a while since the last log, add a separator.
411 static double priorTime = 0;
412 const char *separator = "";
413 if (priorTime > 0 && time - priorTime > 0.5)
414 separator = "\n";
415 priorTime = time;
416
417 // Decide on a name for the thread emitting the log message.
418 pthread_t thread = pthread_self();
419 char threadName[256];
420 if (pthread_equal(thread, VuoLog_mainThread))
421 strcpy(threadName, "main");
422 else
423 {
424 bzero(threadName, 256);
425 int ret = pthread_getname_np(thread, threadName, 256);
426 if (!(ret == 0 && strlen(threadName)))
427 snprintf(threadName, 256, "%llx", (uint64_t)thread);
428 }
429
430 // Use a bright color for the main text.
431 const char *mainColor = "\033[97m";
432 // Use a medium color for the metadata.
433 const char *metadataColor = "\033[38;5;249m";
434 // Use a darker color for separators.
435 const char *separatorColor = "\033[90m";
436 // Try to give each process a unique color, to distinguish the host and the running composition(s).
437 // ANSI-256's 6x6x6 color cube begins at index 16 and spans 216 indices.
438 // Skip the first 72 indices, which are darker (illegible against a black terminal background).
439 int pidColor = getpid() % 144 + 88;
440 // Color the main thread the same as the process; choose a unique color for each other thread.
441 int threadColor = pthread_equal(thread, VuoLog_mainThread)
442 ? pidColor
443 : ((uint64_t)thread) % 144 + 88;
444
445 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",
446 separator,
447 separatorColor,
448 metadataColor,
449 time,
450 separatorColor,
451 metadataColor,
453 separatorColor,
454 metadataColor,
455 moduleName ? moduleName : "Vuo",
456 separatorColor,
457 pidColor,
458 getpid(),
459 separatorColor,
460 threadColor,
461 threadName,
462 separatorColor,
463 metadataColor,
464 formattedFile,
465 separatorColor,
466 metadataColor,
467 linenumber,
468 formattedFunction ? formattedFunction : function,
469 mainColor,
470 formattedString);
471
472
473 // Also send it to the macOS Console.
474 {
475 // Can't just call this directly because it relies on Apple-specific compiler extensions that aren't available in Clang 3.2.
476 // os_log(OS_LOG_DEFAULT, "...", ...);
477
478 typedef void (*vuoMacOsLogInternalType)(void *dso, void *log, uint8_t type, const char *message, ...);
479 typedef void (*vuoMacOsLogImplType)(void *dso, void *log, uint8_t type, const char *format, uint8_t *buf, uint32_t size);
480 static vuoMacOsLogInternalType vuoMacOsLogInternal = NULL;
481 static vuoMacOsLogImplType vuoMacOsLogImpl = NULL;
482 static dispatch_once_t once = 0;
483 static bool debuggerAttached = false;
484 dispatch_once(&once, ^{
485 debuggerAttached = VuoLog_isDebuggerAttached();
486 NSOperatingSystemVersion operatingSystemVersion = VuoLog_getOSVersion();
487 if (operatingSystemVersion.majorVersion == 10 && operatingSystemVersion.minorVersion == 12)
488 // _os_log_impl doesn't work on macOS 10.12.
489 vuoMacOsLogInternal = (vuoMacOsLogInternalType)dlsym(RTLD_SELF, "_os_log_internal");
490 else if ((operatingSystemVersion.majorVersion == 10 && operatingSystemVersion.minorVersion > 12)
491 || operatingSystemVersion.majorVersion > 10)
492 // _os_log_internal doesn't work on macOS 10.13+.
493 vuoMacOsLogImpl = (vuoMacOsLogImplType)dlsym(RTLD_SELF, "_os_log_impl");
494 });
495
496 if (!debuggerAttached)
497 {
498 void *log = os_log_create("org.vuo", formattedFile);
499
500 if (vuoMacOsLogInternal)
501 vuoMacOsLogInternal(&__dso_handle, log, 0 /*OS_LOG_TYPE_DEFAULT*/, "%{public}41s:%-4u %{public}s", formattedFunction ? formattedFunction : function, linenumber, formattedString);
502 else if (vuoMacOsLogImpl)
503 {
504 char *formattedForOsLog;
505 asprintf(&formattedForOsLog, "%41s:%-4u %s", formattedFunction ? formattedFunction : function, linenumber, formattedString);
506
507 // https://reviews.llvm.org/rC284990#C2197511NL2613
508 uint8_t logFormatDescriptor[12] = {
509 2, // "summary" = HasNonScalarItems (a C string)
510 1, // "numArgs" = one C string
511 34, // "argDescriptor" = 2 (IsPublic) + 2 (StringKind) << 4
512 8, // "argSize" = one C string (a 64-bit pointer)
513 };
514 // …followed by the pointer itself.
515 memcpy(logFormatDescriptor + 4, &formattedForOsLog, 8);
516
517 vuoMacOsLogImpl(&__dso_handle, log, 0 /*OS_LOG_TYPE_DEFAULT*/, "%{public}s", logFormatDescriptor, sizeof(logFormatDescriptor));
518
519 free(formattedForOsLog);
520 }
521
522 os_release(log);
523 }
524 }
525
526
527 static dispatch_once_t historyInitialized = 0;
528 dispatch_once(&historyInitialized, ^{
529 for (int i = 0; i < VuoLogHistoryItems; ++i)
530 VuoLogHistory[i] = NULL;
531 VuoLogHistoryQueue = dispatch_queue_create("VuoLogHistory", NULL);
532 });
533
534 dispatch_sync(VuoLogHistoryQueue, ^{
535 // Keep the most recent messages in VuoLogHistory.
536 {
537 char *formattedPrefixedString;
538 asprintf(&formattedPrefixedString, "t=%8.4fs %27.27s:%-4u %41.41s %s", time, formattedFile, linenumber, formattedFunction ? formattedFunction : function, formattedString);
539 free(formattedString);
540 if (formattedFunction)
541 free(formattedFunction);
542
543 // Find the first open history slot.
544 int i;
545 for (i = 0; i < VuoLogHistoryItems; ++i)
546 if (!VuoLogHistory[i])
547 break;
548
549 if (i >= VuoLogHistoryItems)
550 {
551 // No open slots; expire 1 and rotate the rest.
552 free(VuoLogHistory[0]);
553 for (int i = 0; i < VuoLogHistoryItems-1; ++i)
555 i = VuoLogHistoryItems - 1;
556 }
557
558 VuoLogHistory[i] = formattedPrefixedString;
559 }
560
561 // Combine VuoLogHistory into a single string for the crash report.
562 {
563 if (VuoCrashReport.message)
564 free(VuoCrashReport.message);
565
566 long size = 0;
567 for (int i = 0; i < VuoLogHistoryItems; ++i)
568 if (VuoLogHistory[i])
569 size += strlen(VuoLogHistory[i]) + 1 /* \n */;
570 size += 1 /* null terminator */;
571
572 char *message = (char *)malloc(size);
573 strlcpy(message, VuoLogHistory[0], size);
574 for (int i = 1; i < VuoLogHistoryItems; ++i)
575 if (VuoLogHistory[i])
576 {
577 strlcat(message, "\n", size);
578 strlcat(message, VuoLogHistory[i], size);
579 }
580
581 VuoCrashReport.message = message;
582 }
583 });
584}
585
595{
596 static dispatch_once_t checked = 0;
597 static bool debug = false;
598 dispatch_once(&checked, ^{
599 debug = CFPreferencesGetAppBooleanValue(CFSTR("debug"), CFSTR("org.vuo.Editor"), NULL);
600 });
601 return debug;
602}
603
608{
609 vector<string> backtrace = VuoLog_getBacktrace();
610
611 // Skip the VuoLog_backtrace() function.
612 backtrace.erase(backtrace.begin());
613
614 int i = 1;
615 for (auto line : backtrace)
616 fprintf(stderr, "%3d %s\n", i++, line.c_str());
617}
618
624void VuoLog_replaceString(char *wholeString, const char *substringToRemove, const char *replacement)
625{
626 size_t replacementLen = strlen(replacement);
627 regex_t regex;
628 regcomp(&regex, substringToRemove, REG_EXTENDED);
629 size_t nmatch = 1;
630 regmatch_t pmatch[nmatch];
631 while (!regexec(&regex, wholeString, nmatch, pmatch, 0))
632 {
633 strncpy(wholeString + pmatch[0].rm_so, replacement, replacementLen);
634 memmove(wholeString + pmatch[0].rm_so + replacementLen, wholeString + pmatch[0].rm_eo, strlen(wholeString + pmatch[0].rm_eo) + 1);
635 }
636 regfree(&regex);
637}
638
642vector<string> VuoLog_getBacktrace(void)
643{
644 void *array[100];
645 size_t size = backtrace(array, 100);
646 char **strings = backtrace_symbols(array, size);
647 vector<string> outputStrings;
648
649 // Start at 1 to skip the VuoLog_getBacktrace() function.
650 for (size_t i = 1; i < size; i++)
651 {
652 // Trim off the line number, since callees may want to skip additional stack frames.
653 const int lineNumberLen = 4;
654 string trimmedLine = strings[i] + lineNumberLen;
655
656 const int libraryLen = 36;
657 const int addressLen = 19;
658 string symbol = strings[i] + lineNumberLen + libraryLen + addressLen;
659 string instructionOffset = symbol.substr(symbol.find(' '));
660 symbol = symbol.substr(0, symbol.find(' '));
661
662 int status;
663 char *unmangled = abi::__cxa_demangle(symbol.c_str(), nullptr, nullptr, &status);
664 if (status == 0)
665 {
666 // Boil down the C++ standard library's bloviation.
667 VuoLog_replaceString(unmangled, "std::__1::", "");
668 VuoLog_replaceString(unmangled, "basic_string<char, char_traits<char>, allocator<char> >", "string");
669 VuoLog_replaceString(unmangled, ", less<[^>]*>, allocator<pair<[^>]*, [^>]*> > >", ">"); // map<…>
670 VuoLog_replaceString(unmangled, ", less<[^>]*>, allocator<[^>]*> >", ">"); // set<…>
671 VuoLog_replaceString(unmangled, ", allocator<[^>]*> >", ">"); // vector<…>
672
673 outputStrings.push_back(trimmedLine.substr(0, libraryLen + addressLen) + unmangled + instructionOffset);
674 free(unmangled);
675 }
676 else
677 outputStrings.push_back(trimmedLine);
678 }
679
680 // Hide uninformative stack frames.
681 {
682 // If the last stack frame is something like "??? 0x0000000000000010 0x0 + 16",
683 // the stack parser's gone off the rails.
684 auto last = outputStrings.back();
685 if (last.substr(0, 4) == "??? "
686 && last.find(" 0x0 + ") != string::npos)
687 outputStrings.pop_back();
688
689 last = outputStrings.back();
690 if (last.substr(0, 13) == "libdyld.dylib"
691 && last.find(" start + ") != string::npos)
692 outputStrings.pop_back();
693
694 outputStrings.erase(
695 remove_if(outputStrings.begin(), outputStrings.end(),
696 [](const string &s) {
697 return s.find("_dispatch_queue_override_invoke") != string::npos
698 || s.find("_dispatch_root_queue_drain") != string::npos
699 || s.find("_dispatch_worker_thread2") != string::npos
700 || s.find("_dispatch_lane_serial_drain") != string::npos
701 || s.find("_dispatch_lane_barrier_sync_invoke_and_complete") != string::npos
702 || s.find("_dispatch_lane_invoke") != string::npos
703 || s.find("_dispatch_workloop_worker_thread") != string::npos
704 || s.find("_dispatch_continuation_pop") != string::npos
705 || s.find("_dispatch_main_queue_callback_4CF") != string::npos
706 || s.find("__CFRunLoopDoObservers") != string::npos
707 || s.find("__CFRunLoopDoSource0") != string::npos
708 || s.find("__CFRunLoopDoSources0") != string::npos
709 || s.find("__CFRunLoopRun") != string::npos
710 || s.find("__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__") != string::npos
711 || s.find("__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__") != string::npos
712 || s.find("__CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__") != string::npos
713 || s.find("_CFXRegistrationPost") != string::npos
714 || s.find("_CFXNotification") != string::npos
715 || s.find("_NSWindowSendWindowDidMove") != string::npos
716 || s.find("_NSSendEventToObservers") != string::npos
717 || s.find("NSCarbonMenuImpl") != string::npos
718 || s.find("NSSLMMenuEventHandler") != string::npos
719 || s.find("CopyCarbonUIElementAttributeValue") != string::npos
720 || s.find("NSApplication(NSEvent) _") != string::npos
721 || s.find("NSApplication(NSAppleEventHandling) _") != string::npos
722 || s.find("withWindowOrderingObserverHeuristic") != string::npos
723 || s.find("aeProcessAppleEvent") != string::npos
724 || s.find("dispatchEventAndSendReply") != string::npos
725 || s.find("aeDispatchAppleEvent") != string::npos
726 || s.find("_NSAppleEventManagerGenericHandler") != string::npos
727 || s.find("NSWindow _") != string::npos
728 || s.find("HIServices") != string::npos
729 || s.find("HIToolbox") != string::npos
730 || s.find("RunCurrentEventLoopInMode") != string::npos
731 || s.find("ReceiveNextEventCommon") != string::npos
732 || s.find("_BlockUntilNextEventMatchingListInModeWithFilter") != string::npos
733 || s.find("_DPSNextEvent") != string::npos
734 || s.find("_pthread_wqthread") != string::npos
735 || s.find("qt_plugin_instance") != string::npos
736 || s.find("QWindowSystemInterface::") != string::npos
737 || s.find("QWidgetPrivate::") != string::npos
738 || s.find("QApplicationPrivate::") != string::npos
739 || s.find("QGuiApplicationPrivate::") != string::npos
740 || s.find("QCoreApplication::notifyInternal2") != string::npos
741 || s.find("QCoreApplicationPrivate::") != string::npos;
742 }),
743 outputStrings.end());
744 }
745
746 free(strings);
747 return outputStrings;
748}