1 /* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
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_config.h"
24
25 #include <signal.h>
26 #include <sys/types.h>
27 #include <time.h>
28 #include <algorithm>
29 #include <atomic>
30
31 #include "lex_string.h"
32 #include "my_inttypes.h"
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36
37 #include "my_macros.h"
38 #include "my_stacktrace.h"
39 #include "my_sys.h"
40 #include "sql/mysqld.h"
41 #include "sql/sql_class.h"
42 #include "sql/sql_const.h"
43
44 #ifdef _WIN32
45 #include <crtdbg.h>
46
47 #define SIGNAL_FMT "exception 0x%x"
48 #else
49 #define SIGNAL_FMT "signal %d"
50 #endif
51
52 /*
53 We are handling signals in this file.
54 Any global variables we read should be 'volatile sig_atomic_t'
55 to guarantee that we read some consistent value.
56 */
57 static volatile sig_atomic_t segfaulted = 0;
58
59 /**
60 * Handler for fatal signals
61 *
62 * Fatal events (seg.fault, bus error etc.) will trigger
63 * this signal handler. The handler will try to dump relevant
64 * debugging information to stderr and dump a core image.
65 *
66 * Signal handlers can only use a set of 'safe' system calls
67 * and library functions. A list of safe calls in POSIX systems
68 * are available at:
69 * http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html
70 * For MS Windows, guidelines are available at:
71 * http://msdn.microsoft.com/en-us/library/xdkz3x12(v=vs.71).aspx
72 *
73 * @param sig Signal number
74 */
handle_fatal_signal(int sig)75 extern "C" void handle_fatal_signal(int sig) {
76 if (segfaulted) {
77 my_safe_printf_stderr("Fatal " SIGNAL_FMT " while backtracing\n", sig);
78 _exit(MYSQLD_FAILURE_EXIT); /* Quit without running destructors */
79 }
80
81 segfaulted = 1;
82
83 #ifdef _WIN32
84 SYSTEMTIME utc_time;
85 GetSystemTime(&utc_time);
86 const long hrs = utc_time.wHour;
87 const long mins = utc_time.wMinute;
88 const long secs = utc_time.wSecond;
89 #else
90 /* Using time() instead of my_time() to avoid looping */
91 const time_t curr_time = time(nullptr);
92 /* Calculate time of day */
93 const long tmins = curr_time / 60;
94 const long thrs = tmins / 60;
95 const long hrs = thrs % 24;
96 const long mins = tmins % 60;
97 const long secs = curr_time % 60;
98 #endif
99
100 char hrs_buf[3] = "00";
101 char mins_buf[3] = "00";
102 char secs_buf[3] = "00";
103 my_safe_itoa(10, hrs, &hrs_buf[2]);
104 my_safe_itoa(10, mins, &mins_buf[2]);
105 my_safe_itoa(10, secs, &secs_buf[2]);
106
107 my_safe_printf_stderr("%s:%s:%s UTC - mysqld got " SIGNAL_FMT " ;\n", hrs_buf,
108 mins_buf, secs_buf, sig);
109
110 my_safe_printf_stderr(
111 "%s",
112 "Most likely, you have hit a bug, but this error can also "
113 "be caused by malfunctioning hardware.\n");
114
115 #ifdef HAVE_STACKTRACE
116 THD *thd = current_thd;
117
118 if (!(test_flags & TEST_NO_STACKTRACE)) {
119 my_safe_printf_stderr("Thread pointer: 0x%p\n", thd);
120 my_safe_printf_stderr(
121 "%s",
122 "Attempting backtrace. You can use the following "
123 "information to find out\n"
124 "where mysqld died. If you see no messages after this, something went\n"
125 "terribly wrong...\n");
126 my_print_stacktrace(
127 thd ? pointer_cast<const uchar *>(thd->thread_stack) : nullptr,
128 my_thread_stack_size);
129 }
130 if (thd) {
131 const char *kreason = "UNKNOWN";
132 switch (thd->killed.load()) {
133 case THD::NOT_KILLED:
134 kreason = "NOT_KILLED";
135 break;
136 case THD::KILL_CONNECTION:
137 kreason = "KILL_CONNECTION";
138 break;
139 case THD::KILL_QUERY:
140 kreason = "KILL_QUERY";
141 break;
142 case THD::KILL_TIMEOUT:
143 kreason = "KILL_TIMEOUT";
144 break;
145 case THD::KILLED_NO_VALUE:
146 kreason = "KILLED_NO_VALUE";
147 break;
148 }
149 my_safe_printf_stderr(
150 "%s",
151 "\n"
152 "Trying to get some variables.\n"
153 "Some pointers may be invalid and cause the dump to abort.\n");
154
155 my_safe_printf_stderr("Query (%p): ", thd->query().str);
156 my_safe_puts_stderr(thd->query().str,
157 std::min(size_t{1024}, thd->query().length));
158 my_safe_printf_stderr("Connection ID (thread ID): %u\n", thd->thread_id());
159 my_safe_printf_stderr("Status: %s\n\n", kreason);
160 }
161 my_safe_printf_stderr(
162 "%s",
163 "\n"
164 "Please report a bug at https://jira.percona.com/projects/PXB\n");
165
166 #endif /* HAVE_STACKTRACE */
167
168 if (test_flags & TEST_CORE_ON_SIGNAL) {
169 my_safe_printf_stderr("%s", "Writing a core file\n");
170 my_write_core(sig);
171 }
172
173 #ifndef _WIN32
174 /*
175 Quit, without running destructors (etc.)
176 On Windows, do not terminate, but pass control to exception filter.
177 */
178 _exit(MYSQLD_FAILURE_EXIT); // Using _exit(), since exit() is not async
179 // signal safe
180 #endif
181 }
182