Line data Source code
1 : // Copyright (c) 2012-2021 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/eventdispatcher
4 : // contact@m2osw.com
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 : /** \file
21 : * \brief Implementation of the Signal Profiler class.
22 : *
23 : * The Signal Profiler class is at attempt to implement the SIGPROF without
24 : * stopping system functions such as poll(). At this point, this doesn't
25 : * work.
26 : *
27 : * To test with the profiler, use the `-pg` command line option on your g++
28 : * command line. See the g++ docs for more info.
29 : */
30 :
31 : // self
32 : //
33 : #include "eventdispatcher/signal_profiler.h"
34 :
35 :
36 : // C lib
37 : //
38 : #include <ucontext.h>
39 :
40 :
41 : // last include
42 : //
43 : #include <snapdev/poison.h>
44 :
45 :
46 :
47 : namespace ed
48 : {
49 :
50 : /** \brief Initialize the profiler signal objects.
51 : *
52 : * This constructor sets up the signal within the event dispatcher
53 : * environment and then it retrieves the pointer to the gcc SIGPROF
54 : * function which is used to collect the necessary data.
55 : *
56 : * \todo
57 : * Make this whole thing work. It is very likely that the stack trace
58 : * is going to be wrong if the handler doesn't use the newer scheme
59 : * (i.e. the one where the context gets saved at the time the event
60 : * occurs and not at the time we're handling it here). At the moment,
61 : * Linux does it properly, so no worries here. That being said, so
62 : * far I've not been able to make it work properly.
63 : */
64 0 : signal_profiler::signal_profiler()
65 0 : : signal(SIGPROF)
66 : {
67 : // retrieve the handler so we can call it whenever the signal occurs
68 : //
69 0 : sigaction(SIGPROF, nullptr, &f_action);
70 0 : }
71 :
72 0 : void signal_profiler::process_signal()
73 : {
74 0 : if((f_action.sa_flags & SA_SIGINFO) != 0)
75 : {
76 0 : if(f_action.sa_handler != SIG_IGN
77 0 : && f_action.sa_handler != SIG_DFL
78 0 : && f_action.sa_handler != nullptr)
79 : {
80 0 : (*f_action.sa_handler)(SIGPROF);
81 : }
82 : }
83 : else
84 : {
85 0 : if(f_action.sa_sigaction != nullptr)
86 : {
87 0 : signalfd_siginfo const * fdinfo(get_signal_info());
88 0 : siginfo_t info = siginfo_t();
89 0 : info.si_signo = fdinfo->ssi_signo;
90 0 : info.si_errno = fdinfo->ssi_errno;
91 0 : info.si_code = fdinfo->ssi_code;
92 : //info.si_trapno = fdinfo->ssi_trapno; // not defined on all machines
93 0 : info.si_pid = fdinfo->ssi_pid;
94 0 : info.si_uid = fdinfo->ssi_uid;
95 0 : info.si_status = fdinfo->ssi_status;
96 0 : info.si_utime = fdinfo->ssi_utime;
97 0 : info.si_stime = fdinfo->ssi_stime;
98 0 : info.si_value.sival_int = 0;
99 0 : info.si_int = fdinfo->ssi_int;
100 0 : info.si_ptr = reinterpret_cast<void *>(fdinfo->ssi_ptr);
101 0 : info.si_overrun = fdinfo->ssi_overrun;
102 0 : info.si_timerid = 0;
103 0 : info.si_addr = reinterpret_cast<void *>(fdinfo->ssi_addr);
104 0 : info.si_band = fdinfo->ssi_band;
105 0 : info.si_fd = fdinfo->ssi_fd;
106 0 : info.si_addr_lsb = 0; //fdinfo->ssi_addr_lsb; // not on arch64 and doesn't help at this point
107 :
108 : // the following fields don't exist in 16.04, keep commented until we stop support
109 : //info.si_lower = 0;
110 : //info.si_upper = 0;
111 : //info.si_pkey = 0;
112 :
113 0 : info.si_call_addr = 0;
114 0 : info.si_syscall = 0;
115 0 : info.si_arch = 0;
116 :
117 0 : ucontext_t uc;
118 0 : getcontext(&uc);
119 :
120 0 : (*f_action.sa_sigaction)(SIGPROF, &info, &uc);
121 : }
122 : }
123 0 : }
124 :
125 :
126 : } // namespace ed
127 : // vim: ts=4 sw=4 et
|