9 #include "mainloop-signal.h"
14 struct sigaction saved_sigaction
;
15 void (*callback
) (void *id
, int signal
, void *userdata
);
17 struct signal_info
*previous
, *next
;
20 static struct pa_mainloop_api
*api
= NULL
;
21 static int signal_pipe
[2] = { -1, -1 };
22 static void* mainloop_source
= NULL
;
23 static struct signal_info
*signals
= NULL
;
25 static void signal_handler(int sig
) {
26 write(signal_pipe
[1], &sig
, sizeof(sig
));
29 static void callback(struct pa_mainloop_api
*a
, void *id
, int fd
, enum pa_mainloop_api_io_events events
, void *userdata
) {
30 assert(a
&& id
&& events
== PA_MAINLOOP_API_IO_EVENT_INPUT
&& id
== mainloop_source
&& fd
== signal_pipe
[0]);
37 if ((r
= read(signal_pipe
[0], &sig
, sizeof(sig
))) < 0) {
41 fprintf(stderr
, "signal.c: read(): %s\n", strerror(errno
));
45 if (r
!= sizeof(sig
)) {
46 fprintf(stderr
, "signal.c: short read()\n");
50 for (s
= signals
; s
; s
= s
->next
)
53 s
->callback(s
, sig
, s
->userdata
);
59 int pa_signal_init(struct pa_mainloop_api
*a
) {
61 if (pipe(signal_pipe
) < 0) {
62 fprintf(stderr
, "pipe() failed: %s\n", strerror(errno
));
66 make_nonblock_fd(signal_pipe
[0]);
67 make_nonblock_fd(signal_pipe
[1]);
70 mainloop_source
= api
->source_io(api
, signal_pipe
[0], PA_MAINLOOP_API_IO_EVENT_INPUT
, callback
, NULL
);
71 assert(mainloop_source
);
75 void pa_signal_done(void) {
76 assert(api
&& signal_pipe
[0] >= 0 && signal_pipe
[1] >= 0 && mainloop_source
);
78 api
->cancel_io(api
, mainloop_source
);
79 mainloop_source
= NULL
;
81 close(signal_pipe
[0]);
82 close(signal_pipe
[1]);
83 signal_pipe
[0] = signal_pipe
[1] = -1;
86 pa_signal_unregister(signals
);
91 void* pa_signal_register(int sig
, void (*callback
) (void *id
, int signal
, void *userdata
), void *userdata
) {
92 struct signal_info
*s
= NULL
;
94 assert(sig
> 0 && callback
);
96 for (s
= signals
; s
; s
= s
->next
)
100 s
= malloc(sizeof(struct signal_info
));
103 s
->callback
= callback
;
104 s
->userdata
= userdata
;
106 memset(&sa
, 0, sizeof(sa
));
107 sa
.sa_handler
= signal_handler
;
108 sigemptyset(&sa
.sa_mask
);
109 sa
.sa_flags
= SA_RESTART
;
111 if (sigaction(sig
, &sa
, &s
->saved_sigaction
) < 0)
125 void pa_signal_unregister(void *id
) {
126 struct signal_info
*s
= id
;
130 s
->next
->previous
= s
->previous
;
132 s
->previous
->next
= s
->next
;
136 sigaction(s
->sig
, &s
->saved_sigaction
, NULL
);