usb_moded  0.86.0+mer57
usb_moded-sigpipe.c
Go to the documentation of this file.
1 
24 #include "usb_moded-sigpipe.h"
25 
26 #include "usb_moded.h"
27 #include "usb_moded-log.h"
28 
29 #include <unistd.h>
30 #include <fcntl.h>
31 
32 /* ========================================================================= *
33  * Prototypes
34  * ========================================================================= */
35 
36 /* ------------------------------------------------------------------------- *
37  * SIGPIPE
38  * ------------------------------------------------------------------------- */
39 
40 static gboolean sigpipe_read_signal_cb(GIOChannel *channel, GIOCondition condition, gpointer data);
41 static void sigpipe_trap_signal_cb(int sig);
42 static bool sigpipe_crate_pipe (void);
43 static void sigpipe_trap_signals (void);
44 bool sigpipe_init (void);
45 
46 /* ========================================================================= *
47  * Data
48  * ========================================================================= */
49 
51 static int sigpipe_fd = -1;
52 
61 static gboolean
62 sigpipe_read_signal_cb(GIOChannel *channel,
63  GIOCondition condition,
64  gpointer data)
65 {
66  LOG_REGISTER_CONTEXT;
67 
68  gboolean keep_watch = FALSE;
69 
70  int fd, rc, sig;
71 
72  (void)data;
73 
74  /* Should never happen, but we must disable the io watch
75  * if the pipe fd still goes into unexpected state ... */
76  if( condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL) )
77  goto EXIT;
78 
79  if( (fd = g_io_channel_unix_get_fd(channel)) == -1 )
80  goto EXIT;
81 
82  /* If the actual read fails, terminate with core dump */
83  rc = TEMP_FAILURE_RETRY(read(fd, &sig, sizeof sig));
84  if( rc != (int)sizeof sig )
85  abort();
86 
87  /* handle the signal */
88  usbmoded_handle_signal(sig);
89 
90  keep_watch = TRUE;
91 
92 EXIT:
93  if( !keep_watch )
94  log_crit("disabled signal handler io watch\n");
95 
96  return keep_watch;
97 }
98 
103 static void
104 sigpipe_trap_signal_cb(int sig)
105 {
106  LOG_REGISTER_CONTEXT;
107 
108  /* NOTE: This function *MUST* be kept async-signal-safe! */
109 
110  static volatile int exit_tries = 0;
111 
112  int rc;
113 
114  /* Restore signal handler */
115  signal(sig, sigpipe_trap_signal_cb);
116 
117  switch( sig )
118  {
119  case SIGINT:
120  case SIGQUIT:
121  case SIGTERM:
122  /* If we receive multiple signals that should have
123  * caused the process to exit, assume that mainloop
124  * is stuck and terminate with core dump. */
125  if( ++exit_tries >= 2 )
126  abort();
127  break;
128 
129  default:
130  break;
131  }
132 
133  /* Transfer the signal to mainloop via pipe ... */
134  rc = TEMP_FAILURE_RETRY(write(sigpipe_fd, &sig, sizeof sig));
135 
136  /* ... or terminate with core dump in case of failures */
137  if( rc != (int)sizeof sig )
138  abort();
139 }
140 
145 static bool
146 sigpipe_crate_pipe(void)
147 {
148  LOG_REGISTER_CONTEXT;
149 
150  bool res = false;
151  GIOChannel *chn = 0;
152  int pfd[2] = { -1, -1 };
153 
154  if( pipe2(pfd, O_CLOEXEC) == -1 )
155  goto EXIT;
156 
157  if( (chn = g_io_channel_unix_new(pfd[0])) == 0 )
158  goto EXIT;
159 
160  if( !g_io_add_watch(chn, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
161  sigpipe_read_signal_cb, 0) )
162  goto EXIT;
163 
164  g_io_channel_set_close_on_unref(chn, true), pfd[0] = -1;
165  sigpipe_fd = pfd[1], pfd[1] = -1;
166 
167  res = true;
168 
169 EXIT:
170  if( chn ) g_io_channel_unref(chn);
171  if( pfd[0] != -1 ) close(pfd[0]);
172  if( pfd[1] != -1 ) close(pfd[1]);
173 
174  return res;
175 }
176 
179 static void
180 sigpipe_trap_signals(void)
181 {
182  LOG_REGISTER_CONTEXT;
183 
184  static const int sig[] =
185  {
186  SIGINT,
187  SIGQUIT,
188  SIGTERM,
189  SIGHUP,
190  -1
191  };
192 
193  for( size_t i = 0; sig[i] != -1; ++i )
194  {
195  signal(sig[i], sigpipe_trap_signal_cb);
196  }
197 }
198 
203 bool
205 {
206  LOG_REGISTER_CONTEXT;
207 
208  bool success = false;
209 
210  if( !sigpipe_crate_pipe() )
211  goto EXIT;
212 
213  sigpipe_trap_signals();
214 
215  success = true;
216 
217 EXIT:
218  return success;
219 }
usb_moded-sigpipe.h
sigpipe_init
bool sigpipe_init(void)
Definition: usb_moded-sigpipe.c:204
usb_moded.h
usb_moded-log.h