1 /* Copyright (c) 2011, 2021, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23 #include "my_global.h"
24 #include <signal.h>
25
26 #include "sys_vars.h"
27 #include "my_stacktrace.h"
28 #include "connection_handler_manager.h" // Connection_handler_manager
29 #include "mysqld_thd_manager.h" // Global_THD_manager
30 #include "sql_class.h"
31
32 #ifdef _WIN32
33 #include <crtdbg.h>
34 #define SIGNAL_FMT "exception 0x%x"
35 #else
36 #define SIGNAL_FMT "signal %d"
37 #endif
38
39 /*
40 We are handling signals in this file.
41 Any global variables we read should be 'volatile sig_atomic_t'
42 to guarantee that we read some consistent value.
43 */
44 static volatile sig_atomic_t segfaulted= 0;
45 extern volatile sig_atomic_t calling_initgroups;
46
47 /**
48 * Handler for fatal signals
49 *
50 * Fatal events (seg.fault, bus error etc.) will trigger
51 * this signal handler. The handler will try to dump relevant
52 * debugging information to stderr and dump a core image.
53 *
54 * Signal handlers can only use a set of 'safe' system calls
55 * and library functions. A list of safe calls in POSIX systems
56 * are available at:
57 * http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html
58 * For MS Windows, guidelines are available at:
59 * http://msdn.microsoft.com/en-us/library/xdkz3x12(v=vs.71).aspx
60 *
61 * @param sig Signal number
62 */
handle_fatal_signal(int sig)63 extern "C" void handle_fatal_signal(int sig)
64 {
65 if (segfaulted)
66 {
67 my_safe_printf_stderr("Fatal " SIGNAL_FMT " while backtracing\n", sig);
68 _exit(MYSQLD_FAILURE_EXIT); /* Quit without running destructors */
69 }
70
71 segfaulted = 1;
72
73 #ifdef _WIN32
74 SYSTEMTIME utc_time;
75 GetSystemTime(&utc_time);
76 const long hrs= utc_time.wHour;
77 const long mins= utc_time.wMinute;
78 const long secs= utc_time.wSecond;
79 #else
80 /* Using time() instead of my_time() to avoid looping */
81 const time_t curr_time= time(NULL);
82 /* Calculate time of day */
83 const long tmins = curr_time / 60;
84 const long thrs = tmins / 60;
85 const long hrs = thrs % 24;
86 const long mins = tmins % 60;
87 const long secs = curr_time % 60;
88 #endif
89
90 char hrs_buf[3]= "00";
91 char mins_buf[3]= "00";
92 char secs_buf[3]= "00";
93 my_safe_itoa(10, hrs, &hrs_buf[2]);
94 my_safe_itoa(10, mins, &mins_buf[2]);
95 my_safe_itoa(10, secs, &secs_buf[2]);
96
97 my_safe_printf_stderr("%s:%s:%s UTC - mysqld got " SIGNAL_FMT " ;\n",
98 hrs_buf, mins_buf, secs_buf, sig);
99
100 my_safe_printf_stderr("%s",
101 "This could be because you hit a bug. It is also possible that this binary\n"
102 "or one of the libraries it was linked against is corrupt, improperly built,\n"
103 "or misconfigured. This error can also be caused by malfunctioning hardware.\n");
104
105 my_safe_printf_stderr("%s",
106 "Attempting to collect some information that could help diagnose the problem.\n"
107 "As this is a crash and something is definitely wrong, the information\n"
108 "collection process might fail.\n"
109 "Please help us make Percona Server better by reporting any\n"
110 "bugs at https://bugs.percona.com/\n\n");
111
112 my_safe_printf_stderr("key_buffer_size=%lu\n",
113 (ulong) dflt_key_cache->key_cache_mem_size);
114
115 my_safe_printf_stderr("read_buffer_size=%ld\n",
116 (long) global_system_variables.read_buff_size);
117
118 my_safe_printf_stderr("max_used_connections=%lu\n",
119 Connection_handler_manager::max_used_connections);
120
121 uint max_threads= 1;
122 #ifndef EMBEDDED_LIBRARY
123 max_threads= Connection_handler_manager::max_threads;
124 #endif
125 my_safe_printf_stderr("max_threads=%u\n", max_threads +
126 (uint) extra_max_connections);
127
128 my_safe_printf_stderr("thread_count=%u\n", Global_THD_manager::global_thd_count);
129
130 my_safe_printf_stderr("connection_count=%u\n",
131 Connection_handler_manager::connection_count);
132
133 my_safe_printf_stderr("It is possible that mysqld could use up to \n"
134 "key_buffer_size + "
135 "(read_buffer_size + sort_buffer_size)*max_threads = "
136 "%lu K bytes of memory\n",
137 (ulong)(dflt_key_cache->key_cache_mem_size +
138 (global_system_variables.read_buff_size +
139 global_system_variables.sortbuff_size) *
140 max_threads +
141 (max_connections + extra_max_connections) * sizeof(THD)) / 1024);
142
143 my_safe_printf_stderr("%s",
144 "Hope that's ok; if not, decrease some variables in the equation.\n\n");
145
146 my_safe_printf_stderr("\n");
147 #ifdef __linux__
148 my_print_buildID();
149 #endif
150 my_safe_printf_stderr("Server Version: %s %s\n\n", server_version,
151 MYSQL_COMPILATION_COMMENT);
152
153 #ifdef HAVE_STACKTRACE
154 THD *thd= my_thread_get_THR_THD();
155
156 if (!(test_flags & TEST_NO_STACKTRACE))
157 {
158 my_safe_printf_stderr("Thread pointer: 0x%p\n", thd);
159 my_safe_printf_stderr("%s",
160 "Attempting backtrace. You can use the following "
161 "information to find out\n"
162 "where mysqld died. If you see no messages after this, something went\n"
163 "terribly wrong...\n");
164 my_print_stacktrace(thd ? (uchar*) thd->thread_stack : NULL,
165 my_thread_stack_size);
166 }
167 if (thd)
168 {
169 const char *kreason= "UNKNOWN";
170 switch (thd->killed) {
171 case THD::NOT_KILLED:
172 kreason= "NOT_KILLED";
173 break;
174 case THD::KILL_BAD_DATA:
175 kreason= "KILL_BAD_DATA";
176 break;
177 case THD::KILL_CONNECTION:
178 kreason= "KILL_CONNECTION";
179 break;
180 case THD::KILL_QUERY:
181 kreason= "KILL_QUERY";
182 break;
183 case THD::KILL_TIMEOUT:
184 kreason= "KILL_TIMEOUT";
185 break;
186 case THD::KILLED_NO_VALUE:
187 kreason= "KILLED_NO_VALUE";
188 break;
189 }
190 my_safe_printf_stderr("%s", "\n"
191 "Trying to get some variables.\n"
192 "Some pointers may be invalid and cause the dump to abort.\n");
193
194 my_safe_printf_stderr("Query (%p): ", thd->query().str);
195 my_safe_puts_stderr(thd->query().str, MY_MIN(1024U, thd->query().length));
196 my_safe_printf_stderr("Connection ID (thread ID): %u\n",
197 thd->thread_id());
198 my_safe_printf_stderr("Status: %s\n\n", kreason);
199 }
200 my_safe_printf_stderr("%s",
201 "You may download the Percona Server operations manual by visiting\n"
202 "http://www.percona.com/software/percona-server/. You may find information\n"
203 "in the manual which will help you identify the cause of the crash.\n");
204
205 #endif /* HAVE_STACKTRACE */
206
207 #ifdef HAVE_INITGROUPS
208 if (calling_initgroups)
209 {
210 my_safe_printf_stderr("%s", "\n"
211 "This crash occured while the server was calling initgroups(). This is\n"
212 "often due to the use of a mysqld that is statically linked against \n"
213 "glibc and configured to use LDAP in /etc/nsswitch.conf.\n"
214 "You will need to either upgrade to a version of glibc that does not\n"
215 "have this problem (2.3.4 or later when used with nscd),\n"
216 "disable LDAP in your nsswitch.conf, or use a "
217 "mysqld that is not statically linked.\n");
218 }
219 #endif
220
221 if (locked_in_memory)
222 {
223 my_safe_printf_stderr("%s", "\n"
224 "The \"--memlock\" argument, which was enabled, "
225 "uses system calls that are\n"
226 "unreliable and unstable on some operating systems and "
227 "operating-system versions (notably, some versions of Linux).\n"
228 "This crash could be due to use of those buggy OS calls.\n"
229 "You should consider whether you really need the "
230 "\"--memlock\" parameter and/or consult the OS distributer about "
231 "\"mlockall\" bugs.\n");
232 }
233
234 if (test_flags & TEST_CORE_ON_SIGNAL)
235 {
236 #if HAVE_LIBCOREDUMPER
237 if (opt_libcoredumper)
238 {
239 if (opt_libcoredumper_path != NULL)
240 {
241 if (!validate_libcoredumper_path(opt_libcoredumper_path))
242 {
243 my_safe_printf_stderr("%s", "Changing path to datadir\n");
244 opt_libcoredumper_path= NULL;
245 }
246 }
247 my_safe_printf_stderr("%s",
248 "Writing a core file using lib coredumper\n");
249 my_write_libcoredumper(sig, opt_libcoredumper_path, curr_time);
250 }
251 else
252 {
253 #endif
254 my_safe_printf_stderr("%s", "Writing a core file\n");
255 my_write_core(sig);
256 #if HAVE_LIBCOREDUMPER
257 }
258 #endif
259 }
260
261 #ifndef _WIN32
262 /*
263 Quit, without running destructors (etc.)
264 On Windows, do not terminate, but pass control to exception filter.
265 */
266 _exit(MYSQLD_FAILURE_EXIT); // Using _exit(), since exit() is not async signal safe
267 #endif
268 }
269