Bug Summary

File:cafe-session/cdm-signal-handler.c
Warning:line 279, column 4
This statement is never executed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name cdm-signal-handler.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/rootdir/cafe-session -resource-dir /usr/lib/llvm-16/lib/clang/16 -D HAVE_CONFIG_H -I . -I .. -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/ctk-3.0 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I ../egg -D LOCALE_DIR="/usr/local/share/locale" -D DATA_DIR="/usr/local/share/cafe-session" -D LIBEXECDIR="/usr/local/libexec" -D CTKBUILDER_DIR="/usr/local/share/cafe-session-manager" -D I_KNOW_THE_DEVICEKIT_POWER_API_IS_SUBJECT_TO_CHANGE -internal-isystem /usr/lib/llvm-16/lib/clang/16/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdebug-compilation-dir=/rootdir/cafe-session -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-checker deadcode.DeadStores -analyzer-checker alpha.deadcode.UnreachableCode -analyzer-checker alpha.core.CastSize -analyzer-checker alpha.core.CastToStruct -analyzer-checker alpha.core.IdenticalExpr -analyzer-checker alpha.core.SizeofPtr -analyzer-checker alpha.security.ArrayBoundV2 -analyzer-checker alpha.security.MallocOverflow -analyzer-checker alpha.security.ReturnPtrRange -analyzer-checker alpha.unix.SimpleStream -analyzer-checker alpha.unix.cstring.BufferOverlap -analyzer-checker alpha.unix.cstring.NotNullTerminated -analyzer-checker alpha.unix.cstring.OutOfBounds -analyzer-checker alpha.core.FixedAddr -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /rootdir/html-report/2023-12-13-192738-18718-1 -x c cdm-signal-handler.c
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
50typedef struct {
51 int signal_number;
52 CdmSignalHandlerFunc func;
53 gpointer data;
54 guint id;
55} CallbackData;
56
57struct _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
67static void cdm_signal_handler_finalize (GObject* object);
68
69static gpointer signal_handler_object = NULL((void*)0);
70static int signal_pipes[2];
71static int signals_blocked = 0;
72static sigset_t signals_block_mask;
73static sigset_t signals_oldmask;
74
75G_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
77static 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
90static 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
101static 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
174static 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
205static 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
236static 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
256static 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
294static 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
312static 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
326guint 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
357void 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
368static void callback_data_free(CallbackData* d)
369{
370 g_free(d);
371}
372
373static 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
394void 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
409static 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
438void 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
455static 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
462static void signal_list_free(GSList *list)
463{
464 g_slist_free(list);
465}
466
467void 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
475static 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
497static 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
536CdmSignalHandler* 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}