static void VMToolsLogWrapper(GLogLevelFlags level, const char *fmt, va_list args) { if (!gLogInitialized && !IS_FATAL(level)) { /* * Avoid logging without initialization because * it leads to spamming of the console output. * Fatal messages are exception. */ return; } VMTools_AcquireLogStateLock(); if (gLoggingStopped) { /* This is to avoid nested logging in vmxLogger */ VMTools_ReleaseLogStateLock(); return; } VMTools_ReleaseLogStateLock(); if (gPanicCount == 0) { char *msg = Str_Vasprintf(NULL, fmt, args); if (msg != NULL) { g_log(gLogDomain, level, "%s", msg); free(msg); } } else { /* Try to avoid malloc() since we're aborting. */ gchar msg[256]; Str_Vsnprintf(msg, sizeof msg, fmt, args); VMToolsLog(gLogDomain, level, msg, gDefaultData); } }
static void VMToolsLogMsg(gpointer _data, gpointer userData) { LogEntry *entry = _data; GlibLogger *logger = entry->handler->logger; gboolean usedSyslog = FALSE; if (logger != NULL) { logger->logfn(entry->domain, entry->level, entry->msg, logger); usedSyslog = entry->handler->isSysLog; } else if (gErrorData->logger != NULL) { gErrorData->logger->logfn(entry->domain, entry->level, entry->msg, gErrorData->logger); usedSyslog = gErrorData->isSysLog; } /* * Any fatal errors need to go to syslog no matter what. */ if (!usedSyslog && IS_FATAL(entry->level) && gErrorSyslog) { gErrorSyslog->logger->logfn(entry->domain, entry->level, entry->msg, gErrorSyslog->logger); } VMToolsFreeLogEntry(entry); }
static void VMToolsLog(const gchar *domain, GLogLevelFlags level, const gchar *message, gpointer _data) { LogHandler *data = _data; if (SHOULD_LOG(level, data)) { gchar *msg; data = data->inherited ? gDefaultData : data; msg = VMToolsLogFormat(message, domain, level, data); if (data->logger != NULL) { data->logger->logfn(domain, level, msg, data->logger); } else if (gErrorData->logger != NULL) { gErrorData->logger->logfn(domain, level, msg, gErrorData->logger); } g_free(msg); } if (IS_FATAL(level)) { VMToolsLogPanic(); } }
static void VMToolsLog(const gchar *domain, GLogLevelFlags level, const gchar *message, gpointer _data) { LogHandler *data = _data; if (SHOULD_LOG(level, data)) { LogEntry *entry; data = data->inherited ? gDefaultData : data; entry = g_malloc0(sizeof(LogEntry)); if (entry) { entry->domain = domain ? g_strdup(domain) : NULL; if (domain && !entry->domain) { VMToolsLogPanic(); } entry->handler = data; entry->level = level; } if (gLogIOSuspended && data->needsFileIO) { if (gMaxCacheEntries == 0) { /* No way to log at this point, drop it */ VMToolsFreeLogEntry(entry); gDroppedLogCount++; goto exit; } entry->msg = VMToolsLogFormat(message, domain, level, data, TRUE); /* * Cache the log message */ if (!gCachedLogs) { /* * If gMaxCacheEntries > 1K, start with 1/4th size * to avoid frequent allocations */ gCachedLogs = g_ptr_array_sized_new(gMaxCacheEntries < 1024 ? gMaxCacheEntries : gMaxCacheEntries/4); if (!gCachedLogs) { VMToolsLogPanic(); } /* * Some builds use glib version 2.16.4 which does not * support g_ptr_array_set_free_func function */ } /* * We don't expect logging to be suspended for a long time, * so we can avoid putting a cap on cache size. However, we * still have a default cap of 4K messages, just to be safe. */ if (gCachedLogs->len < gMaxCacheEntries) { g_ptr_array_add(gCachedLogs, entry); } else { /* * Cache is full, drop the oldest log message. This is not * very efficient but we don't expect this to be a common * case anyway. */ LogEntry *oldest = g_ptr_array_remove_index(gCachedLogs, 0); VMToolsFreeLogEntry(oldest); gDroppedLogCount++; g_ptr_array_add(gCachedLogs, entry); } } else { entry->msg = VMToolsLogFormat(message, domain, level, data, FALSE); VMToolsLogMsg(entry, NULL); } } exit: if (IS_FATAL(level)) { VMToolsLogPanic(); } }