]> www.fi.muni.cz Git - evince.git/blob - lib/ev-debug.c
0173a7da388090023a6f6f7ce160f6e0dec5ebf2
[evince.git] / lib / ev-debug.c
1 /*
2  *  Copyright (C) 2003 Marco Pesenti Gritti
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2, or (at your option)
7  *  any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  *
18  *  $Id$
19  */
20
21 #include "config.h"
22
23 #include "ev-debug.h"
24
25 #ifndef DISABLE_PROFILING
26
27 #include <glib/gbacktrace.h>
28 #include <string.h>
29 #include <signal.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #ifdef HAVE_EXECINFO_H
33 #include <execinfo.h>
34 #endif
35
36 static GHashTable *ev_profilers_hash = NULL;
37 static const char *ev_profile_modules = NULL;
38 static const char *ev_debug_break = NULL;
39
40 #endif
41
42 #ifndef DISABLE_LOGGING
43
44 static const char *ev_log_modules;
45
46 static void
47 log_module (const gchar *log_domain,
48             GLogLevelFlags log_level,
49             const gchar *message,
50             gpointer user_data)
51 {
52         gboolean should_log = FALSE;
53
54         if (!ev_log_modules) return;
55
56         if (strcmp (ev_log_modules, "all") != 0)
57         {
58                 char **modules;
59                 int i;
60
61                 modules = g_strsplit (ev_log_modules, ":", 100);
62
63                 for (i = 0; modules[i] != NULL; i++)
64                 {
65                         if (strstr (message, modules [i]) != NULL)
66                         {
67                                 should_log = TRUE;
68                                 break;
69                         }
70                 }
71
72                 g_strfreev (modules);
73         }
74         else
75         {
76                 should_log = TRUE;
77         }
78
79         if (should_log)
80         {
81                 g_print ("%s\n", message);
82         }
83 }
84
85 #define MAX_DEPTH 200
86
87 static void 
88 trap_handler (const char *log_domain,
89               GLogLevelFlags log_level,
90               const char *message,
91               gpointer user_data)
92 {
93         g_log_default_handler (log_domain, log_level, message, user_data);
94
95         if (ev_debug_break != NULL &&
96             (log_level & (G_LOG_LEVEL_WARNING |
97                           G_LOG_LEVEL_ERROR |
98                           G_LOG_LEVEL_CRITICAL |
99                           G_LOG_FLAG_FATAL)))
100         {
101                 if (strcmp (ev_debug_break, "stack") == 0)
102                 {
103 #ifdef HAVE_EXECINFO_H
104                         void *array[MAX_DEPTH];
105                         size_t size;
106                         
107                         size = backtrace (array, MAX_DEPTH);
108                         backtrace_symbols_fd (array, size, 2);
109 #else
110                         g_on_error_stack_trace (g_get_prgname ());
111 #endif
112                 }
113                 else if (strcmp (ev_debug_break, "trap") == 0)
114                 {
115                         G_BREAKPOINT ();
116                 }
117                 else if (strcmp (ev_debug_break, "suspend") == 0)
118                 {
119                         g_print ("Suspending program; attach with the debugger.\n");
120
121                         raise (SIGSTOP);
122                 }
123         }
124 }
125
126 #endif
127
128 void
129 ev_debug_init (void)
130 {
131 #ifndef DISABLE_LOGGING
132         ev_log_modules = g_getenv ("EV_LOG_MODULES");
133         ev_debug_break = g_getenv ("EV_DEBUG_BREAK");
134
135         g_log_set_default_handler (trap_handler, NULL);
136
137         g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, log_module, NULL);
138
139 #endif
140 #ifndef DISABLE_PROFILING
141         ev_profile_modules = g_getenv ("EV_PROFILE_MODULES");
142 #endif
143 }
144
145 #ifndef DISABLE_PROFILING
146
147 static EvProfiler *
148 ev_profiler_new (const char *name, const char *module)
149 {
150         EvProfiler *profiler;
151
152         profiler = g_new0 (EvProfiler, 1);
153         profiler->timer = g_timer_new ();
154         profiler->name  = g_strdup (name);
155         profiler->module  = g_strdup (module);
156
157         g_timer_start (profiler->timer);
158
159         return profiler;
160 }
161
162 static gboolean
163 ev_should_profile (const char *module)
164 {
165         char **modules;
166         int i;
167         gboolean res = FALSE;
168
169         if (!ev_profile_modules) return FALSE;
170         if (strcmp (ev_profile_modules, "all") == 0) return TRUE;
171
172         modules = g_strsplit (ev_profile_modules, ":", 100);
173
174         for (i = 0; modules[i] != NULL; i++)
175         {
176                 if (strcmp (module, modules [i]) == 0)
177                 {
178                         res = TRUE;
179                         break;
180                 }
181         }
182
183         g_strfreev (modules);
184
185         return res;
186 }
187
188 static void
189 ev_profiler_dump (EvProfiler *profiler)
190 {
191         double seconds;
192
193         g_return_if_fail (profiler != NULL);
194
195         seconds = g_timer_elapsed (profiler->timer, NULL);
196
197         g_print ("[ %s ] %s %f s elapsed\n",
198                  profiler->module, profiler->name,
199                  seconds);
200 }
201
202 static void
203 ev_profiler_free (EvProfiler *profiler)
204 {
205         g_return_if_fail (profiler != NULL);
206
207         g_timer_destroy (profiler->timer);
208         g_free (profiler->name);
209         g_free (profiler->module);
210         g_free (profiler);
211 }
212
213 void
214 ev_profiler_start (const char *name, const char *module)
215 {
216         EvProfiler *profiler;
217
218         if (ev_profilers_hash == NULL)
219         {
220                 ev_profilers_hash =
221                         g_hash_table_new_full (g_str_hash, g_str_equal,
222                                                g_free, NULL);
223         }
224
225         if (!ev_should_profile (module)) return;
226
227         profiler = ev_profiler_new (name, module);
228
229         g_hash_table_insert (ev_profilers_hash, g_strdup (name), profiler);
230 }
231
232 void
233 ev_profiler_stop (const char *name)
234 {
235         EvProfiler *profiler;
236
237         profiler = g_hash_table_lookup (ev_profilers_hash, name);
238         if (profiler == NULL) return;
239         g_hash_table_remove (ev_profilers_hash, name);
240
241         ev_profiler_dump (profiler);
242         ev_profiler_free (profiler);
243 }
244
245 #endif