Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / global / signal_handler.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4  * Ceph - scalable distributed file system
5  *
6  * Copyright (C) 2011 New Dream Network
7  *
8  * This is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License version 2.1, as published by the Free Software
11  * Foundation.  See file COPYING.
12  *
13  */
14
15 #include "include/compat.h"
16 #include "pthread.h"
17
18 #include "common/BackTrace.h"
19 #include "common/debug.h"
20 #include "global/pidfile.h"
21 #include "global/signal_handler.h"
22
23 #include <poll.h>
24 #include <signal.h>
25 #include <sstream>
26 #include <stdlib.h>
27 #include <sys/stat.h>
28 #include <sys/types.h>
29 #include "common/errno.h"
30 #if defined(_AIX)
31 extern char *sys_siglist[]; 
32 #endif 
33
34 #define dout_context g_ceph_context
35
36 void install_sighandler(int signum, signal_handler_t handler, int flags)
37 {
38   int ret;
39   struct sigaction oldact;
40   struct sigaction act;
41   memset(&act, 0, sizeof(act));
42
43   act.sa_handler = handler;
44   sigemptyset(&act.sa_mask);
45   act.sa_flags = flags;
46
47   ret = sigaction(signum, &act, &oldact);
48   if (ret != 0) {
49     char buf[1024];
50 #if defined(__sun)
51     char message[SIG2STR_MAX];
52     sig2str(signum,message);
53     snprintf(buf, sizeof(buf), "install_sighandler: sigaction returned "
54             "%d when trying to install a signal handler for %s\n",
55              ret, message);
56 #else
57     snprintf(buf, sizeof(buf), "install_sighandler: sigaction returned "
58             "%d when trying to install a signal handler for %s\n",
59              ret, sig_str(signum));
60 #endif
61     dout_emergency(buf);
62     exit(1);
63   }
64 }
65
66 void sighup_handler(int signum)
67 {
68   g_ceph_context->reopen_logs();
69 }
70
71 static void reraise_fatal(int signum)
72 {
73   // Use default handler to dump core
74   int ret = raise(signum);
75
76   // Normally, we won't get here. If we do, something is very weird.
77   char buf[1024];
78   if (ret) {
79     snprintf(buf, sizeof(buf), "reraise_fatal: failed to re-raise "
80             "signal %d\n", signum);
81     dout_emergency(buf);
82   }
83   else {
84     snprintf(buf, sizeof(buf), "reraise_fatal: default handler for "
85             "signal %d didn't terminate the process?\n", signum);
86     dout_emergency(buf);
87   }
88   exit(1);
89 }
90
91 static void handle_fatal_signal(int signum)
92 {
93   // This code may itself trigger a SIGSEGV if the heap is corrupt. In that
94   // case, SA_RESETHAND specifies that the default signal handler--
95   // presumably dump core-- will handle it.
96   char buf[1024];
97   char pthread_name[16] = {0}; //limited by 16B include terminating null byte.
98   int r = ceph_pthread_getname(pthread_self(), pthread_name, sizeof(pthread_name));
99   (void)r;
100 #if defined(__sun)
101   char message[SIG2STR_MAX];
102   sig2str(signum,message);
103   snprintf(buf, sizeof(buf), "*** Caught signal (%s) **\n "
104             "in thread %llx thread_name:%s\n", message, (unsigned long long)pthread_self(),
105             pthread_name);
106 #else
107   snprintf(buf, sizeof(buf), "*** Caught signal (%s) **\n "
108             "in thread %llx thread_name:%s\n", sig_str(signum), (unsigned long long)pthread_self(),
109             pthread_name);
110 #endif
111   dout_emergency(buf);
112   pidfile_remove();
113
114   // TODO: don't use an ostringstream here. It could call malloc(), which we
115   // don't want inside a signal handler.
116   // Also fix the backtrace code not to allocate memory.
117   BackTrace bt(0);
118   ostringstream oss;
119   bt.print(oss);
120   dout_emergency(oss.str());
121
122   // avoid recursion back into logging code if that is where
123   // we got the SEGV.
124   if (g_ceph_context &&
125       g_ceph_context->_log &&
126       !g_ceph_context->_log->is_inside_log_lock()) {
127     // dump to log.  this uses the heap extensively, but we're better
128     // off trying than not.
129     derr << buf << std::endl;
130     bt.print(*_dout);
131     *_dout << " NOTE: a copy of the executable, or `objdump -rdS <executable>` "
132            << "is needed to interpret this.\n"
133            << dendl;
134
135     g_ceph_context->_log->dump_recent();
136   }
137
138   reraise_fatal(signum);
139 }
140
141 void install_standard_sighandlers(void)
142 {
143   install_sighandler(SIGSEGV, handle_fatal_signal, SA_RESETHAND | SA_NODEFER);
144   install_sighandler(SIGABRT, handle_fatal_signal, SA_RESETHAND | SA_NODEFER);
145   install_sighandler(SIGBUS, handle_fatal_signal, SA_RESETHAND | SA_NODEFER);
146   install_sighandler(SIGILL, handle_fatal_signal, SA_RESETHAND | SA_NODEFER);
147   install_sighandler(SIGFPE, handle_fatal_signal, SA_RESETHAND | SA_NODEFER);
148   install_sighandler(SIGXCPU, handle_fatal_signal, SA_RESETHAND | SA_NODEFER);
149   install_sighandler(SIGXFSZ, handle_fatal_signal, SA_RESETHAND | SA_NODEFER);
150   install_sighandler(SIGSYS, handle_fatal_signal, SA_RESETHAND | SA_NODEFER);
151 }
152
153
154
155 /// --- safe handler ---
156
157 #include "common/Thread.h"
158 #include <errno.h>
159
160 string get_name_by_pid(pid_t pid)
161 {
162   char proc_pid_path[PATH_MAX] = {0};
163   snprintf(proc_pid_path, PATH_MAX, PROCPREFIX "/proc/%d/cmdline", pid);
164   int fd = open(proc_pid_path, O_RDONLY);
165
166   if (fd < 0) {
167     fd = -errno;
168     derr << "Fail to open '" << proc_pid_path 
169          << "' error = " << cpp_strerror(fd) 
170          << dendl;
171     return "<unknown>";
172   }
173   // assuming the cmdline length does not exceed PATH_MAX. if it
174   // really does, it's fine to return a truncated version.
175   char buf[PATH_MAX] = {0};
176   int ret = read(fd, buf, sizeof(buf));
177   close(fd);
178   if (ret < 0) {
179     ret = -errno;
180     derr << "Fail to read '" << proc_pid_path
181          << "' error = " << cpp_strerror(ret)
182          << dendl;
183     return "<unknown>";
184   }
185   std::replace(buf, buf + ret, '\0', ' ');
186   return string(buf, ret);
187 }
188
189  
190 /**
191  * safe async signal handler / dispatcher
192  *
193  * This is an async unix signal handler based on the design from
194  *
195  *  http://evbergen.home.xs4all.nl/unix-signals.html
196  *
197  * Features:
198  *   - no unsafe work is done in the signal handler itself
199  *   - callbacks are called from a regular thread
200  *   - signals are not lost, unless multiple instances of the same signal
201  *     are sent twice in quick succession.
202  */
203 struct SignalHandler : public Thread {
204   /// to kick the thread, for shutdown, new handlers, etc.
205   int pipefd[2];  // write to [1], read from [0]
206
207   /// to signal shutdown
208   bool stop;
209
210   /// for an individual signal
211   struct safe_handler {
212
213     safe_handler() {
214       memset(pipefd, 0, sizeof(pipefd));
215       memset(&handler, 0, sizeof(handler));
216       memset(&info_t, 0, sizeof(info_t));    
217     }
218
219     siginfo_t info_t;
220     int pipefd[2];  // write to [1], read from [0]
221     signal_handler_t handler;
222   };
223
224   /// all handlers
225   safe_handler *handlers[32] = {nullptr};
226
227   /// to protect the handlers array
228   Mutex lock;
229
230   SignalHandler()
231     : stop(false), lock("SignalHandler::lock")
232   {
233     // create signal pipe
234     int r = pipe(pipefd);
235     assert(r == 0);
236     r = fcntl(pipefd[0], F_SETFL, O_NONBLOCK);
237     assert(r == 0);
238
239     // create thread
240     create("signal_handler");
241   }
242
243   ~SignalHandler() override {
244     shutdown();
245   }
246
247   void signal_thread() {
248     int r = write(pipefd[1], "\0", 1);
249     assert(r == 1);
250   }
251
252   void shutdown() {
253     stop = true;
254     signal_thread();
255     join();
256   }
257
258   // thread entry point
259   void *entry() override {
260     while (!stop) {
261       // build fd list
262       struct pollfd fds[33];
263
264       lock.Lock();
265       int num_fds = 0;
266       fds[num_fds].fd = pipefd[0];
267       fds[num_fds].events = POLLIN | POLLERR;
268       fds[num_fds].revents = 0;
269       ++num_fds;
270       for (unsigned i=0; i<32; i++) {
271         if (handlers[i]) {
272           fds[num_fds].fd = handlers[i]->pipefd[0];
273           fds[num_fds].events = POLLIN | POLLERR;
274           fds[num_fds].revents = 0;
275           ++num_fds;
276         }
277       }
278       lock.Unlock();
279
280       // wait for data on any of those pipes
281       int r = poll(fds, num_fds, -1);
282       if (stop)
283         break;
284       if (r > 0) {
285         char v;
286
287         // consume byte from signal socket, if any.
288         TEMP_FAILURE_RETRY(read(pipefd[0], &v, 1));
289
290         lock.Lock();
291         for (unsigned signum=0; signum<32; signum++) {
292           if (handlers[signum]) {
293             r = read(handlers[signum]->pipefd[0], &v, 1);
294             if (r == 1) {
295               siginfo_t * siginfo = &handlers[signum]->info_t;
296               string task_name = get_name_by_pid(siginfo->si_pid);
297               derr << "received  signal: " << sig_str(signum)
298                    << " from " << " PID: " << siginfo->si_pid
299                    << " task name: " << task_name
300                    << " UID: " << siginfo->si_uid
301                    << dendl;
302               handlers[signum]->handler(signum);
303             }
304           }
305         }
306         lock.Unlock();
307       } 
308     }
309     return NULL;
310   }
311
312   void queue_signal(int signum) {
313     // If this signal handler is registered, the callback must be
314     // defined.  We can do this without the lock because we will never
315     // have the signal handler defined without the handlers entry also
316     // being filled in.
317     assert(handlers[signum]);
318     int r = write(handlers[signum]->pipefd[1], " ", 1);
319     assert(r == 1);
320   }
321
322   void queue_signal_info(int signum, siginfo_t *siginfo, void * content) {
323     // If this signal handler is registered, the callback must be
324     // defined.  We can do this without the lock because we will never
325     // have the signal handler defined without the handlers entry also
326     // being filled in.
327     assert(handlers[signum]);
328     memcpy(&handlers[signum]->info_t, siginfo, sizeof(siginfo_t));
329     int r = write(handlers[signum]->pipefd[1], " ", 1);
330     assert(r == 1);
331   }
332
333   void register_handler(int signum, signal_handler_t handler, bool oneshot);
334   void unregister_handler(int signum, signal_handler_t handler);
335 };
336
337 static SignalHandler *g_signal_handler = NULL;
338
339 static void handler_signal_hook(int signum, siginfo_t * siginfo, void * content) {
340   g_signal_handler->queue_signal_info(signum, siginfo, content);
341 }
342
343 void SignalHandler::register_handler(int signum, signal_handler_t handler, bool oneshot)
344 {
345   int r;
346
347   assert(signum >= 0 && signum < 32);
348
349   safe_handler *h = new safe_handler;
350
351   r = pipe(h->pipefd);
352   assert(r == 0);
353   r = fcntl(h->pipefd[0], F_SETFL, O_NONBLOCK);
354   assert(r == 0);
355
356   h->handler = handler;
357   lock.Lock();
358   handlers[signum] = h;
359   lock.Unlock();
360
361   // signal thread so that it sees our new handler
362   signal_thread();
363   
364   // install our handler
365   struct sigaction oldact;
366   struct sigaction act;
367   memset(&act, 0, sizeof(act));
368
369   act.sa_handler = (signal_handler_t)handler_signal_hook;
370   sigfillset(&act.sa_mask);  // mask all signals in the handler
371   act.sa_flags = SA_SIGINFO | (oneshot ? SA_RESETHAND : 0);
372   int ret = sigaction(signum, &act, &oldact);
373   assert(ret == 0);
374 }
375
376 void SignalHandler::unregister_handler(int signum, signal_handler_t handler)
377 {
378   assert(signum >= 0 && signum < 32);
379   safe_handler *h = handlers[signum];
380   assert(h);
381   assert(h->handler == handler);
382
383   // restore to default
384   signal(signum, SIG_DFL);
385
386   // _then_ remove our handlers entry
387   lock.Lock();
388   handlers[signum] = NULL;
389   lock.Unlock();
390
391   // this will wake up select() so that worker thread sees our handler is gone
392   close(h->pipefd[0]);
393   close(h->pipefd[1]);
394   delete h;
395 }
396
397
398 // -------
399
400 void init_async_signal_handler()
401 {
402   assert(!g_signal_handler);
403   g_signal_handler = new SignalHandler;
404 }
405
406 void shutdown_async_signal_handler()
407 {
408   assert(g_signal_handler);
409   delete g_signal_handler;
410   g_signal_handler = NULL;
411 }
412
413 void queue_async_signal(int signum)
414 {
415   assert(g_signal_handler);
416   g_signal_handler->queue_signal(signum);
417 }
418
419 void register_async_signal_handler(int signum, signal_handler_t handler)
420 {
421   assert(g_signal_handler);
422   g_signal_handler->register_handler(signum, handler, false);
423 }
424
425 void register_async_signal_handler_oneshot(int signum, signal_handler_t handler)
426 {
427   assert(g_signal_handler);
428   g_signal_handler->register_handler(signum, handler, true);
429 }
430
431 void unregister_async_signal_handler(int signum, signal_handler_t handler)
432 {
433   assert(g_signal_handler);
434   g_signal_handler->unregister_handler(signum, handler);
435 }
436
437
438