| 95 | } |
| 96 | |
| 97 | void gjs_log_init() { |
| 98 | bool expected = false; |
| 99 | if (!s_initialized.compare_exchange_strong(expected, true)) |
| 100 | return; |
| 101 | |
| 102 | if (gjs_environment_variable_is_set("GJS_DEBUG_TIMESTAMP")) |
| 103 | s_timer = g_timer_new(); |
| 104 | |
| 105 | s_print_thread = gjs_environment_variable_is_set("GJS_DEBUG_THREAD"); |
| 106 | |
| 107 | const char* debug_output = g_getenv("GJS_DEBUG_OUTPUT"); |
| 108 | if (debug_output && g_str_equal(debug_output, "stderr")) { |
| 109 | s_debug_log_enabled = true; |
| 110 | } else if (debug_output) { |
| 111 | std::string log_file; |
| 112 | |
| 113 | /* Allow debug-%u.log for per-pid logfiles as otherwise log messages |
| 114 | * from multiple processes can overwrite each other. |
| 115 | * |
| 116 | * (printf below should be safe as we check '%u' is the only format |
| 117 | * string) |
| 118 | */ |
| 119 | char* c = strchr(const_cast<char*>(debug_output), '%'); |
| 120 | if (c && c[1] == 'u' && !strchr(c + 1, '%')) { |
| 121 | Gjs::AutoChar file_name; |
| 122 | #if defined(__clang__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) |
| 123 | _Pragma("GCC diagnostic push") |
| 124 | _Pragma("GCC diagnostic ignored \"-Wformat-nonliteral\"") |
| 125 | #endif |
| 126 | file_name = g_strdup_printf(debug_output, getpid()); |
| 127 | #if defined(__clang__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) |
| 128 | _Pragma("GCC diagnostic pop") |
| 129 | #endif |
| 130 | log_file = file_name.get(); |
| 131 | } else { |
| 132 | log_file = debug_output; |
| 133 | } |
| 134 | |
| 135 | // avoid truncating in case we're using shared logfile |
| 136 | s_log_file = std::make_unique<LogFile>(log_file.c_str()); |
| 137 | if (s_log_file->has_error()) { |
| 138 | fprintf(stderr, "Failed to open log file `%s': %s\n", |
| 139 | log_file.c_str(), g_strerror(errno)); |
| 140 | } |
| 141 | |
| 142 | s_debug_log_enabled = true; |
| 143 | } |
| 144 | |
| 145 | if (!s_log_file) |
| 146 | s_log_file = std::make_unique<LogFile>(nullptr, stderr); |
| 147 | |
| 148 | if (s_debug_log_enabled) { |
| 149 | const char* topics = g_getenv("GJS_DEBUG_TOPICS"); |
| 150 | s_enabled_topics.fill(topics == nullptr); |
| 151 | if (topics) { |
| 152 | Gjs::AutoStrv prefixes{g_strsplit(topics, ";", -1)}; |
| 153 | for (unsigned i = 0; prefixes[i] != nullptr; i++) { |
| 154 | GjsDebugTopic topic = prefix_to_topic(prefixes[i]); |
no test coverage detected