File: | cafe-session/cdm-signal-handler.c |
Warning: | line 279, column 4 This statement is never executed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- |
2 | * |
3 | * Copyright (C) 2006 Red Hat, Inc. |
4 | * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu> |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by |
8 | * the Free Software Foundation; either version 2 of the License, or |
9 | * (at your option) any later version. |
10 | * |
11 | * This program is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU General Public License |
17 | * along with this program; if not, write to the Free Software |
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. |
19 | * |
20 | */ |
21 | |
22 | #include "config.h" |
23 | |
24 | #include <stdlib.h> |
25 | #include <stdio.h> |
26 | #include <fcntl.h> |
27 | #include <unistd.h> |
28 | #include <string.h> |
29 | #include <signal.h> |
30 | #if HAVE_EXECINFO_H1 |
31 | #include <execinfo.h> |
32 | #endif |
33 | #include <syslog.h> |
34 | #include <sys/wait.h> |
35 | #include <sys/stat.h> |
36 | |
37 | #include <glib.h> |
38 | #include <glib/gi18n.h> |
39 | #include <glib/gstdio.h> |
40 | #include <glib-object.h> |
41 | |
42 | #include "cdm-signal-handler.h" |
43 | |
44 | #ifdef __GNUC__4 |
45 | #define UNUSED_VARIABLE__attribute__ ((unused)) __attribute__ ((unused)) |
46 | #else |
47 | #define UNUSED_VARIABLE__attribute__ ((unused)) |
48 | #endif |
49 | |
50 | typedef struct { |
51 | int signal_number; |
52 | CdmSignalHandlerFunc func; |
53 | gpointer data; |
54 | guint id; |
55 | } CallbackData; |
56 | |
57 | struct _CdmSignalHandler { |
58 | GObject parent_instance; |
59 | GHashTable* lookup; |
60 | GHashTable* id_lookup; |
61 | GHashTable* action_lookup; |
62 | guint next_id; |
63 | GDestroyNotify fatal_func; |
64 | gpointer fatal_data; |
65 | }; |
66 | |
67 | static void cdm_signal_handler_finalize (GObject* object); |
68 | |
69 | static gpointer signal_handler_object = NULL((void*)0); |
70 | static int signal_pipes[2]; |
71 | static int signals_blocked = 0; |
72 | static sigset_t signals_block_mask; |
73 | static sigset_t signals_oldmask; |
74 | |
75 | G_DEFINE_TYPE(CdmSignalHandler, cdm_signal_handler, G_TYPE_OBJECT)static void cdm_signal_handler_init (CdmSignalHandler *self); static void cdm_signal_handler_class_init (CdmSignalHandlerClass *klass); static GType cdm_signal_handler_get_type_once (void ); static gpointer cdm_signal_handler_parent_class = ((void*) 0); static gint CdmSignalHandler_private_offset; static void cdm_signal_handler_class_intern_init (gpointer klass) { cdm_signal_handler_parent_class = g_type_class_peek_parent (klass); if (CdmSignalHandler_private_offset != 0) g_type_class_adjust_private_offset (klass, &CdmSignalHandler_private_offset); cdm_signal_handler_class_init ((CdmSignalHandlerClass*) klass); } __attribute__ ((__unused__ )) static inline gpointer cdm_signal_handler_get_instance_private (CdmSignalHandler *self) { return (((gpointer) ((guint8*) (self ) + (glong) (CdmSignalHandler_private_offset)))); } GType cdm_signal_handler_get_type (void) { static gsize static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer), "Expression evaluates to false"); (void) ( 0 ? (gpointer) *(&static_g_define_type_id) : ((void*)0)); (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id ) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (*(&static_g_define_type_id)) gapg_temp_newval; __typeof__ ((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id ); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5) ; gapg_temp_newval; })) && g_once_init_enter (&static_g_define_type_id )); }))) { GType g_define_type_id = cdm_signal_handler_get_type_once (); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id ) == sizeof (gpointer), "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id) = (g_define_type_id) ) : (void) 0; g_once_init_leave ((&static_g_define_type_id ), (gsize) (g_define_type_id)); })); } return static_g_define_type_id ; } __attribute__ ((__noinline__)) static GType cdm_signal_handler_get_type_once (void) { GType g_define_type_id = g_type_register_static_simple (((GType) ((20) << (2))), g_intern_static_string ("CdmSignalHandler" ), sizeof (CdmSignalHandlerClass), (GClassInitFunc)(void (*)( void)) cdm_signal_handler_class_intern_init, sizeof (CdmSignalHandler ), (GInstanceInitFunc)(void (*)(void)) cdm_signal_handler_init , (GTypeFlags) 0); { {{};} } return g_define_type_id; } |
76 | |
77 | static void block_signals_push(void) |
78 | { |
79 | signals_blocked++; |
80 | |
81 | if (signals_blocked == 1) |
82 | { |
83 | /* Set signal mask */ |
84 | sigemptyset(&signals_block_mask); |
85 | sigfillset(&signals_block_mask); |
86 | sigprocmask(SIG_BLOCK0, &signals_block_mask, &signals_oldmask); |
87 | } |
88 | } |
89 | |
90 | static void block_signals_pop(void) |
91 | { |
92 | signals_blocked--; |
93 | |
94 | if (signals_blocked == 0) |
95 | { |
96 | /* Set signal mask */ |
97 | sigprocmask(SIG_SETMASK2, &signals_oldmask, NULL((void*)0)); |
98 | } |
99 | } |
100 | |
101 | static gboolean signal_io_watch(GIOChannel* ioc, GIOCondition condition, CdmSignalHandler* handler) |
102 | { |
103 | char buf[256]; |
104 | gboolean is_fatal; |
105 | gsize bytes_read; |
106 | int i; |
107 | |
108 | block_signals_push(); |
109 | |
110 | g_io_channel_read_chars(ioc, buf, sizeof(buf), &bytes_read, NULL((void*)0)); |
111 | |
112 | is_fatal = FALSE(0); |
113 | |
114 | for (i = 0; i < bytes_read; i++) |
115 | { |
116 | int signum; |
117 | GSList* handlers; |
118 | GSList* l; |
119 | |
120 | signum = (gint32) buf[i]; |
121 | |
122 | g_debug("CdmSignalHandler: handling signal %d", signum); |
123 | handlers = g_hash_table_lookup(handler->lookup, GINT_TO_POINTER(signum)((gpointer) (glong) (signum))); |
124 | |
125 | g_debug("CdmSignalHandler: Found %u callbacks", g_slist_length(handlers)); |
126 | |
127 | for (l = handlers; l != NULL((void*)0); l = l->next) |
128 | { |
129 | gboolean res; |
130 | CallbackData* data; |
131 | |
132 | data = g_hash_table_lookup(handler->id_lookup, l->data); |
133 | |
134 | if (data != NULL((void*)0)) |
135 | { |
136 | if (data->func != NULL((void*)0)) |
137 | { |
138 | g_debug("CdmSignalHandler: running %d handler: %p", signum, data->func); |
139 | |
140 | res = data->func(signum, data->data); |
141 | |
142 | if (!res) |
143 | { |
144 | is_fatal = TRUE(!(0)); |
145 | } |
146 | } |
147 | } |
148 | } |
149 | } |
150 | |
151 | block_signals_pop(); |
152 | |
153 | if (is_fatal) |
154 | { |
155 | if (handler->fatal_func != NULL((void*)0)) |
156 | { |
157 | g_debug("CdmSignalHandler: Caught termination signal - calling fatal func"); |
158 | handler->fatal_func(handler->fatal_data); |
159 | } |
160 | else |
161 | { |
162 | g_debug("CdmSignalHandler: Caught termination signal - exiting"); |
163 | exit (1); |
164 | } |
165 | |
166 | return FALSE(0); |
167 | } |
168 | |
169 | g_debug("CdmSignalHandler: Done handling signals"); |
170 | |
171 | return TRUE(!(0)); |
172 | } |
173 | |
174 | static void fallback_get_backtrace(void) |
175 | { |
176 | #if HAVE_EXECINFO_H1 |
177 | void* frames[64]; |
178 | size_t size; |
179 | char** strings; |
180 | size_t i; |
181 | |
182 | size = backtrace(frames, G_N_ELEMENTS(frames)(sizeof (frames) / sizeof ((frames)[0]))); |
183 | |
184 | if ((strings = backtrace_symbols(frames, size))) |
185 | { |
186 | syslog(LOG_CRIT2, "******************* START ********************************"); |
187 | |
188 | for (i = 0; i < size; i++) |
189 | { |
190 | syslog(LOG_CRIT2, "Frame %zd: %s", i, strings[i]); |
191 | } |
192 | |
193 | free(strings); |
194 | syslog(LOG_CRIT2, "******************* END **********************************"); |
195 | } |
196 | else |
197 | { |
198 | #endif |
199 | g_warning ("CDM crashed, but symbols couldn't be retrieved."); |
200 | #if HAVE_EXECINFO_H1 |
201 | } |
202 | #endif |
203 | } |
204 | |
205 | static gboolean crashlogger_get_backtrace(void) |
206 | { |
207 | gboolean success = FALSE(0); |
208 | int pid; |
209 | |
210 | pid = fork(); |
211 | |
212 | if (pid > 0) |
213 | { |
214 | /* Wait for the child to finish */ |
215 | int estatus; |
216 | |
217 | if (waitpid(pid, &estatus, 0) != -1) |
218 | { |
219 | /* Only succeed if the crashlogger succeeded */ |
220 | if (WIFEXITED(estatus)(((estatus) & 0x7f) == 0) && (WEXITSTATUS(estatus)(((estatus) & 0xff00) >> 8) == 0)) |
221 | { |
222 | success = TRUE(!(0)); |
223 | } |
224 | } |
225 | } |
226 | else if (pid == 0) |
227 | { |
228 | /* Child process */ |
229 | execl(LIBEXECDIR"/usr/local/libexec" "/cdm-crash-logger", LIBEXECDIR"/usr/local/libexec" "/cdm-crash-logger", NULL((void*)0)); |
230 | } |
231 | |
232 | return success; |
233 | } |
234 | |
235 | |
236 | static void cdm_signal_handler_backtrace(void) |
237 | { |
238 | struct stat s; |
239 | gboolean fallback = TRUE(!(0)); |
240 | |
241 | /* Try to use gdb via cdm-crash-logger if it exists, since |
242 | * we get much better information out of it. Otherwise |
243 | * fall back to execinfo. |
244 | */ |
245 | if (g_statstat(LIBEXECDIR"/usr/local/libexec" "/cdm-crash-logger", &s) == 0) |
246 | { |
247 | fallback = crashlogger_get_backtrace() ? FALSE(0) : TRUE(!(0)); |
248 | } |
249 | |
250 | if (fallback) |
251 | { |
252 | fallback_get_backtrace(); |
253 | } |
254 | } |
255 | |
256 | static void signal_handler(int signo) |
257 | { |
258 | static int in_fatal = 0; |
259 | int UNUSED_VARIABLE__attribute__ ((unused)) ignore; |
260 | guchar signo_byte = signo; |
261 | |
262 | /* avoid loops */ |
263 | if (in_fatal > 0) |
264 | { |
265 | return; |
266 | } |
267 | |
268 | ++in_fatal; |
269 | |
270 | switch (signo) |
271 | { |
272 | case SIGSEGV11: |
273 | case SIGBUS7: |
274 | case SIGILL4: |
275 | case SIGABRT6: |
276 | case SIGTRAP5: |
277 | cdm_signal_handler_backtrace(); |
278 | exit(1); |
279 | break; |
This statement is never executed | |
280 | case SIGFPE8: |
281 | case SIGPIPE13: |
282 | /* let the fatal signals interrupt us */ |
283 | --in_fatal; |
284 | cdm_signal_handler_backtrace(); |
285 | ignore = write(signal_pipes [1], &signo_byte, 1); |
286 | break; |
287 | default: |
288 | --in_fatal; |
289 | ignore = write(signal_pipes [1], &signo_byte, 1); |
290 | break; |
291 | } |
292 | } |
293 | |
294 | static void catch_signal(CdmSignalHandler *handler, int signal_number) |
295 | { |
296 | struct sigaction action; |
297 | struct sigaction* old_action; |
298 | |
299 | g_debug("CdmSignalHandler: Registering for %d signals", signal_number); |
300 | |
301 | action.sa_handler__sigaction_handler.sa_handler = signal_handler; |
302 | sigemptyset(&action.sa_mask); |
303 | action.sa_flags = 0; |
304 | |
305 | old_action = g_new0(struct sigaction, 1)((struct sigaction *) g_malloc0_n ((1), sizeof (struct sigaction ))); |
306 | |
307 | sigaction(signal_number, &action, old_action); |
308 | |
309 | g_hash_table_insert(handler->action_lookup, GINT_TO_POINTER(signal_number)((gpointer) (glong) (signal_number)), old_action); |
310 | } |
311 | |
312 | static void uncatch_signal(CdmSignalHandler* handler, int signal_number) |
313 | { |
314 | struct sigaction* old_action; |
315 | |
316 | g_debug("CdmSignalHandler: Unregistering for %d signals", signal_number); |
317 | |
318 | old_action = g_hash_table_lookup(handler->action_lookup, GINT_TO_POINTER(signal_number)((gpointer) (glong) (signal_number))); |
319 | g_hash_table_remove(handler->action_lookup, GINT_TO_POINTER(signal_number)((gpointer) (glong) (signal_number))); |
320 | |
321 | sigaction(signal_number, old_action, NULL((void*)0)); |
322 | |
323 | g_free(old_action); |
324 | } |
325 | |
326 | guint cdm_signal_handler_add(CdmSignalHandler* handler, int signal_number, CdmSignalHandlerFunc callback, gpointer data) |
327 | { |
328 | CallbackData* cdata; |
329 | GSList* list; |
330 | |
331 | g_return_val_if_fail(CDM_IS_SIGNAL_HANDLER(handler), 0)do { if ((CDM_IS_SIGNAL_HANDLER(handler))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "CDM_IS_SIGNAL_HANDLER(handler)" ); return (0); } } while (0); |
332 | |
333 | cdata = g_new0(CallbackData, 1)((CallbackData *) g_malloc0_n ((1), sizeof (CallbackData))); |
334 | cdata->signal_number = signal_number; |
335 | cdata->func = callback; |
336 | cdata->data = data; |
337 | cdata->id = handler->next_id++; |
338 | |
339 | g_debug("CdmSignalHandler: Adding handler %u: signum=%d %p", cdata->id, cdata->signal_number, cdata->func); |
340 | |
341 | if (g_hash_table_lookup(handler->action_lookup, GINT_TO_POINTER(signal_number)((gpointer) (glong) (signal_number))) == NULL((void*)0)) |
342 | { |
343 | catch_signal(handler, signal_number); |
344 | } |
345 | |
346 | /* ID lookup owns the CallbackData */ |
347 | g_hash_table_insert(handler->id_lookup, GUINT_TO_POINTER(cdata->id)((gpointer) (gulong) (cdata->id)), cdata); |
348 | |
349 | list = g_hash_table_lookup(handler->lookup, GINT_TO_POINTER(signal_number)((gpointer) (glong) (signal_number))); |
350 | list = g_slist_prepend(list, GUINT_TO_POINTER (cdata->id)((gpointer) (gulong) (cdata->id))); |
351 | |
352 | g_hash_table_insert(handler->lookup, GINT_TO_POINTER(signal_number)((gpointer) (glong) (signal_number)), list); |
353 | |
354 | return cdata->id; |
355 | } |
356 | |
357 | void cdm_signal_handler_add_fatal(CdmSignalHandler* handler) |
358 | { |
359 | g_return_if_fail(CDM_IS_SIGNAL_HANDLER(handler))do { if ((CDM_IS_SIGNAL_HANDLER(handler))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "CDM_IS_SIGNAL_HANDLER(handler)" ); return; } } while (0); |
360 | |
361 | cdm_signal_handler_add(handler, SIGILL4, NULL((void*)0), NULL((void*)0)); |
362 | cdm_signal_handler_add(handler, SIGBUS7, NULL((void*)0), NULL((void*)0)); |
363 | cdm_signal_handler_add(handler, SIGSEGV11, NULL((void*)0), NULL((void*)0)); |
364 | cdm_signal_handler_add(handler, SIGABRT6, NULL((void*)0), NULL((void*)0)); |
365 | cdm_signal_handler_add(handler, SIGTRAP5, NULL((void*)0), NULL((void*)0)); |
366 | } |
367 | |
368 | static void callback_data_free(CallbackData* d) |
369 | { |
370 | g_free(d); |
371 | } |
372 | |
373 | static void cdm_signal_handler_remove_and_free_data(CdmSignalHandler* handler, CallbackData* cdata) |
374 | { |
375 | GSList* list; |
376 | |
377 | g_return_if_fail(CDM_IS_SIGNAL_HANDLER(handler))do { if ((CDM_IS_SIGNAL_HANDLER(handler))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "CDM_IS_SIGNAL_HANDLER(handler)" ); return; } } while (0); |
378 | |
379 | list = g_hash_table_lookup(handler->lookup, GINT_TO_POINTER(cdata->signal_number)((gpointer) (glong) (cdata->signal_number))); |
380 | list = g_slist_remove_all(list, GUINT_TO_POINTER(cdata->id)((gpointer) (gulong) (cdata->id))); |
381 | |
382 | if (list == NULL((void*)0)) |
383 | { |
384 | uncatch_signal(handler, cdata->signal_number); |
385 | } |
386 | |
387 | g_debug("CdmSignalHandler: Removing handler %u: signum=%d %p", cdata->signal_number, cdata->id, cdata->func); |
388 | /* put changed list back in */ |
389 | g_hash_table_insert(handler->lookup, GINT_TO_POINTER(cdata->signal_number)((gpointer) (glong) (cdata->signal_number)), list); |
390 | |
391 | g_hash_table_remove(handler->id_lookup, GUINT_TO_POINTER(cdata->id)((gpointer) (gulong) (cdata->id))); |
392 | } |
393 | |
394 | void cdm_signal_handler_remove(CdmSignalHandler* handler, guint id) |
395 | { |
396 | CallbackData* found; |
397 | |
398 | g_return_if_fail(CDM_IS_SIGNAL_HANDLER(handler))do { if ((CDM_IS_SIGNAL_HANDLER(handler))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "CDM_IS_SIGNAL_HANDLER(handler)" ); return; } } while (0); |
399 | |
400 | found = g_hash_table_lookup(handler->id_lookup, GUINT_TO_POINTER(id)((gpointer) (gulong) (id))); |
401 | |
402 | if (found != NULL((void*)0)) |
403 | { |
404 | cdm_signal_handler_remove_and_free_data(handler, found); |
405 | found = NULL((void*)0); |
406 | } |
407 | } |
408 | |
409 | static CallbackData* find_callback_data_by_func(CdmSignalHandler* handler, guint signal_number, CdmSignalHandlerFunc callback, gpointer data) |
410 | { |
411 | GSList* list; |
412 | GSList* l; |
413 | CallbackData* found; |
414 | |
415 | found = NULL((void*)0); |
416 | |
417 | list = g_hash_table_lookup(handler->lookup, GINT_TO_POINTER(signal_number)((gpointer) (glong) (signal_number))); |
418 | |
419 | for (l = list; l != NULL((void*)0); l = l->next) |
420 | { |
421 | guint id; |
422 | CallbackData* d; |
423 | |
424 | id = GPOINTER_TO_UINT(l->data)((guint) (gulong) (l->data)); |
425 | |
426 | d = g_hash_table_lookup(handler->id_lookup, GUINT_TO_POINTER (id)((gpointer) (gulong) (id))); |
427 | |
428 | if (d != NULL((void*)0) && d->func == callback && d->data == data) |
429 | { |
430 | found = d; |
431 | break; |
432 | } |
433 | } |
434 | |
435 | return found; |
436 | } |
437 | |
438 | void cdm_signal_handler_remove_func(CdmSignalHandler* handler, guint signal_number, CdmSignalHandlerFunc callback, gpointer data) |
439 | { |
440 | CallbackData* found; |
441 | |
442 | g_return_if_fail(CDM_IS_SIGNAL_HANDLER(handler))do { if ((CDM_IS_SIGNAL_HANDLER(handler))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "CDM_IS_SIGNAL_HANDLER(handler)" ); return; } } while (0); |
443 | |
444 | found = find_callback_data_by_func(handler, signal_number, callback, data); |
445 | |
446 | if (found != NULL((void*)0)) |
447 | { |
448 | cdm_signal_handler_remove_and_free_data(handler, found); |
449 | found = NULL((void*)0); |
450 | } |
451 | |
452 | /* FIXME: once all handlers are removed deregister signum handler */ |
453 | } |
454 | |
455 | static void cdm_signal_handler_class_init(CdmSignalHandlerClass* klass) |
456 | { |
457 | GObjectClass* object_class = G_OBJECT_CLASS(klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((klass)), (((GType) ((20) << (2)))))))); |
458 | |
459 | object_class->finalize = cdm_signal_handler_finalize; |
460 | } |
461 | |
462 | static void signal_list_free(GSList *list) |
463 | { |
464 | g_slist_free(list); |
465 | } |
466 | |
467 | void cdm_signal_handler_set_fatal_func(CdmSignalHandler* handler, CdmShutdownHandlerFunc func, gpointer user_data) |
468 | { |
469 | g_return_if_fail(CDM_IS_SIGNAL_HANDLER(handler))do { if ((CDM_IS_SIGNAL_HANDLER(handler))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "CDM_IS_SIGNAL_HANDLER(handler)" ); return; } } while (0); |
470 | |
471 | handler->fatal_func = func; |
472 | handler->fatal_data = user_data; |
473 | } |
474 | |
475 | static void cdm_signal_handler_init(CdmSignalHandler* handler) |
476 | { |
477 | GIOChannel* ioc; |
478 | |
479 | handler->next_id = 1; |
480 | |
481 | handler->lookup = g_hash_table_new(NULL((void*)0), NULL((void*)0)); |
482 | handler->id_lookup = g_hash_table_new(NULL((void*)0), NULL((void*)0)); |
483 | handler->action_lookup = g_hash_table_new(NULL((void*)0), NULL((void*)0)); |
484 | |
485 | if (pipe(signal_pipes) == -1) |
486 | { |
487 | g_error ("Could not create pipe() for signal handling"); |
488 | } |
489 | |
490 | ioc = g_io_channel_unix_new(signal_pipes[0]); |
491 | g_io_channel_set_flags(ioc, G_IO_FLAG_NONBLOCK, NULL((void*)0)); |
492 | g_io_add_watch_full(ioc, G_PRIORITY_HIGH-100, G_IO_IN, (GIOFunc) signal_io_watch, handler, NULL((void*)0)); |
493 | g_io_channel_set_close_on_unref(ioc, TRUE(!(0))); |
494 | g_io_channel_unref(ioc); |
495 | } |
496 | |
497 | static void cdm_signal_handler_finalize(GObject* object) |
498 | { |
499 | CdmSignalHandler* handler; |
500 | GList* l; |
501 | |
502 | g_return_if_fail(object != NULL)do { if ((object != ((void*)0))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "object != NULL") ; return; } } while (0); |
503 | g_return_if_fail(CDM_IS_SIGNAL_HANDLER(object))do { if ((CDM_IS_SIGNAL_HANDLER(object))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "CDM_IS_SIGNAL_HANDLER(object)" ); return; } } while (0); |
504 | |
505 | handler = CDM_SIGNAL_HANDLER(object); |
506 | |
507 | g_debug("CdmSignalHandler: Finalizing signal handler"); |
508 | |
509 | for (l = g_hash_table_get_values(handler->lookup); l != NULL((void*)0); l = l->next) |
510 | { |
511 | signal_list_free((GSList*) l->data); |
512 | } |
513 | |
514 | g_hash_table_destroy(handler->lookup); |
515 | |
516 | for (l = g_hash_table_get_values(handler->id_lookup); l != NULL((void*)0); l = l->next) |
517 | { |
518 | callback_data_free((CallbackData*) l->data); |
519 | } |
520 | |
521 | g_hash_table_destroy(handler->id_lookup); |
522 | |
523 | for (l = g_hash_table_get_values(handler->action_lookup); l != NULL((void*)0); l = l->next) |
524 | { |
525 | g_free(l->data); |
526 | } |
527 | |
528 | g_hash_table_destroy(handler->action_lookup); |
529 | |
530 | close(signal_pipes[0]); |
531 | close(signal_pipes[1]); |
532 | |
533 | G_OBJECT_CLASS(cdm_signal_handler_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((cdm_signal_handler_parent_class)), (((GType) ((20) << (2))))))))->finalize(object); |
534 | } |
535 | |
536 | CdmSignalHandler* cdm_signal_handler_new(void) |
537 | { |
538 | if (signal_handler_object != NULL((void*)0)) |
539 | { |
540 | g_object_ref(signal_handler_object)((__typeof__ (signal_handler_object)) (g_object_ref) (signal_handler_object )); |
541 | } |
542 | else |
543 | { |
544 | signal_handler_object = g_object_new(CDM_TYPE_SIGNAL_HANDLER(cdm_signal_handler_get_type()), NULL((void*)0)); |
545 | g_object_add_weak_pointer(signal_handler_object, (gpointer*) &signal_handler_object); |
546 | } |
547 | |
548 | return CDM_SIGNAL_HANDLER(signal_handler_object); |
549 | } |