1 /* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights
2    reserved.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
23 
24 #include "my_global.h"                          /* NO_EMBEDDED_ACCESS_CHECKS */
25 
26 #include <vector>
27 #include <algorithm>
28 #include <functional>
29 #include <list>
30 #include <set>
31 
32 #include "sql_priv.h"
33 #include "unireg.h"
34 #include <signal.h>
35 #include "sql_parse.h"    // test_if_data_home_dir
36 #include "sql_cache.h"    // query_cache, query_cache_*
37 #include "sql_locale.h"   // MY_LOCALES, my_locales, my_locale_by_name
38 #include "sql_show.h"     // free_status_vars, add_status_vars,
39                           // reset_status_vars
40 #include "strfunc.h"      // find_set_from_flags
41 #include "parse_file.h"   // File_parser_dummy_hook
42 #include "sql_db.h"       // my_dboptions_cache_free
43                           // my_dboptions_cache_init
44 #include "sql_table.h"    // release_ddl_log, execute_ddl_log_recovery
45 #include "sql_connect.h"  // free_max_user_conn, init_max_user_conn,
46                           // handle_one_connection
47 #include "sql_time.h"     // known_date_time_formats,
48                           // get_date_time_format_str,
49                           // date_time_format_make
50 #include "tztime.h"       // my_tz_free, my_tz_init, my_tz_SYSTEM
51 #include "hostname.h"     // hostname_cache_free, hostname_cache_init
52 #include "sql_acl.h"      // acl_free, grant_free, acl_init,
53                           // grant_init
54 #include "sql_base.h"     // table_def_free, table_def_init,
55                           // Table_cache,
56                           // cached_table_definitions
57 #include "sql_test.h"     // mysql_print_status
58 #include "item_create.h"  // item_create_cleanup, item_create_init
59 #include "sql_servers.h"  // servers_free, servers_init
60 #include "init.h"         // unireg_init
61 #include "derror.h"       // init_errmessage
62 #include "derror.h"       // init_errmessage
63 #include "des_key_file.h" // load_des_key_file
64 #include "sql_manager.h"  // stop_handle_manager, start_handle_manager
65 #include <m_ctype.h>
66 #include <my_dir.h>
67 #include <my_bit.h>
68 #include "rpl_gtid.h"
69 #include "rpl_slave.h"
70 #include "rpl_master.h"
71 #include "rpl_mi.h"
72 #include "rpl_filter.h"
73 #include <sql_common.h>
74 #include <my_stacktrace.h>
75 #include "mysqld_suffix.h"
76 #include "mysys_err.h"
77 #include "events.h"
78 #include "sql_audit.h"
79 #include "probes_mysql.h"
80 #include "scheduler.h"
81 #include "debug_sync.h"
82 #ifdef WITH_WSREP
83 #include "wsrep_mysqld.h"
84 #include "wsrep_var.h"
85 #include "wsrep_thd.h"
86 #include "wsrep_sst.h"
87 #endif
88 #include "sql_callback.h"
89 #include "opt_trace_context.h"
90 
91 #include "global_threads.h"
92 #include "mysqld.h"
93 #include "my_default.h"
94 
95 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
96 #include "../storage/perfschema/pfs_server.h"
97 #else
98 #include "lf.h"
99 int dummy_variable_to_pull_in_lf_hash_functions= LF_HASH_OVERHEAD;
100 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
101 
102 #include <mysql/psi/mysql_idle.h>
103 #include <mysql/psi/mysql_socket.h>
104 #include <mysql/psi/mysql_statement.h>
105 #include "mysql_com_server.h"
106 
107 #include "keycaches.h"
108 #include "../storage/myisam/ha_myisam.h"
109 #include "set_var.h"
110 
111 #include "sys_vars_shared.h"
112 
113 #include "rpl_injector.h"
114 
115 #include "rpl_handler.h"
116 
117 #ifdef HAVE_SYS_PRCTL_H
118 #include <sys/prctl.h>
119 #endif
120 
121 #include <thr_alarm.h>
122 #include <ft_global.h>
123 #include <errmsg.h>
124 #include "sp_rcontext.h"
125 #include "sp_cache.h"
126 #include "sql_reload.h"  // reload_acl_and_cache
127 
128 #ifdef HAVE_POLL_H
129 #include <poll.h>
130 #endif
131 
132 #ifdef HAVE_FESETROUND
133 #include <fenv.h>
134 #endif
135 #include "table_cache.h" // table_cache_manager
136 
137 using std::min;
138 using std::max;
139 using std::vector;
140 
141 #define mysqld_charset &my_charset_latin1
142 
143 /* We have HAVE_purify below as this speeds up the shutdown of MySQL */
144 
145 #if defined(HAVE_DEC_3_2_THREADS) || defined(SIGNALS_DONT_BREAK_READ) || defined(HAVE_purify) && defined(__linux__)
146 #define HAVE_CLOSE_SERVER_SOCK 1
147 #endif
148 
149 extern "C" {          // Because of SCO 3.2V4.2
150 #include <errno.h>
151 #include <sys/stat.h>
152 #ifndef __GNU_LIBRARY__
153 #define __GNU_LIBRARY__       // Skip warnings in getopt.h
154 #endif
155 #include <my_getopt.h>
156 #ifdef HAVE_SYSENT_H
157 #include <sysent.h>
158 #endif
159 #ifdef HAVE_PWD_H
160 #include <pwd.h>        // For getpwent
161 #endif
162 #ifdef HAVE_GRP_H
163 #include <grp.h>
164 #endif
165 #include <my_net.h>
166 
167 #if !defined(__WIN__)
168 #include <sys/resource.h>
169 #ifdef HAVE_SYS_UN_H
170 #include <sys/un.h>
171 #endif
172 #ifdef HAVE_SELECT_H
173 #include <select.h>
174 #endif
175 #ifdef HAVE_SYS_SELECT_H
176 #include <sys/select.h>
177 #endif
178 #include <sys/utsname.h>
179 #endif /* __WIN__ */
180 
181 #include <my_libwrap.h>
182 
183 #ifdef HAVE_SYS_MMAN_H
184 #include <sys/mman.h>
185 #endif
186 
187 #ifdef __WIN__
188 #include <crtdbg.h>
189 #endif
190 
191 #ifdef HAVE_SOLARIS_LARGE_PAGES
192 #include <sys/mman.h>
193 #if defined(__sun__) && defined(__GNUC__) && defined(__cplusplus) \
194     && defined(_XOPEN_SOURCE)
195 extern int getpagesizes(size_t *, int);
196 extern int getpagesizes2(size_t *, int);
197 extern int memcntl(caddr_t, size_t, int, caddr_t, int, int);
198 #endif /* __sun__ ... */
199 #endif /* HAVE_SOLARIS_LARGE_PAGES */
200 
201 #ifdef _AIX41
202 int initgroups(const char *,unsigned int);
203 #endif
204 
205 #if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H) && !defined(HAVE_FEDISABLEEXCEPT)
206 #include <ieeefp.h>
207 #ifdef HAVE_FP_EXCEPT       // Fix type conflict
208 typedef fp_except fp_except_t;
209 #endif
210 #endif /* __FreeBSD__ && HAVE_IEEEFP_H && !HAVE_FEDISABLEEXCEPT */
211 #ifdef HAVE_SYS_FPU_H
212 /* for IRIX to use set_fpc_csr() */
213 #include <sys/fpu.h>
214 #endif
215 #ifdef HAVE_FPU_CONTROL_H
216 #include <fpu_control.h>
217 #endif
218 #if defined(__i386__) && !defined(HAVE_FPU_CONTROL_H)
219 # define fpu_control_t unsigned int
220 # define _FPU_EXTENDED 0x300
221 # define _FPU_DOUBLE 0x200
222 # if defined(__GNUC__) || (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x590)
223 #  define _FPU_GETCW(cw) asm volatile ("fnstcw %0" : "=m" (*&cw))
224 #  define _FPU_SETCW(cw) asm volatile ("fldcw %0" : : "m" (*&cw))
225 # else
226 #  define _FPU_GETCW(cw) (cw= 0)
227 #  define _FPU_SETCW(cw)
228 # endif
229 #endif
230 
231 extern "C" my_bool reopen_fstreams(const char *filename,
232                                    FILE *outstream, FILE *errstream);
233 
setup_fpu()234 inline void setup_fpu()
235 {
236 #if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H) && !defined(HAVE_FEDISABLEEXCEPT)
237   /* We can't handle floating point exceptions with threads, so disable
238      this on freebsd
239      Don't fall for overflow, underflow,divide-by-zero or loss of precision.
240      fpsetmask() is deprecated in favor of fedisableexcept() in C99.
241   */
242 #if defined(FP_X_DNML)
243   fpsetmask(~(FP_X_INV | FP_X_DNML | FP_X_OFL | FP_X_UFL | FP_X_DZ |
244         FP_X_IMP));
245 #else
246   fpsetmask(~(FP_X_INV |             FP_X_OFL | FP_X_UFL | FP_X_DZ |
247               FP_X_IMP));
248 #endif /* FP_X_DNML */
249 #endif /* __FreeBSD__ && HAVE_IEEEFP_H && !HAVE_FEDISABLEEXCEPT */
250 
251 #ifdef HAVE_FEDISABLEEXCEPT
252   fedisableexcept(FE_ALL_EXCEPT);
253 #endif
254 
255 #ifdef HAVE_FESETROUND
256     /* Set FPU rounding mode to "round-to-nearest" */
257   fesetround(FE_TONEAREST);
258 #endif /* HAVE_FESETROUND */
259 
260   /*
261     x86 (32-bit) requires FPU precision to be explicitly set to 64 bit
262     (double precision) for portable results of floating point operations.
263     However, there is no need to do so if compiler is using SSE2 for floating
264     point, double values will be stored and processed in 64 bits anyway.
265   */
266 #if defined(__i386__) && !defined(__SSE2_MATH__)
267 #if defined(_WIN32)
268 #if !defined(_WIN64)
269   _control87(_PC_53, MCW_PC);
270 #endif /* !_WIN64 */
271 #else /* !_WIN32 */
272   fpu_control_t cw;
273   _FPU_GETCW(cw);
274   cw= (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE;
275   _FPU_SETCW(cw);
276 #endif /* _WIN32 && */
277 #endif /* __i386__ */
278 
279 #if defined(__sgi) && defined(HAVE_SYS_FPU_H)
280   /* Enable denormalized DOUBLE values support for IRIX */
281   union fpc_csr n;
282   n.fc_word = get_fpc_csr();
283   n.fc_struct.flush = 0;
284   set_fpc_csr(n.fc_word);
285 #endif
286 }
287 
288 } /* cplusplus */
289 
290 #define MYSQL_KILL_SIGNAL SIGTERM
291 
292 #include <my_pthread.h>     // For thr_setconcurency()
293 
294 #ifdef SOLARIS
295 extern "C" int gethostname(char *name, int namelen);
296 #endif
297 
298 extern "C" sig_handler handle_fatal_signal(int sig);
299 
300 #if defined(__linux__)
301 #define ENABLE_TEMP_POOL 1
302 #else
303 #define ENABLE_TEMP_POOL 0
304 #endif
305 
306 /* Constants */
307 
308 #include <welcome_copyright_notice.h> // ORACLE_WELCOME_COPYRIGHT_NOTICE
309 
310 const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"};
311 
312 static const char *tc_heuristic_recover_names[]=
313 {
314   "COMMIT", "ROLLBACK", NullS
315 };
316 static TYPELIB tc_heuristic_recover_typelib=
317 {
318   array_elements(tc_heuristic_recover_names)-1,"",
319   tc_heuristic_recover_names, NULL
320 };
321 
322 const char *first_keyword= "first", *binary_keyword= "BINARY";
323 const char *my_localhost= "localhost", *delayed_user= "DELAYED";
324 
325 bool opt_large_files= sizeof(my_off_t) > 4;
326 static my_bool opt_autocommit; ///< for --autocommit command-line option
327 
328 /*
329   Used with --help for detailed option
330 */
331 static my_bool opt_help= 0, opt_verbose= 0;
332 
333 arg_cmp_func Arg_comparator::comparator_matrix[5][2] =
334 {{&Arg_comparator::compare_string,     &Arg_comparator::compare_e_string},
335  {&Arg_comparator::compare_real,       &Arg_comparator::compare_e_real},
336  {&Arg_comparator::compare_int_signed, &Arg_comparator::compare_e_int},
337  {&Arg_comparator::compare_row,        &Arg_comparator::compare_e_row},
338  {&Arg_comparator::compare_decimal,    &Arg_comparator::compare_e_decimal}};
339 
340 /* static variables */
341 
342 #ifdef HAVE_PSI_INTERFACE
343 #if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
344 static PSI_thread_key key_thread_handle_con_namedpipes;
345 static PSI_cond_key key_COND_handler_count;
346 static PSI_rwlock_key key_rwlock_LOCK_named_pipe_full_access_group;
347 #endif /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */
348 
349 #if defined(HAVE_SMEM) && !defined(EMBEDDED_LIBRARY)
350 static PSI_thread_key key_thread_handle_con_sharedmem;
351 #endif /* HAVE_SMEM && !EMBEDDED_LIBRARY */
352 
353 #if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
354 static PSI_thread_key key_thread_handle_con_sockets;
355 #endif /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */
356 
357 #ifdef __WIN__
358 static PSI_thread_key key_thread_handle_shutdown;
359 #endif /* __WIN__ */
360 
361 #if defined (HAVE_OPENSSL)
362 static PSI_rwlock_key key_rwlock_openssl;
363 #endif
364 #endif /* HAVE_PSI_INTERFACE */
365 
366 /**
367   Statement instrumentation key for replication.
368 */
369 #ifdef HAVE_PSI_STATEMENT_INTERFACE
370 PSI_statement_info stmt_info_rpl;
371 #endif
372 
373 /* the default log output is log tables */
374 static bool lower_case_table_names_used= 0;
375 static bool volatile select_thread_in_use, signal_thread_in_use;
376 /* See Bug#56666 and Bug#56760 */;
377 volatile bool ready_to_exit;
378 static my_bool opt_debugging= 0, opt_external_locking= 0, opt_console= 0;
379 static my_bool opt_short_log_format= 0;
380 static uint kill_blocked_pthreads_flag, wake_pthread;
381 static ulong killed_threads;
382        ulong max_used_connections;
383 static char *mysqld_user, *mysqld_chroot;
384 static char *default_character_set_name;
385 static char *character_set_filesystem_name;
386 static char *lc_messages;
387 static char *lc_time_names_name;
388 char *my_bind_addr_str;
389 static char *default_collation_name;
390 char *default_storage_engine;
391 char *default_tmp_storage_engine;
392 static char compiled_default_collation_name[]= MYSQL_DEFAULT_COLLATION_NAME;
393 static bool binlog_format_used= false;
394 
395 LEX_STRING opt_init_connect, opt_init_slave;
396 
397 static mysql_cond_t COND_thread_cache, COND_flush_thread_cache;
398 
399 /* Global variables */
400 
401 bool opt_bin_log, opt_ignore_builtin_innodb= 0;
402 my_bool opt_log, opt_slow_log, opt_log_raw;
403 ulonglong log_output_options;
404 my_bool opt_log_queries_not_using_indexes= 0;
405 ulong opt_log_throttle_queries_not_using_indexes= 0;
406 bool opt_error_log= IF_WIN(1,0);
407 bool opt_disable_networking=0, opt_skip_show_db=0;
408 bool opt_skip_name_resolve=0;
409 my_bool opt_character_set_client_handshake= 1;
410 bool server_id_supplied = 0;
411 bool opt_endinfo, using_udf_functions;
412 my_bool locked_in_memory;
413 bool opt_using_transactions;
414 bool volatile abort_loop;
415 bool volatile shutdown_in_progress;
416 ulong log_warnings;
417 uint host_cache_size;
418 
419 #if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
420 ulong slow_start_timeout;
421 #endif
422 /*
423   True if the bootstrap thread is running. Protected by LOCK_thread_count.
424   Used in bootstrap() function to determine if the bootstrap thread
425   has completed. Note, that we can't use 'thread_count' instead,
426   since in 5.1, in presence of the Event Scheduler, there may be
427   event threads running in parallel, so it's impossible to know
428   what value of 'thread_count' is a sign of completion of the
429   bootstrap thread.
430 
431   At the same time, we can't start the event scheduler after
432   bootstrap either, since we want to be able to process event-related
433   SQL commands in the init file and in --bootstrap mode.
434 */
435 bool in_bootstrap= FALSE;
436 my_bool opt_bootstrap= 0;
437 
438 /**
439    @brief 'grant_option' is used to indicate if privileges needs
440    to be checked, in which case the lock, LOCK_grant, is used
441    to protect access to the grant table.
442    @note This flag is dropped in 5.1
443    @see grant_init()
444  */
445 bool volatile grant_option;
446 
447 my_bool opt_skip_slave_start = 0; ///< If set, slave is not autostarted
448 my_bool opt_reckless_slave = 0;
449 my_bool opt_enable_named_pipe= 0;
450 my_bool opt_local_infile, opt_slave_compressed_protocol;
451 my_bool opt_safe_user_create = 0;
452 my_bool opt_show_slave_auth_info;
453 my_bool opt_log_slave_updates= 0;
454 char *opt_slave_skip_errors;
455 my_bool opt_slave_allow_batching= 0;
456 
457 /**
458   compatibility option:
459     - index usage hints (USE INDEX without a FOR clause) behave as in 5.0
460 */
461 my_bool old_mode;
462 
463 /*
464   Legacy global handlerton. These will be removed (please do not add more).
465 */
466 handlerton *heap_hton;
467 handlerton *myisam_hton;
468 handlerton *partition_hton;
469 
470 uint opt_server_id_bits= 0;
471 ulong opt_server_id_mask= 0;
472 my_bool read_only= 0, opt_readonly= 0;
473 my_bool use_temp_pool, relay_log_purge;
474 my_bool relay_log_recovery;
475 my_bool opt_sync_frm, opt_allow_suspicious_udfs;
476 my_bool opt_secure_auth= 0;
477 char* opt_secure_file_priv;
478 my_bool opt_log_slow_admin_statements= 0;
479 my_bool opt_log_slow_slave_statements= 0;
480 my_bool lower_case_file_system= 0;
481 my_bool opt_large_pages= 0;
482 my_bool opt_super_large_pages= 0;
483 my_bool opt_myisam_use_mmap= 0;
484 uint   opt_large_page_size= 0;
485 #if defined(ENABLED_DEBUG_SYNC)
486 MYSQL_PLUGIN_IMPORT uint    opt_debug_sync_timeout= 0;
487 #endif /* defined(ENABLED_DEBUG_SYNC) */
488 my_bool opt_old_style_user_limits= 0, trust_function_creators= 0;
489 /*
490   True if there is at least one per-hour limit for some user, so we should
491   check them before each query (and possibly reset counters when hour is
492   changed). False otherwise.
493 */
494 volatile bool mqh_used = 0;
495 my_bool opt_noacl= 0;
496 my_bool sp_automatic_privileges= 1;
497 
498 ulong opt_binlog_rows_event_max_size;
499 const char *binlog_checksum_default= "NONE";
500 ulong binlog_checksum_options;
501 my_bool opt_master_verify_checksum= 0;
502 my_bool opt_slave_sql_verify_checksum= 1;
503 const char *binlog_format_names[]= {"MIXED", "STATEMENT", "ROW", NullS};
504 #ifdef WITH_WSREP
505 const char *wsrep_binlog_format_names[]=
506                                    {"MIXED", "STATEMENT", "ROW", "NONE", NullS};
507 #endif /*WITH_WSREP */
508 my_bool enforce_gtid_consistency;
509 my_bool binlog_gtid_simple_recovery;
510 ulong binlog_error_action;
511 const char *binlog_error_action_list[]= {"IGNORE_ERROR", "ABORT_SERVER", NullS};
512 ulong gtid_mode;
513 const char *gtid_mode_names[]=
514 {"OFF", "UPGRADE_STEP_1", "UPGRADE_STEP_2", "ON", NullS};
515 TYPELIB gtid_mode_typelib=
516 { array_elements(gtid_mode_names) - 1, "", gtid_mode_names, NULL };
517 
518 #ifdef HAVE_INITGROUPS
519 volatile sig_atomic_t calling_initgroups= 0; /**< Used in SIGSEGV handler. */
520 #endif
521 uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options;
522 uint mysqld_port_timeout;
523 ulong delay_key_write_options;
524 uint protocol_version;
525 uint lower_case_table_names;
526 ulong tc_heuristic_recover= 0;
527 int32 num_thread_running;
528 ulong thread_created;
529 ulong back_log, connect_timeout, concurrency, server_id;
530 ulong table_cache_size, table_def_size;
531 ulong table_cache_instances;
532 ulong table_cache_size_per_instance;
533 ulong what_to_log;
534 ulong slow_launch_time;
535 int32 slave_open_temp_tables;
536 ulong open_files_limit, max_binlog_size, max_relay_log_size;
537 ulong slave_trans_retries;
538 uint  slave_net_timeout;
539 ulong slave_exec_mode_options;
540 ulonglong slave_type_conversions_options;
541 ulong opt_mts_slave_parallel_workers;
542 ulonglong opt_mts_pending_jobs_size_max;
543 ulonglong slave_rows_search_algorithms_options;
544 #ifndef DBUG_OFF
545 uint slave_rows_last_search_algorithm_used;
546 #endif
547 ulong binlog_cache_size=0;
548 ulonglong  max_binlog_cache_size=0;
549 ulong slave_max_allowed_packet= 0;
550 ulong binlog_stmt_cache_size=0;
551 my_atomic_rwlock_t opt_binlog_max_flush_queue_time_lock;
552 int32 opt_binlog_max_flush_queue_time= 0;
553 ulonglong  max_binlog_stmt_cache_size=0;
554 ulong query_cache_size=0;
555 ulong refresh_version;  /* Increments on each reload */
556 query_id_t global_query_id;
557 my_atomic_rwlock_t global_query_id_lock;
558 my_atomic_rwlock_t thread_running_lock;
559 my_atomic_rwlock_t slave_open_temp_tables_lock;
560 ulong aborted_threads, aborted_connects;
561 ulong delayed_insert_timeout, delayed_insert_limit, delayed_queue_size;
562 ulong delayed_insert_threads, delayed_insert_writes, delayed_rows_in_use;
563 ulong delayed_insert_errors,flush_time;
564 ulong specialflag=0;
565 ulong binlog_cache_use= 0, binlog_cache_disk_use= 0;
566 ulong binlog_stmt_cache_use= 0, binlog_stmt_cache_disk_use= 0;
567 ulong max_connections, max_connect_errors;
568 ulong rpl_stop_slave_timeout= LONG_TIMEOUT;
569 my_bool log_bin_use_v1_row_events= 0;
570 bool thread_cache_size_specified= false;
571 bool host_cache_size_specified= false;
572 bool table_definition_cache_specified= false;
573 
574 Error_log_throttle err_log_throttle(Log_throttle::LOG_THROTTLE_WINDOW_SIZE,
575                                     sql_print_error,
576                                     "Error log throttle: %10lu 'Can't create"
577                                     " thread to handle new connection'"
578                                     " error(s) suppressed");
579 
580 /**
581   Limit of the total number of prepared statements in the server.
582   Is necessary to protect the server against out-of-memory attacks.
583 */
584 ulong max_prepared_stmt_count;
585 /**
586   Current total number of prepared statements in the server. This number
587   is exact, and therefore may not be equal to the difference between
588   `com_stmt_prepare' and `com_stmt_close' (global status variables), as
589   the latter ones account for all registered attempts to prepare
590   a statement (including unsuccessful ones).  Prepared statements are
591   currently connection-local: if the same SQL query text is prepared in
592   two different connections, this counts as two distinct prepared
593   statements.
594 */
595 ulong prepared_stmt_count=0;
596 ulong thread_id=1L,current_pid;
597 ulong slow_launch_threads = 0;
598 uint sync_binlog_period= 0, sync_relaylog_period= 0,
599      sync_relayloginfo_period= 0, sync_masterinfo_period= 0,
600      opt_mts_checkpoint_period, opt_mts_checkpoint_group;
601 ulong expire_logs_days = 0;
602 /**
603   Soft upper limit for number of sp_head objects that can be stored
604   in the sp_cache for one connection.
605 */
606 ulong stored_program_cache_size= 0;
607 /**
608   Compatibility option to prevent auto upgrade of old temporals
609   during certain ALTER TABLE operations.
610 */
611 my_bool avoid_temporal_upgrade;
612 
613 const double log_10[] = {
614   1e000, 1e001, 1e002, 1e003, 1e004, 1e005, 1e006, 1e007, 1e008, 1e009,
615   1e010, 1e011, 1e012, 1e013, 1e014, 1e015, 1e016, 1e017, 1e018, 1e019,
616   1e020, 1e021, 1e022, 1e023, 1e024, 1e025, 1e026, 1e027, 1e028, 1e029,
617   1e030, 1e031, 1e032, 1e033, 1e034, 1e035, 1e036, 1e037, 1e038, 1e039,
618   1e040, 1e041, 1e042, 1e043, 1e044, 1e045, 1e046, 1e047, 1e048, 1e049,
619   1e050, 1e051, 1e052, 1e053, 1e054, 1e055, 1e056, 1e057, 1e058, 1e059,
620   1e060, 1e061, 1e062, 1e063, 1e064, 1e065, 1e066, 1e067, 1e068, 1e069,
621   1e070, 1e071, 1e072, 1e073, 1e074, 1e075, 1e076, 1e077, 1e078, 1e079,
622   1e080, 1e081, 1e082, 1e083, 1e084, 1e085, 1e086, 1e087, 1e088, 1e089,
623   1e090, 1e091, 1e092, 1e093, 1e094, 1e095, 1e096, 1e097, 1e098, 1e099,
624   1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109,
625   1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119,
626   1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129,
627   1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139,
628   1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149,
629   1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159,
630   1e160, 1e161, 1e162, 1e163, 1e164, 1e165, 1e166, 1e167, 1e168, 1e169,
631   1e170, 1e171, 1e172, 1e173, 1e174, 1e175, 1e176, 1e177, 1e178, 1e179,
632   1e180, 1e181, 1e182, 1e183, 1e184, 1e185, 1e186, 1e187, 1e188, 1e189,
633   1e190, 1e191, 1e192, 1e193, 1e194, 1e195, 1e196, 1e197, 1e198, 1e199,
634   1e200, 1e201, 1e202, 1e203, 1e204, 1e205, 1e206, 1e207, 1e208, 1e209,
635   1e210, 1e211, 1e212, 1e213, 1e214, 1e215, 1e216, 1e217, 1e218, 1e219,
636   1e220, 1e221, 1e222, 1e223, 1e224, 1e225, 1e226, 1e227, 1e228, 1e229,
637   1e230, 1e231, 1e232, 1e233, 1e234, 1e235, 1e236, 1e237, 1e238, 1e239,
638   1e240, 1e241, 1e242, 1e243, 1e244, 1e245, 1e246, 1e247, 1e248, 1e249,
639   1e250, 1e251, 1e252, 1e253, 1e254, 1e255, 1e256, 1e257, 1e258, 1e259,
640   1e260, 1e261, 1e262, 1e263, 1e264, 1e265, 1e266, 1e267, 1e268, 1e269,
641   1e270, 1e271, 1e272, 1e273, 1e274, 1e275, 1e276, 1e277, 1e278, 1e279,
642   1e280, 1e281, 1e282, 1e283, 1e284, 1e285, 1e286, 1e287, 1e288, 1e289,
643   1e290, 1e291, 1e292, 1e293, 1e294, 1e295, 1e296, 1e297, 1e298, 1e299,
644   1e300, 1e301, 1e302, 1e303, 1e304, 1e305, 1e306, 1e307, 1e308
645 };
646 
647 time_t server_start_time, flush_status_time;
648 
649 char server_uuid[UUID_LENGTH+1];
650 const char *server_uuid_ptr;
651 char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30];
652 char default_logfile_name[FN_REFLEN];
653 char *default_tz_name;
654 char log_error_file[FN_REFLEN], glob_hostname[FN_REFLEN];
655 char mysql_real_data_home[FN_REFLEN],
656      lc_messages_dir[FN_REFLEN], reg_ext[FN_EXTLEN],
657      mysql_charsets_dir[FN_REFLEN],
658      *opt_init_file, *opt_tc_log_file;
659 char *lc_messages_dir_ptr, *log_error_file_ptr;
660 char mysql_unpacked_real_data_home[FN_REFLEN];
661 int mysql_unpacked_real_data_home_len;
662 uint mysql_real_data_home_len, mysql_data_home_len= 1;
663 uint reg_ext_length;
664 const key_map key_map_empty(0);
665 key_map key_map_full(0);                        // Will be initialized later
666 char logname_path[FN_REFLEN];
667 char slow_logname_path[FN_REFLEN];
668 char secure_file_real_path[FN_REFLEN];
669 
670 DATE_TIME_FORMAT global_date_format, global_datetime_format, global_time_format;
671 Time_zone *default_tz;
672 
673 char *mysql_data_home= const_cast<char*>(".");
674 const char *mysql_real_data_home_ptr= mysql_real_data_home;
675 char server_version[SERVER_VERSION_LENGTH];
676 char *mysqld_unix_port, *opt_mysql_tmpdir;
677 ulong thread_handling;
678 
679 /** name of reference on left expression in rewritten IN subquery */
680 const char *in_left_expr_name= "<left expr>";
681 /** name of additional condition */
682 const char *in_additional_cond= "<IN COND>";
683 const char *in_having_cond= "<IN HAVING>";
684 
685 my_decimal decimal_zero;
686 /** Number of connection errors when selecting on the listening port */
687 ulong connection_errors_select= 0;
688 /** Number of connection errors when accepting sockets in the listening port. */
689 ulong connection_errors_accept= 0;
690 /** Number of connection errors from TCP wrappers. */
691 ulong connection_errors_tcpwrap= 0;
692 /** Number of connection errors from internal server errors. */
693 ulong connection_errors_internal= 0;
694 /** Number of connection errors from the server max_connection limit. */
695 ulong connection_errors_max_connection= 0;
696 /** Number of errors when reading the peer address. */
697 ulong connection_errors_peer_addr= 0;
698 
699 /* classes for comparation parsing/processing */
700 Eq_creator eq_creator;
701 Ne_creator ne_creator;
702 Gt_creator gt_creator;
703 Lt_creator lt_creator;
704 Ge_creator ge_creator;
705 Le_creator le_creator;
706 
707 MYSQL_FILE *bootstrap_file;
708 int bootstrap_error;
709 
710 Rpl_filter* rpl_filter;
711 Rpl_filter* binlog_filter;
712 
713 struct system_variables global_system_variables;
714 struct system_variables max_system_variables;
715 struct system_status_var global_status_var;
716 
717 MY_TMPDIR mysql_tmpdir_list;
718 MY_BITMAP temp_pool;
719 
720 CHARSET_INFO *system_charset_info, *files_charset_info ;
721 CHARSET_INFO *national_charset_info, *table_alias_charset;
722 CHARSET_INFO *character_set_filesystem;
723 CHARSET_INFO *error_message_charset_info;
724 
725 MY_LOCALE *my_default_lc_messages;
726 MY_LOCALE *my_default_lc_time_names;
727 
728 SHOW_COMP_OPTION have_ssl, have_symlink, have_dlopen, have_query_cache;
729 SHOW_COMP_OPTION have_geometry, have_rtree_keys;
730 SHOW_COMP_OPTION have_crypt, have_compress;
731 SHOW_COMP_OPTION have_profiling;
732 
733 /* Thread specific variables */
734 
735 pthread_key(MEM_ROOT**,THR_MALLOC);
736 pthread_key(THD*, THR_THD);
737 mysql_mutex_t LOCK_thread_created;
738 mysql_mutex_t LOCK_thread_count, LOCK_thd_remove;
739 mysql_mutex_t
740   LOCK_status, LOCK_error_log, LOCK_uuid_generator,
741   LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
742   LOCK_crypt,
743   LOCK_global_system_variables,
744   LOCK_user_conn, LOCK_slave_list, LOCK_active_mi,
745   LOCK_connection_count, LOCK_error_messages;
746 mysql_mutex_t LOCK_sql_rand;
747 
748 /**
749   The below lock protects access to two global server variables:
750   max_prepared_stmt_count and prepared_stmt_count. These variables
751   set the limit and hold the current total number of prepared statements
752   in the server, respectively. As PREPARE/DEALLOCATE rate in a loaded
753   server may be fairly high, we need a dedicated lock.
754 */
755 mysql_mutex_t LOCK_prepared_stmt_count;
756 
757 /*
758  The below two locks are introudced as guards (second mutex) for
759   the global variables sql_slave_skip_counter and slave_net_timeout
760   respectively. See fix_slave_skip_counter/fix_slave_net_timeout
761   for more details
762 */
763 mysql_mutex_t LOCK_sql_slave_skip_counter;
764 mysql_mutex_t LOCK_slave_net_timeout;
765 mysql_mutex_t LOCK_log_throttle_qni;
766 #ifdef HAVE_OPENSSL
767 mysql_mutex_t LOCK_des_key_file;
768 #endif
769 mysql_rwlock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave;
770 mysql_rwlock_t LOCK_system_variables_hash;
771 mysql_cond_t COND_thread_count;
772 pthread_t signal_thread;
773 pthread_attr_t connection_attrib;
774 mysql_mutex_t LOCK_server_started;
775 mysql_cond_t COND_server_started;
776 
777 #ifdef WITH_WSREP
778 mysql_mutex_t LOCK_wsrep_ready;
779 mysql_cond_t  COND_wsrep_ready;
780 mysql_mutex_t LOCK_wsrep_sst;
781 mysql_cond_t  COND_wsrep_sst;
782 mysql_mutex_t LOCK_wsrep_sst_init;
783 mysql_cond_t  COND_wsrep_sst_init;
784 mysql_mutex_t LOCK_wsrep_rollback;
785 mysql_cond_t  COND_wsrep_rollback;
786 wsrep_aborting_thd_t wsrep_aborting_thd= NULL;
787 mysql_mutex_t LOCK_wsrep_replaying;
788 mysql_cond_t  COND_wsrep_replaying;
789 mysql_mutex_t LOCK_wsrep_slave_threads;
790 mysql_mutex_t LOCK_wsrep_desync;
791 int wsrep_replaying= 0;
792 ulong wsrep_running_threads = 0; // # of currently running wsrep threads
793 static void wsrep_close_threads(THD* thd);
794 int mysqld_server_initialized= 0;
795 #endif /* WITH_WSREP */
796 int mysqld_server_started= 0;
797 
798 File_parser_dummy_hook file_parser_dummy_hook;
799 
800 /* replication parameters, if master_host is not NULL, we are a slave */
801 uint report_port= 0;
802 ulong master_retry_count=0;
803 char *master_info_file;
804 char *relay_log_info_file, *report_user, *report_password, *report_host;
805 char *opt_relay_logname = 0, *opt_relaylog_index_name=0;
806 char *opt_logname, *opt_slow_logname, *opt_bin_logname;
807 
808 /* Static variables */
809 
810 static volatile sig_atomic_t kill_in_progress;
811 
812 
813 static my_bool opt_myisam_log;
814 static int cleanup_done;
815 static ulong opt_specialflag;
816 static char *opt_update_logname;
817 char *opt_binlog_index_name;
818 char *mysql_home_ptr, *pidfile_name_ptr;
819 /** Initial command line arguments (count), after load_defaults().*/
820 static int defaults_argc;
821 /**
822   Initial command line arguments (arguments), after load_defaults().
823   This memory is allocated by @c load_defaults() and should be freed
824   using @c free_defaults().
825   Do not modify defaults_argc / defaults_argv,
826   use remaining_argc / remaining_argv instead to parse the command
827   line arguments in multiple steps.
828 */
829 static char **defaults_argv;
830 /** Remaining command line arguments (count), filtered by handle_options().*/
831 static int remaining_argc;
832 /** Remaining command line arguments (arguments), filtered by handle_options().*/
833 static char **remaining_argv;
834 
835 int orig_argc;
836 char **orig_argv;
837 
838 #if defined(HAVE_OPENSSL)
839 bool init_rsa_keys(void);
840 void deinit_rsa_keys(void);
841 int show_rsa_public_key(THD *thd, SHOW_VAR *var, char *buff);
842 #endif
843 
844 static volatile sig_atomic_t global_thread_count= 0;
845 static std::set<THD*> *global_thread_list= NULL;
846 
847 ulong max_blocked_pthreads= 0;
848 static ulong blocked_pthread_count= 0;
849 static std::list<THD*> *waiting_thd_list= NULL;
850 Checkable_rwlock *global_sid_lock= NULL;
851 Sid_map *global_sid_map= NULL;
852 Gtid_state *gtid_state= NULL;
853 
854 /*
855   global_thread_list and waiting_thd_list are both pointers to objects
856   on the heap, to avoid potential problems with running destructors atexit().
857  */
delete_global_thread_list()858 static void delete_global_thread_list()
859 {
860   delete global_thread_list;
861   delete waiting_thd_list;
862   global_thread_list= NULL;
863   waiting_thd_list= NULL;
864 }
865 
global_thread_list_begin()866 Thread_iterator global_thread_list_begin()
867 {
868   mysql_mutex_assert_owner(&LOCK_thread_count);
869   return global_thread_list->begin();
870 }
871 
global_thread_list_end()872 Thread_iterator global_thread_list_end()
873 {
874   mysql_mutex_assert_owner(&LOCK_thread_count);
875   return global_thread_list->end();
876 }
877 
copy_global_thread_list(std::set<THD * > * new_copy)878 void copy_global_thread_list(std::set<THD*> *new_copy)
879 {
880   mysql_mutex_assert_owner(&LOCK_thd_remove);
881   mysql_mutex_lock(&LOCK_thread_count);
882   *new_copy= *global_thread_list;
883   mysql_mutex_unlock(&LOCK_thread_count);
884 }
885 
add_global_thread(THD * thd)886 void add_global_thread(THD *thd)
887 {
888   DBUG_PRINT("info", ("add_global_thread %p", thd));
889   mysql_mutex_assert_owner(&LOCK_thread_count);
890   const bool have_thread=
891     global_thread_list->find(thd) != global_thread_list->end();
892   if (!have_thread)
893   {
894     ++global_thread_count;
895     global_thread_list->insert(thd);
896   }
897   // Adding the same THD twice is an error.
898   DBUG_ASSERT(!have_thread);
899 }
900 
remove_global_thread(THD * thd)901 void remove_global_thread(THD *thd)
902 {
903   DBUG_PRINT("info", ("remove_global_thread %p current_linfo %p",
904                       thd, thd->current_linfo));
905   mysql_mutex_lock(&LOCK_thd_remove);
906   mysql_mutex_lock(&LOCK_thread_count);
907   DBUG_ASSERT(thd->release_resources_done());
908   /*
909     Used by binlog_reset_master.  It would be cleaner to use
910     DEBUG_SYNC here, but that's not possible because the THD's debug
911     sync feature has been shut down at this point.
912    */
913   DBUG_EXECUTE_IF("sleep_after_lock_thread_count_before_delete_thd",
914                   sleep(5););
915 
916   const size_t num_erased= global_thread_list->erase(thd);
917   if (num_erased == 1)
918     --global_thread_count;
919   // Removing a THD that was never added is an error.
920   DBUG_ASSERT(1 == num_erased);
921 
922   mysql_mutex_unlock(&LOCK_thd_remove);
923   mysql_cond_broadcast(&COND_thread_count);
924   mysql_mutex_unlock(&LOCK_thread_count);
925 }
926 
get_thread_count()927 uint get_thread_count()
928 {
929   return (uint) global_thread_count;
930 }
931 
932 
set_remaining_args(int argc,char ** argv)933 void set_remaining_args(int argc, char **argv)
934 {
935   remaining_argc= argc;
936   remaining_argv= argv;
937 }
938 /*
939   Multiple threads of execution use the random state maintained in global
940   sql_rand to generate random numbers. sql_rnd_with_mutex use mutex
941   LOCK_sql_rand to protect sql_rand across multiple instantiations that use
942   sql_rand to generate random numbers.
943  */
sql_rnd_with_mutex()944 ulong sql_rnd_with_mutex()
945 {
946   mysql_mutex_lock(&LOCK_sql_rand);
947   ulong tmp=(ulong) (my_rnd(&sql_rand) * 0xffffffff); /* make all bits random */
948   mysql_mutex_unlock(&LOCK_sql_rand);
949   return tmp;
950 }
951 
952 #ifdef HAVE_PSI_STATEMENT_INTERFACE
953 PSI_statement_info stmt_info_new_packet;
954 #endif
955 
956 #ifndef EMBEDDED_LIBRARY
net_before_header_psi(struct st_net * net,void * user_data,size_t)957 void net_before_header_psi(struct st_net *net, void *user_data, size_t /* unused: count */)
958 {
959   THD *thd;
960   thd= static_cast<THD*> (user_data);
961   DBUG_ASSERT(thd != NULL);
962 
963   if (thd->m_server_idle)
964   {
965     /*
966       The server is IDLE, waiting for the next command.
967       Technically, it is a wait on a socket, which may take a long time,
968       because the call is blocking.
969       Disable the socket instrumentation, to avoid recording a SOCKET event.
970       Instead, start explicitly an IDLE event.
971     */
972     MYSQL_SOCKET_SET_STATE(net->vio->mysql_socket, PSI_SOCKET_STATE_IDLE);
973     MYSQL_START_IDLE_WAIT(thd->m_idle_psi, &thd->m_idle_state);
974   }
975 }
976 
net_after_header_psi(struct st_net * net,void * user_data,size_t,my_bool rc)977 void net_after_header_psi(struct st_net *net, void *user_data, size_t /* unused: count */, my_bool rc)
978 {
979   THD *thd;
980   thd= static_cast<THD*> (user_data);
981   DBUG_ASSERT(thd != NULL);
982 
983   if (thd->m_server_idle)
984   {
985     /*
986       The server just got data for a network packet header,
987       from the network layer.
988       The IDLE event is now complete, since we now have a message to process.
989       We need to:
990       - start a new STATEMENT event
991       - start a new STAGE event, within this statement,
992       - start recording SOCKET WAITS events, within this stage.
993       The proper order is critical to get events numbered correctly,
994       and nested in the proper parent.
995     */
996     MYSQL_END_IDLE_WAIT(thd->m_idle_psi);
997 
998     if (! rc)
999     {
1000       thd->m_statement_psi= MYSQL_START_STATEMENT(&thd->m_statement_state,
1001                                                   stmt_info_new_packet.m_key,
1002                                                   thd->db, thd->db_length,
1003                                                   thd->charset());
1004 
1005       /*
1006         Starts a new stage in performance schema, if compiled in and enabled.
1007         Also sets THD::proc_info (used by SHOW PROCESSLIST, column STATE)
1008       */
1009       THD_STAGE_INFO(thd, stage_init);
1010     }
1011 
1012     /*
1013       TODO: consider recording a SOCKET event for the bytes just read,
1014       by also passing count here.
1015     */
1016     MYSQL_SOCKET_SET_STATE(net->vio->mysql_socket, PSI_SOCKET_STATE_ACTIVE);
1017     thd->m_server_idle= false;
1018   }
1019 }
1020 
init_net_server_extension(THD * thd)1021 void init_net_server_extension(THD *thd)
1022 {
1023   /* Start with a clean state for connection events. */
1024   thd->m_idle_psi= NULL;
1025   thd->m_statement_psi= NULL;
1026   thd->m_server_idle= false;
1027 
1028   /* Hook up the NET_SERVER callback in the net layer. */
1029   thd->m_net_server_extension.m_user_data= thd;
1030   thd->m_net_server_extension.m_before_header= net_before_header_psi;
1031   thd->m_net_server_extension.m_after_header= net_after_header_psi;
1032   /* Activate this private extension for the mysqld server. */
1033   thd->net.extension= & thd->m_net_server_extension;
1034 }
1035 #endif /* EMBEDDED_LIBRARY */
1036 
1037 /**
1038   A log message for the error log, buffered in memory.
1039   Log messages are temporarily buffered when generated before the error log
1040   is initialized, and then printed once the error log is ready.
1041 */
1042 class Buffered_log : public Sql_alloc
1043 {
1044 public:
1045   Buffered_log(enum loglevel level, const char *message);
1046 
~Buffered_log()1047   ~Buffered_log()
1048   {}
1049 
1050   void print(void);
1051 
1052 private:
1053   /** Log message level. */
1054   enum loglevel m_level;
1055   /** Log message text. */
1056   String m_message;
1057 };
1058 
1059 /**
1060   Constructor.
1061   @param level          the message log level
1062   @param message        the message text
1063 */
Buffered_log(enum loglevel level,const char * message)1064 Buffered_log::Buffered_log(enum loglevel level, const char *message)
1065   : m_level(level), m_message()
1066 {
1067   m_message.copy(message, strlen(message), &my_charset_latin1);
1068 }
1069 
1070 /**
1071   Print a buffered log to the real log file.
1072 */
print()1073 void Buffered_log::print()
1074 {
1075   /*
1076     Since messages are buffered, they can be printed out
1077     of order with other entries in the log.
1078     Add "Buffered xxx" to the message text to prevent confusion.
1079   */
1080   switch(m_level)
1081   {
1082   case ERROR_LEVEL:
1083     sql_print_error("Buffered error: %s\n", m_message.c_ptr_safe());
1084     break;
1085   case WARNING_LEVEL:
1086     sql_print_warning("Buffered warning: %s\n", m_message.c_ptr_safe());
1087     break;
1088   case INFORMATION_LEVEL:
1089     /*
1090       Messages printed as "information" still end up in the mysqld *error* log,
1091       but with a [Note] tag instead of an [ERROR] tag.
1092       While this is probably fine for a human reading the log,
1093       it is upsetting existing automated scripts used to parse logs,
1094       because such scripts are likely to not already handle [Note] properly.
1095       INFORMATION_LEVEL messages are simply silenced, on purpose,
1096       to avoid un needed verbosity.
1097     */
1098     break;
1099   }
1100 }
1101 
1102 /**
1103   Collection of all the buffered log messages.
1104 */
1105 class Buffered_logs
1106 {
1107 public:
Buffered_logs()1108   Buffered_logs()
1109   {}
1110 
~Buffered_logs()1111   ~Buffered_logs()
1112   {}
1113 
1114   void init();
1115   void cleanup();
1116 
1117   void buffer(enum loglevel m_level, const char *msg);
1118   void print();
1119 private:
1120   /**
1121     Memory root to use to store buffered logs.
1122     This memory root lifespan is between init and cleanup.
1123     Once the buffered logs are printed, they are not needed anymore,
1124     and all the memory used is reclaimed.
1125   */
1126   MEM_ROOT m_root;
1127   /** List of buffered log messages. */
1128   List<Buffered_log> m_list;
1129 };
1130 
init()1131 void Buffered_logs::init()
1132 {
1133   init_alloc_root(&m_root, 1024, 0);
1134 }
1135 
cleanup()1136 void Buffered_logs::cleanup()
1137 {
1138   m_list.delete_elements();
1139   free_root(&m_root, MYF(0));
1140 }
1141 
1142 /**
1143   Add a log message to the buffer.
1144 */
buffer(enum loglevel level,const char * msg)1145 void Buffered_logs::buffer(enum loglevel level, const char *msg)
1146 {
1147   /*
1148     Do not let Sql_alloc::operator new(size_t) allocate memory,
1149     there is no memory root associated with the main() thread.
1150     Give explicitly the proper memory root to use to
1151     Sql_alloc::operator new(size_t, MEM_ROOT *) instead.
1152   */
1153   Buffered_log *log= new (&m_root) Buffered_log(level, msg);
1154   if (log)
1155     m_list.push_back(log, &m_root);
1156 }
1157 
1158 /**
1159   Print buffered log messages.
1160 */
print()1161 void Buffered_logs::print()
1162 {
1163   Buffered_log *log;
1164   List_iterator_fast<Buffered_log> it(m_list);
1165   while ((log= it++))
1166     log->print();
1167 }
1168 
1169 /** Logs reported before a logger is available. */
1170 static Buffered_logs buffered_logs;
1171 
1172 /**
1173   Error reporter that buffer log messages.
1174   @param level          log message level
1175   @param format         log message format string
1176 */
1177 C_MODE_START
buffered_option_error_reporter(enum loglevel level,const char * format,...)1178 static void buffered_option_error_reporter(enum loglevel level,
1179                                            const char *format, ...)
1180 {
1181   va_list args;
1182   char buffer[1024];
1183 
1184   va_start(args, format);
1185   my_vsnprintf(buffer, sizeof(buffer), format, args);
1186   va_end(args);
1187   buffered_logs.buffer(level, buffer);
1188 }
1189 
1190 
1191 /**
1192   Character set and collation error reporter that prints to sql error log.
1193   @param level          log message level
1194   @param format         log message format string
1195 
1196   This routine is used to print character set and collation
1197   warnings and errors inside an already running mysqld server,
1198   e.g. when a character set or collation is requested for the very first time
1199   and its initialization does not go well for some reasons.
1200 
1201   Note: At early mysqld initialization stage,
1202   when error log is not yet available,
1203   we use buffered_option_error_reporter() instead,
1204   to print general character set subsystem initialization errors,
1205   such as Index.xml syntax problems, bad XML tag hierarchy, etc.
1206 */
charset_error_reporter(enum loglevel level,const char * format,...)1207 static void charset_error_reporter(enum loglevel level,
1208                                    const char *format, ...)
1209 {
1210   va_list args;
1211   va_start(args, format);
1212   vprint_msg_to_log(level, format, args);
1213   va_end(args);
1214 }
1215 C_MODE_END
1216 
1217 static MYSQL_SOCKET unix_sock, ip_sock;
1218 struct rand_struct sql_rand; ///< used by sql_class.cc:THD::THD()
1219 
1220 #ifndef EMBEDDED_LIBRARY
1221 struct passwd *user_info;
1222 static pthread_t select_thread;
1223 static uint thr_kill_signal;
1224 #endif
1225 
1226 /* OS specific variables */
1227 
1228 #ifdef __WIN__
1229 #undef   getpid
1230 #include <process.h>
1231 
1232 static mysql_cond_t COND_handler_count;
1233 static uint handler_count;
1234 static bool start_mode=0, use_opt_args;
1235 static int opt_argc;
1236 static char **opt_argv;
1237 
1238 #if !defined(EMBEDDED_LIBRARY)
1239 static HANDLE hEventShutdown;
1240 static char shutdown_event_name[40];
1241 #include "nt_servc.h"
1242 static   NTService  Service;        ///< Service object for WinNT
1243 #endif /* EMBEDDED_LIBRARY */
1244 #endif /* __WIN__ */
1245 
1246 #ifdef _WIN32
1247 static char pipe_name[512];
1248 #include <Aclapi.h>
1249 #include "named_pipe.h"
1250 static SECURITY_ATTRIBUTES saPipeSecurity;
1251 static SECURITY_DESCRIPTOR sdPipeDescriptor;
1252 static SECURITY_ATTRIBUTES *psaPipeSecurity;
1253 static HANDLE hPipe = INVALID_HANDLE_VALUE;
1254 mysql_rwlock_t LOCK_named_pipe_full_access_group;
1255 char *named_pipe_full_access_group;
1256 #endif
1257 
1258 #ifndef EMBEDDED_LIBRARY
1259 bool mysqld_embedded=0;
1260 #else
1261 bool mysqld_embedded=1;
1262 #endif
1263 
1264 #ifndef EMBEDDED_LIBRARY
1265 static my_bool plugins_are_initialized= FALSE;
1266 #endif
1267 
1268 #ifndef DBUG_OFF
1269 static const char* default_dbug_option;
1270 #endif
1271 #ifdef HAVE_LIBWRAP
1272 const char *libwrapName= NULL;
1273 int allow_severity = LOG_INFO;
1274 int deny_severity = LOG_WARNING;
1275 #endif /* HAVE_LIBWRAP */
1276 #ifdef HAVE_QUERY_CACHE
1277 ulong query_cache_min_res_unit= QUERY_CACHE_MIN_RESULT_DATA_SIZE;
1278 Query_cache query_cache;
1279 #endif
1280 #ifdef HAVE_SMEM
1281 char *shared_memory_base_name= default_shared_memory_base_name;
1282 my_bool opt_enable_shared_memory;
1283 HANDLE smem_event_connect_request= 0;
1284 #endif
1285 
1286 my_bool opt_use_ssl  = 0;
1287 char *opt_ssl_ca= NULL, *opt_ssl_capath= NULL, *opt_ssl_cert= NULL,
1288      *opt_ssl_cipher= NULL, *opt_ssl_key= NULL, *opt_ssl_crl= NULL,
1289      *opt_ssl_crlpath= NULL;
1290 
1291 #ifdef HAVE_OPENSSL
1292 #if OPENSSL_VERSION_NUMBER < 0x10100000L
1293 #include <openssl/crypto.h>
1294 typedef struct CRYPTO_dynlock_value
1295 {
1296   mysql_rwlock_t lock;
1297 } openssl_lock_t;
1298 
1299 static openssl_lock_t *openssl_stdlocks;
1300 static openssl_lock_t *openssl_dynlock_create(const char *, int);
1301 static void openssl_dynlock_destroy(openssl_lock_t *, const char *, int);
1302 static void openssl_lock_function(int, int, const char *, int);
1303 static void openssl_lock(int, openssl_lock_t *, const char *, int);
1304 static unsigned long openssl_id_function();
1305 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
1306 
1307 char *des_key_file;
1308 #ifndef EMBEDDED_LIBRARY
1309 struct st_VioSSLFd *ssl_acceptor_fd;
1310 #endif
1311 #endif /* HAVE_OPENSSL */
1312 
1313 /**
1314   Number of currently active user connections. The variable is protected by
1315   LOCK_connection_count.
1316 */
1317 uint connection_count= 0;
1318 mysql_cond_t COND_connection_count;
1319 
1320 /* Function declarations */
1321 
1322 pthread_handler_t signal_hand(void *arg);
1323 static int mysql_init_variables(void);
1324 static int get_options(int *argc_ptr, char ***argv_ptr);
1325 static void add_terminator(vector<my_option> *options);
1326 extern "C" my_bool mysqld_get_one_option(int, const struct my_option *, char *);
1327 static void set_server_version(void);
1328 static int init_thread_environment();
1329 static char *get_relative_path(const char *path);
1330 static int fix_paths(void);
1331 void handle_connections_sockets();
1332 #ifdef _WIN32
1333 pthread_handler_t handle_connections_sockets_thread(void *arg);
1334 #endif
1335 pthread_handler_t kill_server_thread(void *arg);
1336 static void bootstrap(MYSQL_FILE *file);
1337 static bool read_init_file(char *file_name);
1338 #ifdef _WIN32
1339 pthread_handler_t handle_connections_namedpipes(void *arg);
1340 #endif
1341 #ifdef HAVE_SMEM
1342 pthread_handler_t handle_connections_shared_memory(void *arg);
1343 #endif
1344 pthread_handler_t handle_slave(void *arg);
1345 static void clean_up(bool print_message);
1346 static int test_if_case_insensitive(const char *dir_name);
1347 
1348 #ifndef EMBEDDED_LIBRARY
1349 static bool pid_file_created= false;
1350 static void usage(void);
1351 static void start_signal_handler(void);
1352 static void close_server_sock();
1353 static void clean_up_mutexes(void);
1354 static void wait_for_signal_thread_to_end(void);
1355 static void create_pid_file();
1356 static void mysqld_exit(int exit_code) MY_ATTRIBUTE((noreturn));
1357 #endif
1358 static void delete_pid_file(myf flags);
1359 static void end_ssl();
1360 
1361 
1362 #ifndef EMBEDDED_LIBRARY
1363 /****************************************************************************
1364 ** Code to end mysqld
1365 ****************************************************************************/
1366 
close_connections(void)1367 static void close_connections(void)
1368 {
1369 #ifdef EXTRA_DEBUG
1370   int count=0;
1371 #endif
1372   DBUG_ENTER("close_connections");
1373 
1374   /* Kill blocked pthreads */
1375   kill_blocked_pthreads_flag++;
1376   kill_blocked_pthreads();
1377   uint dump_thread_count= 0;
1378   uint dump_thread_kill_retries= 8;
1379   /* kill connection thread */
1380 #if !defined(__WIN__)
1381   DBUG_PRINT("quit", ("waiting for select thread: 0x%lx",
1382                       (ulong) select_thread));
1383   mysql_mutex_lock(&LOCK_thread_count);
1384 
1385   while (select_thread_in_use)
1386   {
1387     struct timespec abstime;
1388     int error;
1389     LINT_INIT(error);
1390     DBUG_PRINT("info",("Waiting for select thread"));
1391 
1392 #ifndef DONT_USE_THR_ALARM
1393     if (pthread_kill(select_thread, thr_client_alarm))
1394       break;          // allready dead
1395 #endif
1396     set_timespec(abstime, 2);
1397     for (uint tmp=0 ; tmp < 10 && select_thread_in_use; tmp++)
1398     {
1399       error= mysql_cond_timedwait(&COND_thread_count, &LOCK_thread_count,
1400                                   &abstime);
1401       if (error != EINTR)
1402   break;
1403     }
1404 #ifdef EXTRA_DEBUG
1405     if (error != 0 && !count++)
1406       sql_print_error("Got error %d from mysql_cond_timedwait", error);
1407 #endif
1408     close_server_sock();
1409   }
1410   mysql_mutex_unlock(&LOCK_thread_count);
1411 #endif /* __WIN__ */
1412 
1413 
1414   /* Abort listening to new connections */
1415   DBUG_PRINT("quit",("Closing sockets"));
1416   if (!opt_disable_networking )
1417   {
1418     if (mysql_socket_getfd(ip_sock) != INVALID_SOCKET)
1419     {
1420       (void) mysql_socket_shutdown(ip_sock, SHUT_RDWR);
1421       (void) mysql_socket_close(ip_sock);
1422       ip_sock= MYSQL_INVALID_SOCKET;
1423     }
1424   }
1425 #ifdef _WIN32
1426   if (hPipe != INVALID_HANDLE_VALUE && opt_enable_named_pipe)
1427   {
1428     HANDLE temp;
1429     DBUG_PRINT("quit", ("Closing named pipes") );
1430 
1431     /* Create connection to the handle named pipe handler to break the loop */
1432     if ((temp = CreateFile(pipe_name,
1433          GENERIC_READ | GENERIC_WRITE,
1434          0,
1435          NULL,
1436          OPEN_EXISTING,
1437          0,
1438          NULL )) != INVALID_HANDLE_VALUE)
1439     {
1440       WaitNamedPipe(pipe_name, 1000);
1441       DWORD dwMode = PIPE_READMODE_BYTE | PIPE_WAIT;
1442       SetNamedPipeHandleState(temp, &dwMode, NULL, NULL);
1443       CancelIo(temp);
1444       DisconnectNamedPipe(temp);
1445       CloseHandle(temp);
1446     }
1447   }
1448 #endif
1449 #ifdef HAVE_SYS_UN_H
1450   if (mysql_socket_getfd(unix_sock) != INVALID_SOCKET)
1451   {
1452     (void) mysql_socket_shutdown(unix_sock, SHUT_RDWR);
1453     (void) mysql_socket_close(unix_sock);
1454     (void) unlink(mysqld_unix_port);
1455     unix_sock= MYSQL_INVALID_SOCKET;
1456   }
1457 #endif
1458   end_thr_alarm(0);      // Abort old alarms.
1459 
1460   /*
1461     First signal all threads that it's time to die
1462     This will give the threads some time to gracefully abort their
1463     statements and inform their clients that the server is about to die.
1464   */
1465 
1466   sql_print_information("Giving %d client threads a chance to die gracefully",
1467                         static_cast<int>(get_thread_count()));
1468 
1469   mysql_mutex_lock(&LOCK_thread_count);
1470 
1471   Thread_iterator it= global_thread_list->begin();
1472   for (; it != global_thread_list->end(); ++it)
1473   {
1474     THD *tmp= *it;
1475     DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
1476                        tmp->thread_id));
1477     /* We skip slave threads & scheduler on this first loop through. */
1478     if (tmp->slave_thread)
1479       continue;
1480 #ifdef WITH_WSREP
1481     /* skip wsrep system threads as well */
1482     if (WSREP(tmp) && (tmp->wsrep_exec_mode==REPL_RECV || tmp->wsrep_applier))
1483       continue;
1484 #endif /* WITH_WSREP */
1485     if (tmp->get_command() == COM_BINLOG_DUMP ||
1486         tmp->get_command() == COM_BINLOG_DUMP_GTID)
1487     {
1488       ++dump_thread_count;
1489       continue;
1490     }
1491     tmp->killed= THD::KILL_CONNECTION;
1492     DBUG_EXECUTE_IF("Check_dump_thread_is_alive",
1493                     {
1494                       DBUG_ASSERT(tmp->get_command() != COM_BINLOG_DUMP &&
1495                                   tmp->get_command() != COM_BINLOG_DUMP_GTID);
1496                     };);
1497     MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (tmp));
1498     mysql_mutex_lock(&tmp->LOCK_thd_data);
1499     if (tmp->mysys_var)
1500     {
1501       tmp->mysys_var->abort=1;
1502       mysql_mutex_lock(&tmp->mysys_var->mutex);
1503       if (tmp->mysys_var->current_cond)
1504       {
1505         mysql_mutex_lock(tmp->mysys_var->current_mutex);
1506         mysql_cond_broadcast(tmp->mysys_var->current_cond);
1507         mysql_mutex_unlock(tmp->mysys_var->current_mutex);
1508       }
1509       mysql_mutex_unlock(&tmp->mysys_var->mutex);
1510     }
1511     mysql_mutex_unlock(&tmp->LOCK_thd_data);
1512   }
1513   mysql_mutex_unlock(&LOCK_thread_count);
1514 
1515   Events::deinit();
1516 
1517   sql_print_information("Shutting down slave threads");
1518   end_slave();
1519 
1520   if (dump_thread_count)
1521   {
1522     /*
1523       Replication dump thread should be terminated after the clients are
1524       terminated. Wait for few more seconds for other sessions to end.
1525      */
1526     while (get_thread_count() > dump_thread_count && dump_thread_kill_retries)
1527     {
1528       sleep(1);
1529       dump_thread_kill_retries--;
1530     }
1531     mysql_mutex_lock(&LOCK_thread_count);
1532     for (it= global_thread_list->begin(); it != global_thread_list->end(); ++it)
1533     {
1534       THD *tmp= *it;
1535       DBUG_PRINT("quit",("Informing dump thread %ld that it's time to die",
1536                          tmp->thread_id));
1537       if (tmp->get_command() == COM_BINLOG_DUMP ||
1538           tmp->get_command() == COM_BINLOG_DUMP_GTID)
1539       {
1540         tmp->killed= THD::KILL_CONNECTION;
1541         MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (tmp));
1542         mysql_mutex_lock(&tmp->LOCK_thd_data);
1543         if (tmp->mysys_var)
1544         {
1545           tmp->mysys_var->abort= 1;
1546           mysql_mutex_lock(&tmp->mysys_var->mutex);
1547           if (tmp->mysys_var->current_cond)
1548           {
1549             mysql_mutex_lock(tmp->mysys_var->current_mutex);
1550             mysql_cond_broadcast(tmp->mysys_var->current_cond);
1551             mysql_mutex_unlock(tmp->mysys_var->current_mutex);
1552           }
1553           mysql_mutex_unlock(&tmp->mysys_var->mutex);
1554         }
1555         mysql_mutex_unlock(&tmp->LOCK_thd_data);
1556       }
1557     }
1558     mysql_mutex_unlock(&LOCK_thread_count);
1559   }
1560   if (get_thread_count() > 0)
1561     sleep(2);         // Give threads time to die
1562 
1563   /*
1564     Force remaining threads to die by closing the connection to the client
1565     This will ensure that threads that are waiting for a command from the
1566     client on a blocking read call are aborted.
1567   */
1568 
1569   sql_print_information("Forcefully disconnecting %d remaining clients",
1570                         static_cast<int>(get_thread_count()));
1571 
1572 #ifndef __bsdi__ // Bug in BSDI kernel
1573   DBUG_PRINT("quit", ("Locking LOCK_thread_count"));
1574   mysql_mutex_lock(&LOCK_thread_count);
1575   for (it= global_thread_list->begin(); it != global_thread_list->end(); ++it)
1576   {
1577     THD *tmp= *it;
1578     if (tmp->vio_ok())
1579     {
1580       if (log_warnings)
1581         sql_print_warning(ER_DEFAULT(ER_FORCING_CLOSE),my_progname,
1582                           tmp->thread_id,
1583                           (tmp->main_security_ctx.user ?
1584                            tmp->main_security_ctx.user : ""));
1585       close_connection(tmp);
1586     }
1587 #ifdef WITH_WSREP
1588     /*
1589      * TODO: this code block may turn out redundant. wsrep->disconnect()
1590      *       should terminate slave threads gracefully, and we don't need
1591      *       to signal them here.
1592      *       The code here makes sure mysqld will not hang during shutdown
1593      *       even if wsrep provider has problems in shutting down.
1594      */
1595     if (WSREP(tmp) && tmp->wsrep_exec_mode==REPL_RECV)
1596     {
1597       sql_print_information("closing wsrep system thread");
1598       tmp->killed= THD::KILL_CONNECTION;
1599       MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (tmp));
1600       if (tmp->mysys_var)
1601       {
1602 	tmp->mysys_var->abort=1;
1603 	mysql_mutex_lock(&tmp->mysys_var->mutex);
1604 	if (tmp->mysys_var->current_cond)
1605         {
1606 	  mysql_mutex_lock(tmp->mysys_var->current_mutex);
1607 	  mysql_cond_broadcast(tmp->mysys_var->current_cond);
1608 	  mysql_mutex_unlock(tmp->mysys_var->current_mutex);
1609 	}
1610 	mysql_mutex_unlock(&tmp->mysys_var->mutex);
1611       }
1612     }
1613 #endif
1614   }
1615   DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
1616   mysql_mutex_unlock(&LOCK_thread_count);
1617 #endif // Bug in BSDI kernel
1618 
1619   /* All threads has now been aborted */
1620   DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",
1621                      get_thread_count()));
1622   mysql_mutex_lock(&LOCK_thread_count);
1623   while (get_thread_count() > 0)
1624   {
1625     mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
1626     DBUG_PRINT("quit", ("One thread died (count=%u)", get_thread_count()));
1627   }
1628   mysql_mutex_unlock(&LOCK_thread_count);
1629 
1630   /*
1631     Connection threads might take a little while to go down after removing from
1632     global thread list. Give it some time.
1633   */
1634   mysql_mutex_lock(&LOCK_connection_count);
1635   while (connection_count > 0)
1636   {
1637     mysql_cond_wait(&COND_connection_count, &LOCK_connection_count);
1638   }
1639   mysql_mutex_unlock(&LOCK_connection_count);
1640 
1641   close_active_mi();
1642   DBUG_PRINT("quit",("close_connections thread"));
1643   DBUG_VOID_RETURN;
1644 }
1645 
1646 
close_server_sock()1647 static void close_server_sock()
1648 {
1649 #ifdef HAVE_CLOSE_SERVER_SOCK
1650   DBUG_ENTER("close_server_sock");
1651   MYSQL_SOCKET tmp_sock;
1652   tmp_sock=ip_sock;
1653   if (mysql_socket_getfd(tmp_sock) != INVALID_SOCKET)
1654   {
1655     ip_sock= MYSQL_INVALID_SOCKET;
1656     DBUG_PRINT("info",("calling shutdown on TCP/IP socket"));
1657     (void) mysql_socket_shutdown(tmp_sock, SHUT_RDWR);
1658   }
1659   tmp_sock=unix_sock;
1660   if (mysql_socket_getfd(tmp_sock) != INVALID_SOCKET)
1661   {
1662     unix_sock= MYSQL_INVALID_SOCKET;
1663     DBUG_PRINT("info",("calling shutdown on unix socket"));
1664     (void) mysql_socket_shutdown(tmp_sock, SHUT_RDWR);
1665     (void) unlink(mysqld_unix_port);
1666   }
1667   DBUG_VOID_RETURN;
1668 #endif
1669 }
1670 
1671 #endif /*EMBEDDED_LIBRARY*/
1672 
1673 
kill_mysql(void)1674 void kill_mysql(void)
1675 {
1676   DBUG_ENTER("kill_mysql");
1677 
1678 #if defined(SIGNALS_DONT_BREAK_READ) && !defined(EMBEDDED_LIBRARY)
1679   abort_loop=1;         // Break connection loops
1680   close_server_sock();        // Force accept to wake up
1681 #endif
1682 
1683 #if defined(__WIN__)
1684 #if !defined(EMBEDDED_LIBRARY)
1685   {
1686     if (!SetEvent(hEventShutdown))
1687     {
1688       DBUG_PRINT("error",("Got error: %ld from SetEvent",GetLastError()));
1689     }
1690     /*
1691       or:
1692       HANDLE hEvent=OpenEvent(0, FALSE, "MySqlShutdown");
1693       SetEvent(hEventShutdown);
1694       CloseHandle(hEvent);
1695     */
1696   }
1697 #endif
1698 #elif defined(HAVE_PTHREAD_KILL)
1699   if (pthread_kill(signal_thread, MYSQL_KILL_SIGNAL))
1700   {
1701     DBUG_PRINT("error",("Got error %d from pthread_kill",errno)); /* purecov: inspected */
1702   }
1703 #elif !defined(SIGNALS_DONT_BREAK_READ)
1704   kill(current_pid, MYSQL_KILL_SIGNAL);
1705 #endif
1706   DBUG_PRINT("quit",("After pthread_kill"));
1707   shutdown_in_progress=1;     // Safety if kill didn't work
1708 #ifdef SIGNALS_DONT_BREAK_READ
1709   if (!kill_in_progress)
1710   {
1711     pthread_t tmp;
1712     int error;
1713     abort_loop=1;
1714     if ((error= mysql_thread_create(0, /* Not instrumented */
1715                                     &tmp, &connection_attrib,
1716                                     kill_server_thread, (void*) 0)))
1717       sql_print_error("Can't create thread to kill server (errno= %d).", error);
1718   }
1719 #endif
1720   DBUG_VOID_RETURN;
1721 }
1722 
1723 /**
1724   Force server down. Kill all connections and threads and exit.
1725 
1726   @param  sig_ptr       Signal number that caused kill_server to be called.
1727 
1728   @note
1729     A signal number of 0 mean that the function was not called
1730     from a signal handler and there is thus no signal to block
1731     or stop, we just want to kill the server.
1732 */
1733 
1734 #if !defined(__WIN__)
kill_server(void * sig_ptr)1735 static void *kill_server(void *sig_ptr)
1736 #define RETURN_FROM_KILL_SERVER return 0
1737 #else
1738 static void __cdecl kill_server(int sig_ptr)
1739 #define RETURN_FROM_KILL_SERVER return
1740 #endif
1741 {
1742   DBUG_ENTER("kill_server");
1743 #ifndef EMBEDDED_LIBRARY
1744   int sig=(int) (long) sig_ptr;     // This is passed a int
1745   // if there is a signal during the kill in progress, ignore the other
1746   if (kill_in_progress)       // Safety
1747   {
1748     DBUG_LEAVE;
1749     RETURN_FROM_KILL_SERVER;
1750   }
1751   kill_in_progress=TRUE;
1752   abort_loop=1;         // This should be set
1753   if (sig != 0) // 0 is not a valid signal number
1754     my_sigset(sig, SIG_IGN);                    /* purify inspected */
1755   if (sig == MYSQL_KILL_SIGNAL || sig == 0)
1756     sql_print_information(ER_DEFAULT(ER_NORMAL_SHUTDOWN),my_progname);
1757   else
1758     sql_print_error(ER_DEFAULT(ER_GOT_SIGNAL),my_progname,sig); /* purecov: inspected */
1759 
1760 #if defined(HAVE_SMEM) && defined(__WIN__)
1761   /*
1762    Send event to smem_event_connect_request for aborting
1763    */
1764   if (opt_enable_shared_memory)
1765   {
1766     if (!SetEvent(smem_event_connect_request))
1767     {
1768       DBUG_PRINT("error",
1769                  ("Got error: %ld from SetEvent of smem_event_connect_request",
1770                   GetLastError()));
1771     }
1772   }
1773 #endif
1774 #ifdef WITH_WSREP
1775   /* Stop wsrep threads in case they are running. */
1776   if (wsrep_running_threads > 0)
1777   {
1778     wsrep_stop_replication(NULL);
1779   }
1780 #endif
1781 
1782   close_connections();
1783 #ifdef WITH_WSREP
1784   if (WSREP_ON) wsrep_deinit();
1785 #endif
1786   if (sig != MYSQL_KILL_SIGNAL &&
1787       sig != 0)
1788     unireg_abort(1);        /* purecov: inspected */
1789   else
1790     unireg_end();
1791 
1792   /* purecov: begin deadcode */
1793   DBUG_LEAVE;                                   // Must match DBUG_ENTER()
1794   my_thread_end();
1795   pthread_exit(0);
1796   /* purecov: end */
1797 
1798   RETURN_FROM_KILL_SERVER;                      // Avoid compiler warnings
1799 
1800 #else /* EMBEDDED_LIBRARY*/
1801 
1802   DBUG_LEAVE;
1803   RETURN_FROM_KILL_SERVER;
1804 
1805 #endif /* EMBEDDED_LIBRARY */
1806 }
1807 
1808 
1809 #if defined(USE_ONE_SIGNAL_HAND)
kill_server_thread(void * arg MY_ATTRIBUTE ((unused)))1810 pthread_handler_t kill_server_thread(void *arg MY_ATTRIBUTE((unused)))
1811 {
1812   my_thread_init();       // Initialize new thread
1813   kill_server(0);
1814   /* purecov: begin deadcode */
1815   my_thread_end();
1816   pthread_exit(0);
1817   return 0;
1818   /* purecov: end */
1819 }
1820 #endif
1821 
1822 
print_signal_warning(int sig)1823 extern "C" sig_handler print_signal_warning(int sig)
1824 {
1825   if (log_warnings)
1826     sql_print_warning("Got signal %d from thread %ld", sig,my_thread_id());
1827 #ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY
1828   my_sigset(sig,print_signal_warning);    /* int. thread system calls */
1829 #endif
1830 #if !defined(__WIN__)
1831   if (sig == SIGALRM)
1832     alarm(2);         /* reschedule alarm */
1833 #endif
1834 }
1835 
1836 #ifndef EMBEDDED_LIBRARY
1837 
init_error_log_mutex()1838 static void init_error_log_mutex()
1839 {
1840   mysql_mutex_init(key_LOCK_error_log, &LOCK_error_log, MY_MUTEX_INIT_FAST);
1841 }
1842 
1843 
clean_up_error_log_mutex()1844 static void clean_up_error_log_mutex()
1845 {
1846   mysql_mutex_destroy(&LOCK_error_log);
1847 }
1848 
1849 
1850 /**
1851   cleanup all memory and end program nicely.
1852 
1853     If SIGNALS_DONT_BREAK_READ is defined, this function is called
1854     by the main thread. To get MySQL to shut down nicely in this case
1855     (Mac OS X) we have to call exit() instead if pthread_exit().
1856 
1857   @note
1858     This function never returns.
1859 */
unireg_end(void)1860 void unireg_end(void)
1861 {
1862   clean_up(1);
1863   my_thread_end();
1864 #if defined(SIGNALS_DONT_BREAK_READ)
1865   exit(0);
1866 #else
1867   pthread_exit(0);        // Exit is in main thread
1868 #endif
1869 }
1870 
1871 
unireg_abort(int exit_code)1872 extern "C" void unireg_abort(int exit_code)
1873 {
1874   DBUG_ENTER("unireg_abort");
1875 
1876   if (opt_help)
1877     usage();
1878   if (exit_code)
1879     sql_print_error("Aborting\n");
1880 
1881 #ifdef WITH_WSREP
1882   if (wsrep)
1883   {
1884     /* This is an abort situation, we cannot expect to gracefully close all
1885      * wsrep threads here, we can only diconnect from service */
1886     wsrep_close_client_connections(FALSE);
1887     shutdown_in_progress= 1;
1888     THD* thd(0);
1889     wsrep->disconnect(wsrep);
1890     WSREP_INFO("Service disconnected.");
1891     wsrep_close_threads(thd); /* this won't close all threads */
1892     sleep(1); /* so give some time to exit for those which can */
1893     WSREP_INFO("Some threads may fail to exit.");
1894     /* Signal possible SE initialization waiters with error. */
1895     wsrep_SE_initialized(WSREP_SE_INIT_RESULT_FAILURE);
1896     wsrep_deinit();
1897   }
1898 #endif // WITH_WSREP
1899 
1900   clean_up(!opt_help && (exit_code || !opt_bootstrap)); /* purecov: inspected */
1901   DBUG_PRINT("quit",("done with cleanup in unireg_abort"));
1902   mysqld_exit(exit_code);
1903 }
1904 
mysqld_exit(int exit_code)1905 static void mysqld_exit(int exit_code)
1906 {
1907   /*
1908     Important note: we wait for the signal thread to end,
1909     but if a kill -15 signal was sent, the signal thread did
1910     spawn the kill_server_thread thread, which is running concurrently.
1911   */
1912   wait_for_signal_thread_to_end();
1913   mysql_audit_finalize();
1914   clean_up_mutexes();
1915   clean_up_error_log_mutex();
1916 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
1917   shutdown_performance_schema();
1918 #endif
1919   my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
1920   exit(exit_code); /* purecov: inspected */
1921 }
1922 
1923 #endif /* !EMBEDDED_LIBRARY */
1924 
1925 /**
1926    GTID cleanup destroys objects and reset their pointer.
1927    Function is reentrant.
1928 */
gtid_server_cleanup()1929 void gtid_server_cleanup()
1930 {
1931   delete gtid_state;
1932   delete global_sid_map;
1933   delete global_sid_lock;
1934   global_sid_lock= NULL;
1935   global_sid_map= NULL;
1936   gtid_state= NULL;
1937 }
1938 
1939 /**
1940    GTID initialization.
1941 
1942    @return true if allocation does not succeed
1943            false if OK
1944 */
gtid_server_init()1945 bool gtid_server_init()
1946 {
1947   bool res=
1948     (!(global_sid_lock= new Checkable_rwlock) ||
1949      !(global_sid_map= new Sid_map(global_sid_lock)) ||
1950      !(gtid_state= new Gtid_state(global_sid_lock, global_sid_map)));
1951   if (res)
1952   {
1953     gtid_server_cleanup();
1954   }
1955   return res;
1956 }
1957 
1958 
clean_up(bool print_message)1959 void clean_up(bool print_message)
1960 {
1961   DBUG_PRINT("exit",("clean_up"));
1962   if (cleanup_done++)
1963     return; /* purecov: inspected */
1964 
1965   stop_handle_manager();
1966   release_ddl_log();
1967 
1968   memcached_shutdown();
1969 
1970   /*
1971     make sure that handlers finish up
1972     what they have that is dependent on the binlog
1973   */
1974   if ((opt_help == 0) || (opt_verbose > 0))
1975     sql_print_information("Binlog end");
1976   ha_binlog_end(current_thd);
1977 
1978   logger.cleanup_base();
1979 
1980   injector::free_instance();
1981   mysql_bin_log.cleanup();
1982   gtid_server_cleanup();
1983 
1984 #ifdef HAVE_REPLICATION
1985   if (use_slave_mask)
1986     bitmap_free(&slave_error_mask);
1987 #endif
1988   my_tz_free();
1989   my_dboptions_cache_free();
1990   ignore_db_dirs_free();
1991 #ifndef NO_EMBEDDED_ACCESS_CHECKS
1992   servers_free(1);
1993   acl_free(1);
1994   grant_free();
1995 #endif
1996   query_cache_destroy();
1997   hostname_cache_free();
1998   item_user_lock_free();
1999   lex_free();       /* Free some memory */
2000   item_create_cleanup();
2001   if (!opt_noacl)
2002   {
2003 #ifdef HAVE_DLOPEN
2004     udf_free();
2005 #endif
2006   }
2007   table_def_start_shutdown();
2008   plugin_shutdown();
2009   ha_end();
2010   if (tc_log)
2011     tc_log->close();
2012   delegates_destroy();
2013   xid_cache_free();
2014   table_def_free();
2015   mdl_destroy();
2016   key_caches.delete_elements((void (*)(const char*, uchar*)) free_key_cache);
2017   multi_keycache_free();
2018   free_status_vars();
2019   end_thr_alarm(1);     /* Free allocated memory */
2020   my_free_open_file_info();
2021   if (defaults_argv)
2022     free_defaults(defaults_argv);
2023   free_tmpdir(&mysql_tmpdir_list);
2024   my_free(opt_bin_logname);
2025   bitmap_free(&temp_pool);
2026   free_max_user_conn();
2027 #ifdef HAVE_REPLICATION
2028   end_slave_list();
2029 #endif
2030   delete binlog_filter;
2031   delete rpl_filter;
2032   end_ssl();
2033   vio_end();
2034   my_regex_end();
2035 #if defined(ENABLED_DEBUG_SYNC)
2036   /* End the debug sync facility. See debug_sync.cc. */
2037   debug_sync_end();
2038 #endif /* defined(ENABLED_DEBUG_SYNC) */
2039 
2040   delete_pid_file(MYF(0));
2041 
2042   if (print_message && my_default_lc_messages && server_start_time)
2043     sql_print_information(ER_DEFAULT(ER_SHUTDOWN_COMPLETE),my_progname);
2044   cleanup_errmsgs();
2045   MYSQL_CALLBACK(thread_scheduler, end, ());
2046   mysql_client_plugin_deinit();
2047   finish_client_errs();
2048   (void) my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST); // finish server errs
2049   DBUG_PRINT("quit", ("Error messages freed"));
2050   /* Tell main we are ready */
2051   logger.cleanup_end();
2052   my_atomic_rwlock_destroy(&opt_binlog_max_flush_queue_time_lock);
2053   my_atomic_rwlock_destroy(&global_query_id_lock);
2054   my_atomic_rwlock_destroy(&thread_running_lock);
2055   free_charsets();
2056   mysql_mutex_lock(&LOCK_thread_count);
2057   DBUG_PRINT("quit", ("got thread count lock"));
2058   ready_to_exit=1;
2059   /* do the broadcast inside the lock to ensure that my_end() is not called */
2060   mysql_cond_broadcast(&COND_thread_count);
2061   mysql_mutex_unlock(&LOCK_thread_count);
2062   sys_var_end();
2063   delete_global_thread_list();
2064 
2065   my_free(const_cast<char*>(log_bin_basename));
2066   my_free(const_cast<char*>(log_bin_index));
2067 #ifndef EMBEDDED_LIBRARY
2068   my_free(const_cast<char*>(relay_log_basename));
2069   my_free(const_cast<char*>(relay_log_index));
2070 #endif
2071   free_list(opt_plugin_load_list_ptr);
2072 
2073   if (THR_THD)
2074     (void) pthread_key_delete(THR_THD);
2075 
2076   if (THR_MALLOC)
2077     (void) pthread_key_delete(THR_MALLOC);
2078 
2079   /*
2080     The following lines may never be executed as the main thread may have
2081     killed us
2082   */
2083   DBUG_PRINT("quit", ("done with cleanup"));
2084 } /* clean_up */
2085 
2086 
2087 #ifndef EMBEDDED_LIBRARY
2088 
2089 /**
2090   This is mainly needed when running with purify, but it's still nice to
2091   know that all child threads have died when mysqld exits.
2092 */
wait_for_signal_thread_to_end()2093 static void wait_for_signal_thread_to_end()
2094 {
2095   uint i;
2096   /*
2097     Wait up to 10 seconds for signal thread to die. We use this mainly to
2098     avoid getting warnings that my_thread_end has not been called
2099   */
2100   for (i= 0 ; i < 100 && signal_thread_in_use; i++)
2101   {
2102     if (pthread_kill(signal_thread, MYSQL_KILL_SIGNAL) != ESRCH)
2103       break;
2104     my_sleep(100);        // Give it time to die
2105   }
2106 }
2107 
2108 
clean_up_mutexes()2109 static void clean_up_mutexes()
2110 {
2111   mysql_rwlock_destroy(&LOCK_grant);
2112   mysql_mutex_destroy(&LOCK_thread_created);
2113   mysql_mutex_destroy(&LOCK_thread_count);
2114   mysql_mutex_destroy(&LOCK_log_throttle_qni);
2115   mysql_mutex_destroy(&LOCK_status);
2116   mysql_mutex_destroy(&LOCK_delayed_insert);
2117   mysql_mutex_destroy(&LOCK_delayed_status);
2118   mysql_mutex_destroy(&LOCK_delayed_create);
2119   mysql_mutex_destroy(&LOCK_manager);
2120   mysql_mutex_destroy(&LOCK_crypt);
2121   mysql_mutex_destroy(&LOCK_user_conn);
2122   mysql_mutex_destroy(&LOCK_connection_count);
2123 #ifdef HAVE_OPENSSL
2124   mysql_mutex_destroy(&LOCK_des_key_file);
2125 #if OPENSSL_VERSION_NUMBER < 0x10100000L
2126   for (int i= 0; i < CRYPTO_num_locks(); ++i)
2127     mysql_rwlock_destroy(&openssl_stdlocks[i].lock);
2128   OPENSSL_free(openssl_stdlocks);
2129 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
2130 #endif
2131   mysql_mutex_destroy(&LOCK_active_mi);
2132   mysql_rwlock_destroy(&LOCK_sys_init_connect);
2133   mysql_rwlock_destroy(&LOCK_sys_init_slave);
2134   mysql_mutex_destroy(&LOCK_global_system_variables);
2135   mysql_rwlock_destroy(&LOCK_system_variables_hash);
2136   mysql_mutex_destroy(&LOCK_uuid_generator);
2137   mysql_mutex_destroy(&LOCK_sql_rand);
2138   mysql_mutex_destroy(&LOCK_prepared_stmt_count);
2139   mysql_mutex_destroy(&LOCK_sql_slave_skip_counter);
2140   mysql_mutex_destroy(&LOCK_slave_net_timeout);
2141   mysql_mutex_destroy(&LOCK_error_messages);
2142   mysql_cond_destroy(&COND_thread_count);
2143   mysql_mutex_destroy(&LOCK_thd_remove);
2144   mysql_cond_destroy(&COND_thread_cache);
2145   mysql_cond_destroy(&COND_flush_thread_cache);
2146   mysql_cond_destroy(&COND_manager);
2147 #ifdef WITH_WSREP
2148   (void) mysql_mutex_destroy(&LOCK_wsrep_ready);
2149   (void) mysql_cond_destroy(&COND_wsrep_ready);
2150   (void) mysql_mutex_destroy(&LOCK_wsrep_sst);
2151   (void) mysql_cond_destroy(&COND_wsrep_sst);
2152   (void) mysql_mutex_destroy(&LOCK_wsrep_sst_init);
2153   (void) mysql_cond_destroy(&COND_wsrep_sst_init);
2154   (void) mysql_mutex_destroy(&LOCK_wsrep_rollback);
2155   (void) mysql_cond_destroy(&COND_wsrep_rollback);
2156   (void) mysql_mutex_destroy(&LOCK_wsrep_replaying);
2157   (void) mysql_cond_destroy(&COND_wsrep_replaying);
2158   (void) mysql_mutex_destroy(&LOCK_wsrep_slave_threads);
2159   (void) mysql_mutex_destroy(&LOCK_wsrep_desync);
2160 #endif
2161   mysql_cond_destroy(&COND_connection_count);
2162 #ifdef _WIN32
2163   mysql_rwlock_destroy(&LOCK_named_pipe_full_access_group);
2164 #endif
2165 }
2166 #endif /*EMBEDDED_LIBRARY*/
2167 
2168 
2169 /****************************************************************************
2170 ** Init IP and UNIX socket
2171 ****************************************************************************/
2172 
2173 
2174 /**
2175   MY_BIND_ALL_ADDRESSES defines a special value for the bind-address option,
2176   which means that the server should listen to all available network addresses,
2177   both IPv6 (if available) and IPv4.
2178 
2179   Basically, this value instructs the server to make an attempt to bind the
2180   server socket to '::' address, and rollback to '0.0.0.0' if the attempt fails.
2181 */
2182 const char *MY_BIND_ALL_ADDRESSES= "*";
2183 
2184 
2185 #ifndef EMBEDDED_LIBRARY
set_ports()2186 static void set_ports()
2187 {
2188   char  *env;
2189   if (!mysqld_port && !opt_disable_networking)
2190   {         // Get port if not from commandline
2191     mysqld_port= MYSQL_PORT;
2192 
2193     /*
2194       if builder specifically requested a default port, use that
2195       (even if it coincides with our factory default).
2196       only if they didn't do we check /etc/services (and, failing
2197       on that, fall back to the factory default of 3306).
2198       either default can be overridden by the environment variable
2199       MYSQL_TCP_PORT, which in turn can be overridden with command
2200       line options.
2201     */
2202 
2203 #if MYSQL_PORT_DEFAULT == 0
2204     struct  servent *serv_ptr;
2205     if ((serv_ptr= getservbyname("mysql", "tcp")))
2206       mysqld_port= ntohs((u_short) serv_ptr->s_port); /* purecov: inspected */
2207 #endif
2208     if ((env = getenv("MYSQL_TCP_PORT")))
2209       mysqld_port= (uint) atoi(env);    /* purecov: inspected */
2210   }
2211   if (!mysqld_unix_port)
2212   {
2213 #ifdef __WIN__
2214     mysqld_unix_port= (char*) MYSQL_NAMEDPIPE;
2215 #else
2216     mysqld_unix_port= (char*) MYSQL_UNIX_ADDR;
2217 #endif
2218     if ((env = getenv("MYSQL_UNIX_PORT")))
2219       mysqld_unix_port= env;      /* purecov: inspected */
2220   }
2221 }
2222 
2223 /* Change to run as another user if started with --user */
2224 
check_user(const char * user)2225 static struct passwd *check_user(const char *user)
2226 {
2227 #if !defined(__WIN__)
2228   struct passwd *tmp_user_info;
2229   uid_t user_id= geteuid();
2230 
2231   // Don't bother if we aren't superuser
2232   if (user_id)
2233   {
2234     if (user)
2235     {
2236       /* Don't give a warning, if real user is same as given with --user */
2237       /* purecov: begin tested */
2238       tmp_user_info= getpwnam(user);
2239       if ((!tmp_user_info || user_id != tmp_user_info->pw_uid) &&
2240     log_warnings)
2241         sql_print_warning(
2242                     "One can only use the --user switch if running as root\n");
2243       /* purecov: end */
2244     }
2245     return NULL;
2246   }
2247   if (!user)
2248   {
2249     if (!opt_bootstrap && !opt_help)
2250     {
2251       sql_print_error("Fatal error: Please read \"Security\" section of the manual to find out how to run mysqld as root!\n");
2252       unireg_abort(1);
2253     }
2254     return NULL;
2255   }
2256   /* purecov: begin tested */
2257   if (!strcmp(user,"root"))
2258     return NULL;                        // Avoid problem with dynamic libraries
2259 
2260   if (!(tmp_user_info= getpwnam(user)))
2261   {
2262     // Allow a numeric uid to be used
2263     const char *pos;
2264     for (pos= user; my_isdigit(mysqld_charset,*pos); pos++) ;
2265     if (*pos)                                   // Not numeric id
2266       goto err;
2267     if (!(tmp_user_info= getpwuid(atoi(user))))
2268       goto err;
2269   }
2270   return tmp_user_info;
2271   /* purecov: end */
2272 
2273 err:
2274   sql_print_error("Fatal error: Can't change to run as user '%s' ;  Please check that the user exists!\n",user);
2275   unireg_abort(1);
2276 
2277 #ifdef PR_SET_DUMPABLE
2278   if (test_flags & TEST_CORE_ON_SIGNAL)
2279   {
2280     /* inform kernel that process is dumpable */
2281     (void) prctl(PR_SET_DUMPABLE, 1);
2282   }
2283 #endif
2284 
2285 #endif
2286   return NULL;
2287 }
2288 
set_user(const char * user,struct passwd * user_info_arg)2289 static void set_user(const char *user, struct passwd *user_info_arg)
2290 {
2291   /* purecov: begin tested */
2292 #if !defined(__WIN__)
2293   DBUG_ASSERT(user_info_arg != 0);
2294 #ifdef HAVE_INITGROUPS
2295   /*
2296     We can get a SIGSEGV when calling initgroups() on some systems when NSS
2297     is configured to use LDAP and the server is statically linked.  We set
2298     calling_initgroups as a flag to the SIGSEGV handler that is then used to
2299     output a specific message to help the user resolve this problem.
2300   */
2301   calling_initgroups= 1;
2302   initgroups((char*) user, user_info_arg->pw_gid);
2303   calling_initgroups= 0;
2304 #endif
2305   if (setgid(user_info_arg->pw_gid) == -1)
2306   {
2307     sql_perror("setgid");
2308     unireg_abort(1);
2309   }
2310   if (setuid(user_info_arg->pw_uid) == -1)
2311   {
2312     sql_perror("setuid");
2313     unireg_abort(1);
2314   }
2315 #endif
2316   /* purecov: end */
2317 }
2318 
2319 
set_effective_user(struct passwd * user_info_arg)2320 static void set_effective_user(struct passwd *user_info_arg)
2321 {
2322 #if !defined(__WIN__)
2323   DBUG_ASSERT(user_info_arg != 0);
2324   if (setregid((gid_t)-1, user_info_arg->pw_gid) == -1)
2325   {
2326     sql_perror("setregid");
2327     unireg_abort(1);
2328   }
2329   if (setreuid((uid_t)-1, user_info_arg->pw_uid) == -1)
2330   {
2331     sql_perror("setreuid");
2332     unireg_abort(1);
2333   }
2334 #endif
2335 }
2336 
2337 
2338 /** Change root user if started with @c --chroot . */
set_root(const char * path)2339 static void set_root(const char *path)
2340 {
2341 #if !defined(__WIN__)
2342   if (chroot(path) == -1)
2343   {
2344     sql_perror("chroot");
2345     unireg_abort(1);
2346   }
2347   my_setwd("/", MYF(0));
2348 #endif
2349 }
2350 
2351 
create_socket(const struct addrinfo * addrinfo_list,int addr_family,struct addrinfo ** use_addrinfo)2352 static MYSQL_SOCKET create_socket(const struct addrinfo *addrinfo_list,
2353                                   int addr_family,
2354                                   struct addrinfo **use_addrinfo)
2355 {
2356   MYSQL_SOCKET sock= MYSQL_INVALID_SOCKET;
2357 
2358   for (const struct addrinfo *cur_ai= addrinfo_list; cur_ai != NULL;
2359        cur_ai= cur_ai->ai_next)
2360   {
2361     if (cur_ai->ai_family != addr_family)
2362       continue;
2363 
2364     sock= mysql_socket_socket(key_socket_tcpip, cur_ai->ai_family,
2365                               cur_ai->ai_socktype, cur_ai->ai_protocol);
2366 
2367     char ip_addr[INET6_ADDRSTRLEN];
2368 
2369     if (vio_getnameinfo(cur_ai->ai_addr, ip_addr, sizeof (ip_addr),
2370                         NULL, 0, NI_NUMERICHOST))
2371     {
2372       ip_addr[0]= 0;
2373     }
2374 
2375     if (mysql_socket_getfd(sock) == INVALID_SOCKET)
2376     {
2377       sql_print_error("Failed to create a socket for %s '%s': errno: %d.",
2378                       (addr_family == AF_INET) ? "IPv4" : "IPv6",
2379                       (const char *) ip_addr,
2380                       (int) socket_errno);
2381 
2382       continue;
2383     }
2384 
2385     sql_print_information("Server socket created on IP: '%s'.",
2386                           (const char *) ip_addr);
2387 
2388     *use_addrinfo= (struct addrinfo *)cur_ai;
2389     return sock;
2390   }
2391 
2392   return MYSQL_INVALID_SOCKET;
2393 }
2394 
2395 
network_init(void)2396 static void network_init(void)
2397 {
2398 #ifdef HAVE_SYS_UN_H
2399   struct sockaddr_un  UNIXaddr;
2400 #endif
2401   int arg;
2402   int   ret;
2403   uint  waited;
2404   uint  this_wait;
2405   uint  retry;
2406   char port_buf[NI_MAXSERV];
2407   DBUG_ENTER("network_init");
2408   LINT_INIT(ret);
2409 
2410   if (MYSQL_CALLBACK_ELSE(thread_scheduler, init, (), 0))
2411     unireg_abort(1);      /* purecov: inspected */
2412 
2413   set_ports();
2414 
2415   if (report_port == 0)
2416   {
2417     report_port= mysqld_port;
2418   }
2419 
2420 #ifndef DBUG_OFF
2421   if (!opt_disable_networking)
2422     DBUG_ASSERT(report_port != 0);
2423 #endif
2424 
2425   if (mysqld_port != 0 && !opt_disable_networking && !opt_bootstrap)
2426   {
2427     struct addrinfo *ai;
2428     struct addrinfo hints;
2429 
2430     const char *bind_address_str= NULL;
2431     const char *ipv6_all_addresses= "::";
2432     const char *ipv4_all_addresses= "0.0.0.0";
2433 
2434     sql_print_information("Server hostname (bind-address): '%s'; port: %d",
2435                           my_bind_addr_str, mysqld_port);
2436 
2437     // Get list of IP-addresses associated with the bind-address.
2438 
2439     memset(&hints, 0, sizeof (hints));
2440     hints.ai_flags= AI_PASSIVE;
2441     hints.ai_socktype= SOCK_STREAM;
2442     hints.ai_family= AF_UNSPEC;
2443 
2444     my_snprintf(port_buf, NI_MAXSERV, "%d", mysqld_port);
2445 
2446     if (strcasecmp(my_bind_addr_str, MY_BIND_ALL_ADDRESSES) == 0)
2447     {
2448       /*
2449         That's the case when bind-address is set to a special value ('*'),
2450         meaning "bind to all available IP addresses". If the box supports
2451         the IPv6 stack, that means binding to '::'. If only IPv4 is available,
2452         bind to '0.0.0.0'.
2453       */
2454 
2455       bool ipv6_available= false;
2456 
2457       if (!getaddrinfo(ipv6_all_addresses, port_buf, &hints, &ai))
2458       {
2459         /*
2460           IPv6 might be available (the system might be able to resolve an IPv6
2461           address, but not be able to create an IPv6-socket). Try to create a
2462           dummy IPv6-socket. Do not instrument that socket by P_S.
2463         */
2464 
2465         MYSQL_SOCKET s= mysql_socket_socket(0, AF_INET6, SOCK_STREAM, 0);
2466 
2467         ipv6_available= mysql_socket_getfd(s) != INVALID_SOCKET;
2468 
2469         mysql_socket_close(s);
2470       }
2471 
2472       if (ipv6_available)
2473       {
2474         sql_print_information("IPv6 is available.");
2475 
2476         // Address info (ai) for IPv6 address is already set.
2477 
2478         bind_address_str= ipv6_all_addresses;
2479       }
2480       else
2481       {
2482         sql_print_information("IPv6 is not available.");
2483 
2484         // Retrieve address info (ai) for IPv4 address.
2485 
2486         if (getaddrinfo(ipv4_all_addresses, port_buf, &hints, &ai))
2487         {
2488           sql_perror(ER_DEFAULT(ER_IPSOCK_ERROR));
2489           sql_print_error("Can't start server: cannot resolve hostname!");
2490           unireg_abort(1);
2491         }
2492 
2493         bind_address_str= ipv4_all_addresses;
2494       }
2495     }
2496     else
2497     {
2498       if (getaddrinfo(my_bind_addr_str, port_buf, &hints, &ai))
2499       {
2500         sql_perror(ER_DEFAULT(ER_IPSOCK_ERROR));  /* purecov: tested */
2501         sql_print_error("Can't start server: cannot resolve hostname!");
2502         unireg_abort(1);                          /* purecov: tested */
2503       }
2504 
2505       bind_address_str= my_bind_addr_str;
2506     }
2507 
2508     // Log all the IP-addresses.
2509     for (struct addrinfo *cur_ai= ai; cur_ai != NULL; cur_ai= cur_ai->ai_next)
2510     {
2511       char ip_addr[INET6_ADDRSTRLEN];
2512 
2513       if (vio_getnameinfo(cur_ai->ai_addr, ip_addr, sizeof (ip_addr),
2514                           NULL, 0, NI_NUMERICHOST))
2515       {
2516         sql_print_error("Fails to print out IP-address.");
2517         continue;
2518       }
2519 
2520       sql_print_information("  - '%s' resolves to '%s';",
2521                             bind_address_str, ip_addr);
2522     }
2523 
2524     /*
2525       If the 'bind-address' option specifies the hostname, which resolves to
2526       multiple IP-address, use the following rule:
2527       - if there are IPv4-addresses, use the first IPv4-address
2528       returned by getaddrinfo();
2529       - if there are IPv6-addresses, use the first IPv6-address
2530       returned by getaddrinfo();
2531     */
2532 
2533     struct addrinfo *a = NULL;
2534     ip_sock= create_socket(ai, AF_INET, &a);
2535 
2536     if (mysql_socket_getfd(ip_sock) == INVALID_SOCKET)
2537       ip_sock= create_socket(ai, AF_INET6, &a);
2538 
2539     // Report user-error if we failed to create a socket.
2540     if (mysql_socket_getfd(ip_sock) == INVALID_SOCKET)
2541     {
2542       sql_perror(ER_DEFAULT(ER_IPSOCK_ERROR));  /* purecov: tested */
2543       unireg_abort(1);                          /* purecov: tested */
2544     }
2545 
2546     mysql_socket_set_thread_owner(ip_sock);
2547 
2548 #ifndef __WIN__
2549     /*
2550       We should not use SO_REUSEADDR on windows as this would enable a
2551       user to open two mysqld servers with the same TCP/IP port.
2552     */
2553     arg= 1;
2554     (void) mysql_socket_setsockopt(ip_sock, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,sizeof(arg));
2555 #endif /* __WIN__ */
2556 
2557 #ifdef IPV6_V6ONLY
2558      /*
2559        For interoperability with older clients, IPv6 socket should
2560        listen on both IPv6 and IPv4 wildcard addresses.
2561        Turn off IPV6_V6ONLY option.
2562 
2563        NOTE: this will work starting from Windows Vista only.
2564        On Windows XP dual stack is not available, so it will not
2565        listen on the corresponding IPv4-address.
2566      */
2567     if (a->ai_family == AF_INET6)
2568     {
2569       arg= 0;
2570 
2571       if (mysql_socket_setsockopt(ip_sock, IPPROTO_IPV6, IPV6_V6ONLY,
2572                                   (char *) &arg, sizeof (arg)))
2573       {
2574         sql_print_warning("Failed to reset IPV6_V6ONLY flag (error: %d). "
2575                           "The server will listen to IPv6 addresses only.",
2576                           (int) socket_errno);
2577       }
2578     }
2579 #endif
2580     /*
2581       Sometimes the port is not released fast enough when stopping and
2582       restarting the server. This happens quite often with the test suite
2583       on busy Linux systems. Retry to bind the address at these intervals:
2584       Sleep intervals: 1, 2, 4,  6,  9, 13, 17, 22, ...
2585       Retry at second: 1, 3, 7, 13, 22, 35, 52, 74, ...
2586       Limit the sequence by mysqld_port_timeout (set --port-open-timeout=#).
2587     */
2588     for (waited= 0, retry= 1; ; retry++, waited+= this_wait)
2589     {
2590       if (((ret= mysql_socket_bind(ip_sock, a->ai_addr, a->ai_addrlen)) >= 0 ) ||
2591           (socket_errno != SOCKET_EADDRINUSE) ||
2592           (waited >= mysqld_port_timeout))
2593         break;
2594       sql_print_information("Retrying bind on TCP/IP port %u", mysqld_port);
2595       this_wait= retry * retry / 3 + 1;
2596       sleep(this_wait);
2597     }
2598     freeaddrinfo(ai);
2599     if (ret < 0)
2600     {
2601       DBUG_PRINT("error",("Got error: %d from bind",socket_errno));
2602       sql_perror("Can't start server: Bind on TCP/IP port");
2603       sql_print_error("Do you already have another mysqld server running on port: %d ?",mysqld_port);
2604       unireg_abort(1);
2605     }
2606     if (mysql_socket_listen(ip_sock, (int)back_log) < 0)
2607     {
2608       sql_perror("Can't start server: listen() on TCP/IP port");
2609       sql_print_error("listen() on TCP/IP failed with error %d",
2610           socket_errno);
2611       unireg_abort(1);
2612     }
2613 #if defined(WITH_WSREP) && defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
2614     (void) fcntl(mysql_socket_getfd(ip_sock), F_SETFD, FD_CLOEXEC);
2615 #endif /* WITH_WSREP */
2616   }
2617 
2618 #ifdef _WIN32
2619   /* create named pipe */
2620   if (Service.IsNT() && mysqld_unix_port[0] && !opt_bootstrap &&
2621       opt_enable_named_pipe)
2622   {
2623     hPipe= create_server_named_pipe(&psaPipeSecurity,
2624                 global_system_variables.net_buffer_length,
2625                 mysqld_unix_port,
2626                 pipe_name,
2627                 sizeof(pipe_name)-1,
2628                 named_pipe_full_access_group);
2629     if (hPipe == INVALID_HANDLE_VALUE)
2630     {
2631       sql_print_error("Can't start server: failed to create named pipe");
2632       unireg_abort(1);
2633     }
2634   }
2635 #endif
2636 
2637 #if defined(HAVE_SYS_UN_H)
2638   /*
2639   ** Create the UNIX socket
2640   */
2641   if (mysqld_unix_port[0] && !opt_bootstrap)
2642   {
2643     DBUG_PRINT("general",("UNIX Socket is %s",mysqld_unix_port));
2644 
2645     if (strlen(mysqld_unix_port) > (sizeof(UNIXaddr.sun_path) - 1))
2646     {
2647       sql_print_error("The socket file path is too long (> %u): %s",
2648                       (uint) sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port);
2649       unireg_abort(1);
2650     }
2651 
2652     unix_sock= mysql_socket_socket(key_socket_unix, AF_UNIX, SOCK_STREAM, 0);
2653 
2654     if (mysql_socket_getfd(unix_sock) < 0)
2655     {
2656       sql_perror("Can't start server : UNIX Socket "); /* purecov: inspected */
2657       unireg_abort(1);        /* purecov: inspected */
2658     }
2659 
2660     mysql_socket_set_thread_owner(unix_sock);
2661 
2662     memset(&UNIXaddr, 0, sizeof(UNIXaddr));
2663     UNIXaddr.sun_family = AF_UNIX;
2664     strmov(UNIXaddr.sun_path, mysqld_unix_port);
2665     (void) unlink(mysqld_unix_port);
2666     arg= 1;
2667     (void) mysql_socket_setsockopt(unix_sock, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
2668           sizeof(arg));
2669     umask(0);
2670     if (mysql_socket_bind(unix_sock, reinterpret_cast<struct sockaddr *> (&UNIXaddr),
2671                           sizeof(UNIXaddr)) < 0)
2672     {
2673       sql_perror("Can't start server : Bind on unix socket"); /* purecov: tested */
2674       sql_print_error("Do you already have another mysqld server running on socket: %s ?",mysqld_unix_port);
2675       unireg_abort(1);          /* purecov: tested */
2676     }
2677     umask(((~my_umask) & 0666));
2678 #if defined(S_IFSOCK) && defined(SECURE_SOCKETS)
2679     (void) chmod(mysqld_unix_port,S_IFSOCK);  /* Fix solaris 2.6 bug */
2680 #endif
2681     if (mysql_socket_listen(unix_sock, (int)back_log) < 0)
2682       sql_print_warning("listen() on Unix socket failed with error %d",
2683           socket_errno);
2684 #if defined(WITH_WSREP) && defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
2685     (void) fcntl(mysql_socket_getfd(unix_sock), F_SETFD, FD_CLOEXEC);
2686 #endif /* WITH_WSREP */
2687   }
2688 #endif
2689   DBUG_PRINT("info",("server started"));
2690   DBUG_VOID_RETURN;
2691 }
2692 
2693 #endif /*!EMBEDDED_LIBRARY*/
2694 
2695 
2696 #ifndef EMBEDDED_LIBRARY
2697 /**
2698   Close a connection.
2699 
2700   @param thd        Thread handle.
2701   @param sql_errno  The error code to send before disconnect.
2702 
2703   @note
2704     For the connection that is doing shutdown, this is called twice
2705 */
2706 #ifdef WITH_WSREP
close_connection(THD * thd,uint sql_errno,bool lock)2707 void close_connection(THD *thd, uint sql_errno, bool lock)
2708 #else
2709 void close_connection(THD *thd, uint sql_errno)
2710 #endif
2711 {
2712   DBUG_ENTER("close_connection");
2713 
2714   if (sql_errno)
2715     net_send_error(thd, sql_errno, ER_DEFAULT(sql_errno), NULL);
2716 
2717   thd->disconnect();
2718 
2719   MYSQL_CONNECTION_DONE((int) sql_errno, thd->thread_id);
2720 
2721   if (MYSQL_CONNECTION_DONE_ENABLED())
2722   {
2723     sleep(0); /* Workaround to avoid tailcall optimisation */
2724   }
2725   MYSQL_AUDIT_NOTIFY_CONNECTION_DISCONNECT(thd, sql_errno);
2726   DBUG_VOID_RETURN;
2727 }
2728 #endif /* EMBEDDED_LIBRARY */
2729 
2730 
2731 /** Called when a thread is aborted. */
2732 /* ARGSUSED */
end_thread_signal(int sig MY_ATTRIBUTE ((unused)))2733 extern "C" sig_handler end_thread_signal(int sig MY_ATTRIBUTE((unused)))
2734 {
2735   THD *thd=current_thd;
2736   my_safe_printf_stderr("end_thread_signal %p", thd);
2737   if (thd && ! thd->bootstrap)
2738   {
2739     statistic_increment(killed_threads, &LOCK_status);
2740     MYSQL_CALLBACK(thread_scheduler, end_thread, (thd,0)); /* purecov: inspected */
2741   }
2742 }
2743 
2744 
2745 /*
2746   Rlease resources of the THD, prior to destruction.
2747 
2748   SYNOPSIS
2749     thd_release_resources()
2750     thd    Thread handler
2751 */
2752 
thd_release_resources(THD * thd)2753 void thd_release_resources(THD *thd)
2754 {
2755   thd->release_resources();
2756 }
2757 
2758 /*
2759   Decrease number of connections
2760 
2761   SYNOPSIS
2762     dec_connection_count()
2763 */
2764 
dec_connection_count()2765 void dec_connection_count()
2766 {
2767   mysql_mutex_lock(&LOCK_connection_count);
2768   --connection_count;
2769   if (connection_count == 0)
2770     mysql_cond_signal(&COND_connection_count);
2771   mysql_mutex_unlock(&LOCK_connection_count);
2772 }
2773 
2774 
2775 /**
2776   Delete the THD object.
2777  */
destroy_thd(THD * thd)2778 void destroy_thd(THD *thd)
2779 {
2780   mysql_mutex_assert_not_owner(&LOCK_thread_count);
2781   delete thd;
2782 }
2783 
2784 
2785 /**
2786   Block the current pthread for reuse by new connections.
2787 
2788   @retval false  Pthread was not blocked for reuse.
2789   @retval true   Pthread is to be reused by new connection.
2790                  (ie, caller should return, not abort with pthread_exit())
2791 */
2792 
block_until_new_connection()2793 static bool block_until_new_connection()
2794 {
2795   mysql_mutex_lock(&LOCK_thread_count);
2796   if (blocked_pthread_count < max_blocked_pthreads &&
2797       !abort_loop && !kill_blocked_pthreads_flag)
2798   {
2799     /* Don't kill the pthread, just block it for reuse */
2800     DBUG_PRINT("info", ("Blocking pthread for reuse"));
2801     blocked_pthread_count++;
2802 
2803     DBUG_POP();
2804     /*
2805       mysys_var is bound to the physical thread,
2806       so make sure mysys_var->dbug is reset to a clean state
2807       before picking another session in the thread cache.
2808     */
2809     DBUG_ASSERT( ! _db_is_pushed_());
2810 
2811     // Block pthread
2812     while (!abort_loop && !wake_pthread && !kill_blocked_pthreads_flag)
2813       mysql_cond_wait(&COND_thread_cache, &LOCK_thread_count);
2814 
2815     blocked_pthread_count--;
2816     if (kill_blocked_pthreads_flag)
2817       mysql_cond_signal(&COND_flush_thread_cache);
2818     if (wake_pthread)
2819     {
2820       THD *thd;
2821       wake_pthread--;
2822       DBUG_ASSERT(!waiting_thd_list->empty());
2823       thd= waiting_thd_list->front();
2824       waiting_thd_list->pop_front();
2825       DBUG_PRINT("info", ("waiting_thd_list->pop %p", thd));
2826 
2827       thd->thread_stack= (char*) &thd;          // For store_globals
2828       (void) thd->store_globals();
2829 
2830 #ifdef HAVE_PSI_THREAD_INTERFACE
2831       /*
2832         Create new instrumentation for the new THD job,
2833         and attach it to this running pthread.
2834       */
2835       PSI_thread *psi= PSI_THREAD_CALL(new_thread)
2836         (key_thread_one_connection, thd, thd->thread_id);
2837       PSI_THREAD_CALL(set_thread)(psi);
2838 #endif
2839 
2840       /*
2841         THD::mysys_var::abort is associated with physical thread rather
2842         than with THD object. So we need to reset this flag before using
2843         this thread for handling of new THD object/connection.
2844       */
2845       thd->mysys_var->abort= 0;
2846       thd->thr_create_utime= thd->start_utime= my_micro_time();
2847       add_global_thread(thd);
2848       mysql_mutex_unlock(&LOCK_thread_count);
2849       return true;
2850     }
2851   }
2852   mysql_mutex_unlock(&LOCK_thread_count);
2853   return false;
2854 }
2855 
2856 
2857 /**
2858   End thread for the current connection
2859 
2860   @param thd            Thread handler
2861   @param block_pthread  Block the pthread so it can be reused later.
2862                         Normally this is true in all cases except when we got
2863                         out of resources initializing the current thread
2864 
2865   @retval false  Signal to handle_one_connection to reuse connection
2866 
2867   @note If the pthread is blocked, we will wait until the pthread is
2868         scheduled to be reused and then return.
2869         If the pthread is not to be blocked, it will be ended.
2870 */
2871 
one_thread_per_connection_end(THD * thd,bool block_pthread)2872 bool one_thread_per_connection_end(THD *thd, bool block_pthread)
2873 {
2874   DBUG_ENTER("one_thread_per_connection_end");
2875   DBUG_PRINT("info", ("thd %p block_pthread %d", thd, (int) block_pthread));
2876 
2877   thd->release_resources();
2878   remove_global_thread(thd);
2879   dec_connection_count();
2880   if (kill_blocked_pthreads_flag)
2881   {
2882     // Do not block if we are about to shut down
2883     block_pthread= false;
2884   }
2885 
2886 #ifdef WITH_WSREP
2887   if (WSREP(thd) && thd->wsrep_applier)
2888   {
2889     WSREP_DEBUG("avoiding thread re-use for applier, thd: %lu", thd->thread_id);
2890     block_pthread= false;
2891   }
2892 #endif /* WITH_WSREP */
2893   // Clean up errors now, before possibly waiting for a new connection.
2894 #ifndef EMBEDDED_LIBRARY
2895 #if OPENSSL_VERSION_NUMBER < 0x10100000L
2896   ERR_remove_thread_state(0);
2897 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
2898 #endif
2899 
2900   delete thd;
2901 
2902 #ifdef HAVE_PSI_THREAD_INTERFACE
2903   /*
2904     Delete the instrumentation for the job that just completed.
2905   */
2906   PSI_THREAD_CALL(delete_current_thread)();
2907 #endif
2908 
2909   if (block_pthread)
2910     block_pthread= block_until_new_connection();
2911 
2912   if (block_pthread)
2913     DBUG_RETURN(false);                         // Pthread is reused
2914 
2915   /* It's safe to broadcast outside a lock (COND... is not deleted here) */
2916   DBUG_PRINT("signal", ("Broadcasting COND_thread_count"));
2917   DBUG_LEAVE;                                   // Must match DBUG_ENTER()
2918   my_thread_end();
2919   mysql_cond_broadcast(&COND_thread_count);
2920 
2921   pthread_exit(0);
2922   return false;                                 // Avoid compiler warnings
2923 }
2924 
2925 
kill_blocked_pthreads()2926 void kill_blocked_pthreads()
2927 {
2928   mysql_mutex_lock(&LOCK_thread_count);
2929   kill_blocked_pthreads_flag++;
2930   while (blocked_pthread_count)
2931   {
2932     mysql_cond_broadcast(&COND_thread_cache);
2933     mysql_cond_wait(&COND_flush_thread_cache, &LOCK_thread_count);
2934   }
2935   kill_blocked_pthreads_flag--;
2936   mysql_mutex_unlock(&LOCK_thread_count);
2937 }
2938 
2939 
2940 #ifdef THREAD_SPECIFIC_SIGPIPE
2941 /**
2942   Aborts a thread nicely. Comes here on SIGPIPE.
2943 
2944   @todo
2945     One should have to fix that thr_alarm know about this thread too.
2946 */
abort_thread(int sig MY_ATTRIBUTE ((unused)))2947 extern "C" sig_handler abort_thread(int sig MY_ATTRIBUTE((unused)))
2948 {
2949   THD *thd=current_thd;
2950   DBUG_ENTER("abort_thread");
2951   if (thd)
2952     thd->killed= THD::KILL_CONNECTION;
2953   DBUG_VOID_RETURN;
2954 }
2955 #endif
2956 
2957 
2958 /******************************************************************************
2959   Setup a signal thread with handles all signals.
2960   Because Linux doesn't support schemas use a mutex to check that
2961   the signal thread is ready before continuing
2962 ******************************************************************************/
2963 
2964 #if defined(__WIN__)
2965 
2966 
2967 /*
2968   On Windows, we use native SetConsoleCtrlHandler for handle events like Ctrl-C
2969   with graceful shutdown.
2970   Also, we do not use signal(), but SetUnhandledExceptionFilter instead - as it
2971   provides possibility to pass the exception to just-in-time debugger, collect
2972   dumps and potentially also the exception and thread context used to output
2973   callstack.
2974 */
2975 
console_event_handler(DWORD type)2976 static BOOL WINAPI console_event_handler( DWORD type )
2977 {
2978   DBUG_ENTER("console_event_handler");
2979 #ifndef EMBEDDED_LIBRARY
2980   if(type == CTRL_C_EVENT)
2981   {
2982      /*
2983        Do not shutdown before startup is finished and shutdown
2984        thread is initialized. Otherwise there is a race condition
2985        between main thread doing initialization and CTRL-C thread doing
2986        cleanup, which can result into crash.
2987      */
2988 #ifndef EMBEDDED_LIBRARY
2989      if(hEventShutdown)
2990        kill_mysql();
2991      else
2992 #endif
2993        sql_print_warning("CTRL-C ignored during startup");
2994      DBUG_RETURN(TRUE);
2995   }
2996 #endif
2997   DBUG_RETURN(FALSE);
2998 }
2999 
3000 
3001 
3002 
3003 #ifdef DEBUG_UNHANDLED_EXCEPTION_FILTER
3004 #define DEBUGGER_ATTACH_TIMEOUT 120
3005 /*
3006   Wait for debugger to attach and break into debugger. If debugger is not attached,
3007   resume after timeout.
3008 */
wait_for_debugger(int timeout_sec)3009 static void wait_for_debugger(int timeout_sec)
3010 {
3011    if(!IsDebuggerPresent())
3012    {
3013      int i;
3014      printf("Waiting for debugger to attach, pid=%u\n",GetCurrentProcessId());
3015      fflush(stdout);
3016      for(i= 0; i < timeout_sec; i++)
3017      {
3018        Sleep(1000);
3019        if(IsDebuggerPresent())
3020        {
3021          /* Break into debugger */
3022          __debugbreak();
3023          return;
3024        }
3025      }
3026      printf("pid=%u, debugger not attached after %d seconds, resuming\n",GetCurrentProcessId(),
3027        timeout_sec);
3028      fflush(stdout);
3029    }
3030 }
3031 #endif /* DEBUG_UNHANDLED_EXCEPTION_FILTER */
3032 
my_unhandler_exception_filter(EXCEPTION_POINTERS * ex_pointers)3033 LONG WINAPI my_unhandler_exception_filter(EXCEPTION_POINTERS *ex_pointers)
3034 {
3035    static BOOL first_time= TRUE;
3036    if(!first_time)
3037    {
3038      /*
3039        This routine can be called twice, typically
3040        when detaching in JIT debugger.
3041        Return EXCEPTION_EXECUTE_HANDLER to terminate process.
3042      */
3043      return EXCEPTION_EXECUTE_HANDLER;
3044    }
3045    first_time= FALSE;
3046 #ifdef DEBUG_UNHANDLED_EXCEPTION_FILTER
3047    /*
3048     Unfortunately there is no clean way to debug unhandled exception filters,
3049     as debugger does not stop there(also documented in MSDN)
3050     To overcome, one could put a MessageBox, but this will not work in service.
3051     Better solution is to print error message and sleep some minutes
3052     until debugger is attached
3053   */
3054   wait_for_debugger(DEBUGGER_ATTACH_TIMEOUT);
3055 #endif /* DEBUG_UNHANDLED_EXCEPTION_FILTER */
3056   __try
3057   {
3058     my_set_exception_pointers(ex_pointers);
3059     handle_fatal_signal(ex_pointers->ExceptionRecord->ExceptionCode);
3060   }
3061   __except(EXCEPTION_EXECUTE_HANDLER)
3062   {
3063     DWORD written;
3064     const char msg[] = "Got exception in exception handler!\n";
3065     WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),msg, sizeof(msg)-1,
3066       &written,NULL);
3067   }
3068   /*
3069     Return EXCEPTION_CONTINUE_SEARCH to give JIT debugger
3070     (drwtsn32 or vsjitdebugger) possibility to attach,
3071     if JIT debugger is configured.
3072     Windows Error reporting might generate a dump here.
3073   */
3074   return EXCEPTION_CONTINUE_SEARCH;
3075 }
3076 
3077 
my_init_signals(void)3078 void my_init_signals(void)
3079 {
3080   if(opt_console)
3081     SetConsoleCtrlHandler(console_event_handler,TRUE);
3082 
3083     /* Avoid MessageBox()es*/
3084   _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
3085   _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
3086   _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
3087   _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
3088   _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
3089   _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
3090 
3091    /*
3092      Do not use SEM_NOGPFAULTERRORBOX in the following SetErrorMode (),
3093      because it would prevent JIT debugger and Windows error reporting
3094      from working. We need WER or JIT-debugging, since our own unhandled
3095      exception filter is not guaranteed to work in all situation
3096      (like heap corruption or stack overflow)
3097    */
3098   SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS
3099                                | SEM_NOOPENFILEERRORBOX);
3100   SetUnhandledExceptionFilter(my_unhandler_exception_filter);
3101 }
3102 
3103 
start_signal_handler(void)3104 static void start_signal_handler(void)
3105 {
3106 #ifndef EMBEDDED_LIBRARY
3107   // Save vm id of this process
3108   if (!opt_bootstrap)
3109     create_pid_file();
3110 #endif /* EMBEDDED_LIBRARY */
3111 }
3112 
3113 
check_data_home(const char * path)3114 static void check_data_home(const char *path)
3115 {}
3116 
3117 #endif /* __WIN__ */
3118 
3119 
3120 #if BACKTRACE_DEMANGLE
3121 #include <cxxabi.h>
my_demangle(const char * mangled_name,int * status)3122 extern "C" char *my_demangle(const char *mangled_name, int *status)
3123 {
3124   return abi::__cxa_demangle(mangled_name, NULL, NULL, status);
3125 }
3126 #endif
3127 
3128 
3129 #if !defined(__WIN__)
3130 #ifndef SA_RESETHAND
3131 #define SA_RESETHAND 0
3132 #endif
3133 #ifndef SA_NODEFER
3134 #define SA_NODEFER 0
3135 #endif
3136 
3137 #ifndef EMBEDDED_LIBRARY
3138 
my_init_signals(void)3139 void my_init_signals(void)
3140 {
3141   sigset_t set;
3142   struct sigaction sa;
3143   DBUG_ENTER("my_init_signals");
3144 
3145   my_sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called!
3146 
3147   if (!(test_flags & TEST_NO_STACKTRACE) || (test_flags & TEST_CORE_ON_SIGNAL))
3148   {
3149     sa.sa_flags = SA_RESETHAND | SA_NODEFER;
3150     sigemptyset(&sa.sa_mask);
3151     sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
3152 
3153 #ifdef HAVE_STACKTRACE
3154     my_init_stacktrace();
3155 #endif
3156 #if defined(__amiga__)
3157     sa.sa_handler=(void(*)())handle_fatal_signal;
3158 #else
3159     sa.sa_handler=handle_fatal_signal;
3160 #endif
3161     sigaction(SIGSEGV, &sa, NULL);
3162     sigaction(SIGABRT, &sa, NULL);
3163 #ifdef SIGBUS
3164     sigaction(SIGBUS, &sa, NULL);
3165 #endif
3166     sigaction(SIGILL, &sa, NULL);
3167     sigaction(SIGFPE, &sa, NULL);
3168   }
3169 
3170 #ifdef HAVE_GETRLIMIT
3171   if (test_flags & TEST_CORE_ON_SIGNAL)
3172   {
3173     /* Change limits so that we will get a core file */
3174     STRUCT_RLIMIT rl;
3175     rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
3176     if (setrlimit(RLIMIT_CORE, &rl) && log_warnings)
3177       sql_print_warning("setrlimit could not change the size of core files to 'infinity';  We may not be able to generate a core file on signals");
3178   }
3179 #endif
3180   (void) sigemptyset(&set);
3181   my_sigset(SIGPIPE,SIG_IGN);
3182   sigaddset(&set,SIGPIPE);
3183 #ifndef IGNORE_SIGHUP_SIGQUIT
3184   sigaddset(&set,SIGQUIT);
3185   sigaddset(&set,SIGHUP);
3186 #endif
3187   sigaddset(&set,SIGTERM);
3188 
3189   /* Fix signals if blocked by parents (can happen on Mac OS X) */
3190   sigemptyset(&sa.sa_mask);
3191   sa.sa_flags = 0;
3192   sa.sa_handler = print_signal_warning;
3193   sigaction(SIGTERM, &sa, (struct sigaction*) 0);
3194   sa.sa_flags = 0;
3195   sa.sa_handler = print_signal_warning;
3196   sigaction(SIGHUP, &sa, (struct sigaction*) 0);
3197 #ifdef SIGTSTP
3198   sigaddset(&set,SIGTSTP);
3199 #endif
3200   sigaddset(&set,THR_SERVER_ALARM);
3201   if (test_flags & TEST_SIGINT)
3202   {
3203     my_sigset(thr_kill_signal, end_thread_signal);
3204     // May be SIGINT
3205     sigdelset(&set, thr_kill_signal);
3206   }
3207   else
3208     sigaddset(&set,SIGINT);
3209   sigprocmask(SIG_SETMASK,&set,NULL);
3210   pthread_sigmask(SIG_SETMASK,&set,NULL);
3211   DBUG_VOID_RETURN;
3212 }
3213 
3214 
start_signal_handler(void)3215 static void start_signal_handler(void)
3216 {
3217   int error;
3218   pthread_attr_t thr_attr;
3219   DBUG_ENTER("start_signal_handler");
3220 
3221   (void) pthread_attr_init(&thr_attr);
3222 #if !defined(HAVE_DEC_3_2_THREADS)
3223   pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_SYSTEM);
3224   (void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
3225 
3226   size_t guardize= 0;
3227   pthread_attr_getguardsize(&thr_attr, &guardize);
3228 
3229 #if defined(__ia64__) || defined(__ia64)
3230   /*
3231     Peculiar things with ia64 platforms - it seems we only have half the
3232     stack size in reality, so we have to double it here
3233   */
3234   guardize= my_thread_stack_size;
3235 #endif
3236 
3237   pthread_attr_setstacksize(&thr_attr, my_thread_stack_size + guardize);
3238 #endif
3239 
3240   mysql_mutex_lock(&LOCK_thread_count);
3241   if ((error= mysql_thread_create(key_thread_signal_hand,
3242                                   &signal_thread, &thr_attr, signal_hand, 0)))
3243   {
3244     sql_print_error("Can't create interrupt-thread (error %d, errno: %d)",
3245                     error,errno);
3246     exit(1);
3247   }
3248   mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
3249   mysql_mutex_unlock(&LOCK_thread_count);
3250 
3251   (void) pthread_attr_destroy(&thr_attr);
3252   DBUG_VOID_RETURN;
3253 }
3254 
3255 
3256 /** This threads handles all signals and alarms. */
3257 /* ARGSUSED */
signal_hand(void * arg MY_ATTRIBUTE ((unused)))3258 pthread_handler_t signal_hand(void *arg MY_ATTRIBUTE((unused)))
3259 {
3260   sigset_t set;
3261   int sig;
3262   my_thread_init();       // Init new thread
3263   signal_thread_in_use= 1;
3264 
3265   /*
3266     Setup alarm handler
3267     This should actually be '+ max_number_of_slaves' instead of +10,
3268     but the +10 should be quite safe.
3269   */
3270   init_thr_alarm(thread_scheduler->max_threads +
3271      global_system_variables.max_insert_delayed_threads + 10);
3272   if (test_flags & TEST_SIGINT)
3273   {
3274     (void) sigemptyset(&set);     // Setup up SIGINT for debug
3275     (void) sigaddset(&set,SIGINT);    // For debugging
3276     (void) pthread_sigmask(SIG_UNBLOCK,&set,NULL);
3277   }
3278   (void) sigemptyset(&set);     // Setup up SIGINT for debug
3279 #ifdef USE_ONE_SIGNAL_HAND
3280   (void) sigaddset(&set,THR_SERVER_ALARM);  // For alarms
3281 #endif
3282 #ifndef IGNORE_SIGHUP_SIGQUIT
3283   (void) sigaddset(&set,SIGQUIT);
3284   (void) sigaddset(&set,SIGHUP);
3285 #endif
3286   (void) sigaddset(&set,SIGTERM);
3287   (void) sigaddset(&set,SIGTSTP);
3288 
3289   /* Save pid to this process (or thread on Linux) */
3290   if (!opt_bootstrap)
3291     create_pid_file();
3292 
3293   /*
3294     signal to start_signal_handler that we are ready
3295     This works by waiting for start_signal_handler to free mutex,
3296     after which we signal it that we are ready.
3297     At this pointer there is no other threads running, so there
3298     should not be any other mysql_cond_signal() calls.
3299   */
3300   mysql_mutex_lock(&LOCK_thread_count);
3301   mysql_cond_broadcast(&COND_thread_count);
3302   mysql_mutex_unlock(&LOCK_thread_count);
3303 
3304   /*
3305     Waiting for until mysqld_server_started != 0
3306     to ensure that all server components has been successfully
3307     initialized. This step is mandatory since signal processing
3308     could be done safely only when all server components
3309     has been initialized.
3310   */
3311   mysql_mutex_lock(&LOCK_server_started);
3312   while (!mysqld_server_started)
3313     mysql_cond_wait(&COND_server_started, &LOCK_server_started);
3314   mysql_mutex_unlock(&LOCK_server_started);
3315 
3316   for (;;)
3317   {
3318     int error;          // Used when debugging
3319     if (shutdown_in_progress && !abort_loop)
3320     {
3321       sig= SIGTERM;
3322       error=0;
3323     }
3324     else
3325       while ((error=my_sigwait(&set,&sig)) == EINTR) ;
3326     if (cleanup_done)
3327     {
3328       my_thread_end();
3329       signal_thread_in_use= 0;
3330       pthread_exit(0);        // Safety
3331       return 0;                                 // Avoid compiler warnings
3332     }
3333     switch (sig) {
3334     case SIGTERM:
3335     case SIGQUIT:
3336     case SIGKILL:
3337 #ifdef EXTRA_DEBUG
3338       sql_print_information("Got signal %d to shutdown mysqld",sig);
3339 #endif
3340       /* switch to the old log message processing */
3341       logger.set_handlers(LOG_FILE, opt_slow_log ? LOG_FILE:LOG_NONE,
3342                           opt_log ? LOG_FILE:LOG_NONE);
3343       DBUG_PRINT("info",("Got signal: %d  abort_loop: %d",sig,abort_loop));
3344       if (!abort_loop)
3345       {
3346         abort_loop=1;       // mark abort for threads
3347 #ifdef HAVE_PSI_THREAD_INTERFACE
3348         /* Delete the instrumentation for the signal thread */
3349         PSI_THREAD_CALL(delete_current_thread)();
3350 #endif
3351 #ifdef USE_ONE_SIGNAL_HAND
3352         pthread_t tmp;
3353         if ((error= mysql_thread_create(0, /* Not instrumented */
3354                                         &tmp, &connection_attrib,
3355                                         kill_server_thread,
3356                                         (void*) &sig)))
3357           sql_print_error("Can't create thread to kill server (errno= %d)",
3358                           error);
3359 #else
3360         kill_server((void*) sig); // MIT THREAD has a alarm thread
3361 #endif
3362       }
3363       break;
3364     case SIGHUP:
3365       if (!abort_loop)
3366       {
3367         int not_used;
3368   mysql_print_status();   // Print some debug info
3369   reload_acl_and_cache((THD*) 0,
3370            (REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST |
3371             REFRESH_GRANT |
3372             REFRESH_THREADS | REFRESH_HOSTS),
3373            (TABLE_LIST*) 0, &not_used); // Flush logs
3374       }
3375       /* reenable logs after the options were reloaded */
3376       if (log_output_options & LOG_NONE)
3377       {
3378         logger.set_handlers(LOG_FILE,
3379                             opt_slow_log ? LOG_TABLE : LOG_NONE,
3380                             opt_log ? LOG_TABLE : LOG_NONE);
3381       }
3382       else
3383       {
3384         logger.set_handlers(LOG_FILE,
3385                             opt_slow_log ? log_output_options : LOG_NONE,
3386                             opt_log ? log_output_options : LOG_NONE);
3387       }
3388       break;
3389 #ifdef USE_ONE_SIGNAL_HAND
3390     case THR_SERVER_ALARM:
3391       process_alarm(sig);     // Trigger alarms.
3392       break;
3393 #endif
3394     default:
3395 #ifdef EXTRA_DEBUG
3396       sql_print_warning("Got signal: %d  error: %d",sig,error); /* purecov: tested */
3397 #endif
3398       break;          /* purecov: tested */
3399     }
3400   }
3401   return(0);          /* purecov: deadcode */
3402 }
3403 
check_data_home(const char * path)3404 static void check_data_home(const char *path)
3405 {}
3406 
3407 #endif /*!EMBEDDED_LIBRARY*/
3408 #endif  /* __WIN__*/
3409 
3410 
3411 /**
3412   All global error messages are sent here where the first one is stored
3413   for the client.
3414 */
3415 /* ARGSUSED */
3416 extern "C" void my_message_sql(uint error, const char *str, myf MyFlags);
3417 
my_message_sql(uint error,const char * str,myf MyFlags)3418 void my_message_sql(uint error, const char *str, myf MyFlags)
3419 {
3420   THD *thd= current_thd;
3421   DBUG_ENTER("my_message_sql");
3422   DBUG_PRINT("error", ("error: %u  message: '%s'", error, str));
3423 
3424   DBUG_ASSERT(str != NULL);
3425   /*
3426     An error should have a valid error number (!= 0), so it can be caught
3427     in stored procedures by SQL exception handlers.
3428     Calling my_error() with error == 0 is a bug.
3429     Remaining known places to fix:
3430     - storage/myisam/mi_create.c, my_printf_error()
3431     TODO:
3432     DBUG_ASSERT(error != 0);
3433   */
3434 
3435   if (error == 0)
3436   {
3437     /* At least, prevent new abuse ... */
3438     DBUG_ASSERT(strncmp(str, "MyISAM table", 12) == 0);
3439     error= ER_UNKNOWN_ERROR;
3440   }
3441 
3442   mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_ERROR, error, str);
3443 
3444   if (thd)
3445   {
3446     if (MyFlags & ME_FATALERROR)
3447       thd->is_fatal_error= 1;
3448     (void) thd->raise_condition(error,
3449                                 NULL,
3450                                 Sql_condition::WARN_LEVEL_ERROR,
3451                                 str);
3452   }
3453 
3454   /* When simulating OOM, skip writing to error log to avoid mtr errors */
3455   DBUG_EXECUTE_IF("simulate_out_of_memory", DBUG_VOID_RETURN;);
3456 
3457   if (!thd || MyFlags & ME_NOREFRESH)
3458     sql_print_error("%s: %s",my_progname,str); /* purecov: inspected */
3459   DBUG_VOID_RETURN;
3460 }
3461 
3462 
3463 #ifndef EMBEDDED_LIBRARY
3464 extern "C" void *my_str_malloc_mysqld(size_t size);
3465 extern "C" void my_str_free_mysqld(void *ptr);
3466 extern "C" void *my_str_realloc_mysqld(void *ptr, size_t size);
3467 
my_str_malloc_mysqld(size_t size)3468 void *my_str_malloc_mysqld(size_t size)
3469 {
3470   return my_malloc(size, MYF(MY_FAE));
3471 }
3472 
3473 
my_str_free_mysqld(void * ptr)3474 void my_str_free_mysqld(void *ptr)
3475 {
3476   my_free(ptr);
3477 }
3478 
my_str_realloc_mysqld(void * ptr,size_t size)3479 void *my_str_realloc_mysqld(void *ptr, size_t size)
3480 {
3481   return my_realloc(ptr, size, MYF(MY_FAE));
3482 }
3483 #endif /* EMBEDDED_LIBRARY */
3484 
3485 
3486 #ifdef __WIN__
3487 
handle_shutdown(void * arg)3488 pthread_handler_t handle_shutdown(void *arg)
3489 {
3490   MSG msg;
3491   my_thread_init();
3492 
3493   /* this call should create the message queue for this thread */
3494   PeekMessage(&msg, NULL, 1, 65534,PM_NOREMOVE);
3495 #if !defined(EMBEDDED_LIBRARY)
3496   if (WaitForSingleObject(hEventShutdown,INFINITE)==WAIT_OBJECT_0)
3497 #endif /* EMBEDDED_LIBRARY */
3498      kill_server(MYSQL_KILL_SIGNAL);
3499   return 0;
3500 }
3501 #endif
3502 
3503 const char *load_default_groups[]= {
3504 #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
3505 "mysql_cluster",
3506 #endif
3507 "mysqld","server", MYSQL_BASE_VERSION, 0, 0};
3508 
3509 #if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
3510 static const int load_default_groups_sz=
3511 sizeof(load_default_groups)/sizeof(load_default_groups[0]);
3512 #endif
3513 
3514 #ifndef EMBEDDED_LIBRARY
3515 /**
3516   This function is used to check for stack overrun for pathological
3517   cases of regular expressions and 'like' expressions.
3518   The call to current_thd is quite expensive, so we try to avoid it
3519   for the normal cases.
3520   The size of each stack frame for the wildcmp() routines is ~128 bytes,
3521   so checking *every* recursive call is not necessary.
3522  */
3523 extern "C" int
check_enough_stack_size(int recurse_level)3524 check_enough_stack_size(int recurse_level)
3525 {
3526   uchar stack_top;
3527   if (recurse_level % 16 != 0)
3528     return 0;
3529 
3530   THD *my_thd= current_thd;
3531   if (my_thd != NULL)
3532     return check_stack_overrun(my_thd, STACK_MIN_SIZE * 2, &stack_top);
3533   return 0;
3534 }
3535 #endif
3536 
3537 
3538 /**
3539   Initialize one of the global date/time format variables.
3540 
3541   @param format_type    What kind of format should be supported
3542   @param var_ptr    Pointer to variable that should be updated
3543 
3544   @retval
3545     0 ok
3546   @retval
3547     1 error
3548 */
3549 
init_global_datetime_format(timestamp_type format_type,DATE_TIME_FORMAT * format)3550 static bool init_global_datetime_format(timestamp_type format_type,
3551                                         DATE_TIME_FORMAT *format)
3552 {
3553   /*
3554     Get command line option
3555     format->format.str is already set by my_getopt
3556   */
3557   format->format.length= strlen(format->format.str);
3558 
3559   if (parse_date_time_format(format_type, format))
3560   {
3561     fprintf(stderr, "Wrong date/time format specifier: %s\n",
3562             format->format.str);
3563     return true;
3564   }
3565   return false;
3566 }
3567 
3568 SHOW_VAR com_status_vars[]= {
3569   {"admin_commands",       (char*) offsetof(STATUS_VAR, com_other), SHOW_LONG_STATUS},
3570   {"assign_to_keycache",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ASSIGN_TO_KEYCACHE]), SHOW_LONG_STATUS},
3571   {"alter_db",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_DB]), SHOW_LONG_STATUS},
3572   {"alter_db_upgrade",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_DB_UPGRADE]), SHOW_LONG_STATUS},
3573   {"alter_event",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_EVENT]), SHOW_LONG_STATUS},
3574   {"alter_function",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_FUNCTION]), SHOW_LONG_STATUS},
3575   {"alter_procedure",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_PROCEDURE]), SHOW_LONG_STATUS},
3576   {"alter_server",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_SERVER]), SHOW_LONG_STATUS},
3577   {"alter_table",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_TABLE]), SHOW_LONG_STATUS},
3578   {"alter_tablespace",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_TABLESPACE]), SHOW_LONG_STATUS},
3579   {"alter_user",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_USER]), SHOW_LONG_STATUS},
3580   {"analyze",              (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ANALYZE]), SHOW_LONG_STATUS},
3581   {"begin",                (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_BEGIN]), SHOW_LONG_STATUS},
3582   {"binlog",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_BINLOG_BASE64_EVENT]), SHOW_LONG_STATUS},
3583   {"call_procedure",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CALL]), SHOW_LONG_STATUS},
3584   {"change_db",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHANGE_DB]), SHOW_LONG_STATUS},
3585   {"change_master",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHANGE_MASTER]), SHOW_LONG_STATUS},
3586   {"check",                (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHECK]), SHOW_LONG_STATUS},
3587   {"checksum",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHECKSUM]), SHOW_LONG_STATUS},
3588   {"commit",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_COMMIT]), SHOW_LONG_STATUS},
3589   {"create_db",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_DB]), SHOW_LONG_STATUS},
3590   {"create_event",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_EVENT]), SHOW_LONG_STATUS},
3591   {"create_function",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_SPFUNCTION]), SHOW_LONG_STATUS},
3592   {"create_index",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_INDEX]), SHOW_LONG_STATUS},
3593   {"create_procedure",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_PROCEDURE]), SHOW_LONG_STATUS},
3594   {"create_server",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_SERVER]), SHOW_LONG_STATUS},
3595   {"create_table",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_TABLE]), SHOW_LONG_STATUS},
3596   {"create_trigger",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_TRIGGER]), SHOW_LONG_STATUS},
3597   {"create_udf",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_FUNCTION]), SHOW_LONG_STATUS},
3598   {"create_user",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_USER]), SHOW_LONG_STATUS},
3599   {"create_view",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_VIEW]), SHOW_LONG_STATUS},
3600   {"dealloc_sql",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DEALLOCATE_PREPARE]), SHOW_LONG_STATUS},
3601   {"delete",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DELETE]), SHOW_LONG_STATUS},
3602   {"delete_multi",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DELETE_MULTI]), SHOW_LONG_STATUS},
3603   {"do",                   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DO]), SHOW_LONG_STATUS},
3604   {"drop_db",              (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_DB]), SHOW_LONG_STATUS},
3605   {"drop_event",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_EVENT]), SHOW_LONG_STATUS},
3606   {"drop_function",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_FUNCTION]), SHOW_LONG_STATUS},
3607   {"drop_index",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_INDEX]), SHOW_LONG_STATUS},
3608   {"drop_procedure",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_PROCEDURE]), SHOW_LONG_STATUS},
3609   {"drop_server",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_SERVER]), SHOW_LONG_STATUS},
3610   {"drop_table",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_TABLE]), SHOW_LONG_STATUS},
3611   {"drop_trigger",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_TRIGGER]), SHOW_LONG_STATUS},
3612   {"drop_user",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_USER]), SHOW_LONG_STATUS},
3613   {"drop_view",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_VIEW]), SHOW_LONG_STATUS},
3614   {"empty_query",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EMPTY_QUERY]), SHOW_LONG_STATUS},
3615   {"execute_sql",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EXECUTE]), SHOW_LONG_STATUS},
3616   {"flush",                (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_FLUSH]), SHOW_LONG_STATUS},
3617   {"get_diagnostics",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GET_DIAGNOSTICS]), SHOW_LONG_STATUS},
3618   {"grant",                (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GRANT]), SHOW_LONG_STATUS},
3619   {"ha_close",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_CLOSE]), SHOW_LONG_STATUS},
3620   {"ha_open",              (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_OPEN]), SHOW_LONG_STATUS},
3621   {"ha_read",              (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_READ]), SHOW_LONG_STATUS},
3622   {"help",                 (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HELP]), SHOW_LONG_STATUS},
3623   {"insert",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSERT]), SHOW_LONG_STATUS},
3624   {"insert_select",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSERT_SELECT]), SHOW_LONG_STATUS},
3625   {"install_plugin",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSTALL_PLUGIN]), SHOW_LONG_STATUS},
3626   {"kill",                 (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_KILL]), SHOW_LONG_STATUS},
3627   {"load",                 (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOAD]), SHOW_LONG_STATUS},
3628   {"lock_tables",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOCK_TABLES]), SHOW_LONG_STATUS},
3629   {"optimize",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_OPTIMIZE]), SHOW_LONG_STATUS},
3630   {"preload_keys",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PRELOAD_KEYS]), SHOW_LONG_STATUS},
3631   {"prepare_sql",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PREPARE]), SHOW_LONG_STATUS},
3632   {"purge",                (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PURGE]), SHOW_LONG_STATUS},
3633   {"purge_before_date",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PURGE_BEFORE]), SHOW_LONG_STATUS},
3634   {"release_savepoint",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RELEASE_SAVEPOINT]), SHOW_LONG_STATUS},
3635   {"rename_table",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RENAME_TABLE]), SHOW_LONG_STATUS},
3636   {"rename_user",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RENAME_USER]), SHOW_LONG_STATUS},
3637   {"repair",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPAIR]), SHOW_LONG_STATUS},
3638   {"replace",              (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPLACE]), SHOW_LONG_STATUS},
3639   {"replace_select",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPLACE_SELECT]), SHOW_LONG_STATUS},
3640   {"reset",                (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESET]), SHOW_LONG_STATUS},
3641   {"resignal",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESIGNAL]), SHOW_LONG_STATUS},
3642   {"revoke",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE]), SHOW_LONG_STATUS},
3643   {"revoke_all",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE_ALL]), SHOW_LONG_STATUS},
3644   {"rollback",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ROLLBACK]), SHOW_LONG_STATUS},
3645   {"rollback_to_savepoint",(char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ROLLBACK_TO_SAVEPOINT]), SHOW_LONG_STATUS},
3646   {"savepoint",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SAVEPOINT]), SHOW_LONG_STATUS},
3647   {"select",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SELECT]), SHOW_LONG_STATUS},
3648   {"set_option",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SET_OPTION]), SHOW_LONG_STATUS},
3649   {"signal",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SIGNAL]), SHOW_LONG_STATUS},
3650   {"show_binlog_events",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOG_EVENTS]), SHOW_LONG_STATUS},
3651   {"show_binlogs",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOGS]), SHOW_LONG_STATUS},
3652   {"show_charsets",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CHARSETS]), SHOW_LONG_STATUS},
3653   {"show_collations",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_COLLATIONS]), SHOW_LONG_STATUS},
3654   {"show_create_db",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_DB]), SHOW_LONG_STATUS},
3655   {"show_create_event",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_EVENT]), SHOW_LONG_STATUS},
3656   {"show_create_func",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_FUNC]), SHOW_LONG_STATUS},
3657   {"show_create_proc",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_PROC]), SHOW_LONG_STATUS},
3658   {"show_create_table",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE]), SHOW_LONG_STATUS},
3659   {"show_create_trigger",  (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_TRIGGER]), SHOW_LONG_STATUS},
3660   {"show_databases",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_DATABASES]), SHOW_LONG_STATUS},
3661   {"show_engine_logs",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_LOGS]), SHOW_LONG_STATUS},
3662   {"show_engine_mutex",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_MUTEX]), SHOW_LONG_STATUS},
3663   {"show_engine_status",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_STATUS]), SHOW_LONG_STATUS},
3664   {"show_events",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_EVENTS]), SHOW_LONG_STATUS},
3665   {"show_errors",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ERRORS]), SHOW_LONG_STATUS},
3666   {"show_fields",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_FIELDS]), SHOW_LONG_STATUS},
3667   {"show_function_code",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_FUNC_CODE]), SHOW_LONG_STATUS},
3668   {"show_function_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS_FUNC]), SHOW_LONG_STATUS},
3669   {"show_grants",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_GRANTS]), SHOW_LONG_STATUS},
3670   {"show_keys",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_KEYS]), SHOW_LONG_STATUS},
3671   {"show_master_status",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_MASTER_STAT]), SHOW_LONG_STATUS},
3672   {"show_open_tables",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_OPEN_TABLES]), SHOW_LONG_STATUS},
3673   {"show_plugins",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PLUGINS]), SHOW_LONG_STATUS},
3674   {"show_privileges",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PRIVILEGES]), SHOW_LONG_STATUS},
3675   {"show_procedure_code",  (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROC_CODE]), SHOW_LONG_STATUS},
3676   {"show_procedure_status",(char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS_PROC]), SHOW_LONG_STATUS},
3677   {"show_processlist",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROCESSLIST]), SHOW_LONG_STATUS},
3678   {"show_profile",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROFILE]), SHOW_LONG_STATUS},
3679   {"show_profiles",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROFILES]), SHOW_LONG_STATUS},
3680   {"show_relaylog_events", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_RELAYLOG_EVENTS]), SHOW_LONG_STATUS},
3681   {"show_slave_hosts",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_HOSTS]), SHOW_LONG_STATUS},
3682   {"show_slave_status",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_STAT]), SHOW_LONG_STATUS},
3683   {"show_status",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS]), SHOW_LONG_STATUS},
3684   {"show_storage_engines", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STORAGE_ENGINES]), SHOW_LONG_STATUS},
3685   {"show_table_status",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLE_STATUS]), SHOW_LONG_STATUS},
3686   {"show_tables",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLES]), SHOW_LONG_STATUS},
3687   {"show_triggers",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TRIGGERS]), SHOW_LONG_STATUS},
3688   {"show_variables",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_VARIABLES]), SHOW_LONG_STATUS},
3689   {"show_warnings",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_WARNS]), SHOW_LONG_STATUS},
3690   {"slave_start",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_START]), SHOW_LONG_STATUS},
3691   {"slave_stop",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_STOP]), SHOW_LONG_STATUS},
3692   {"stmt_close",           (char*) offsetof(STATUS_VAR, com_stmt_close), SHOW_LONG_STATUS},
3693   {"stmt_execute",         (char*) offsetof(STATUS_VAR, com_stmt_execute), SHOW_LONG_STATUS},
3694   {"stmt_fetch",           (char*) offsetof(STATUS_VAR, com_stmt_fetch), SHOW_LONG_STATUS},
3695   {"stmt_prepare",         (char*) offsetof(STATUS_VAR, com_stmt_prepare), SHOW_LONG_STATUS},
3696   {"stmt_reprepare",       (char*) offsetof(STATUS_VAR, com_stmt_reprepare), SHOW_LONG_STATUS},
3697   {"stmt_reset",           (char*) offsetof(STATUS_VAR, com_stmt_reset), SHOW_LONG_STATUS},
3698   {"stmt_send_long_data",  (char*) offsetof(STATUS_VAR, com_stmt_send_long_data), SHOW_LONG_STATUS},
3699   {"truncate",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_TRUNCATE]), SHOW_LONG_STATUS},
3700   {"uninstall_plugin",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UNINSTALL_PLUGIN]), SHOW_LONG_STATUS},
3701   {"unlock_tables",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UNLOCK_TABLES]), SHOW_LONG_STATUS},
3702   {"update",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UPDATE]), SHOW_LONG_STATUS},
3703   {"update_multi",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UPDATE_MULTI]), SHOW_LONG_STATUS},
3704   {"xa_commit",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_COMMIT]),SHOW_LONG_STATUS},
3705   {"xa_end",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_END]),SHOW_LONG_STATUS},
3706   {"xa_prepare",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_PREPARE]),SHOW_LONG_STATUS},
3707   {"xa_recover",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_RECOVER]),SHOW_LONG_STATUS},
3708   {"xa_rollback",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_ROLLBACK]),SHOW_LONG_STATUS},
3709   {"xa_start",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_START]),SHOW_LONG_STATUS},
3710   {NullS, NullS, SHOW_LONG}
3711 };
3712 
3713 LEX_CSTRING sql_statement_names[(uint) SQLCOM_END + 1];
3714 
init_sql_statement_names()3715 void init_sql_statement_names()
3716 {
3717   static LEX_CSTRING empty= { C_STRING_WITH_LEN("") };
3718 
3719   char *first_com= (char*) offsetof(STATUS_VAR, com_stat[0]);
3720   char *last_com= (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_END]);
3721   int record_size= (char*) offsetof(STATUS_VAR, com_stat[1])
3722                    - (char*) offsetof(STATUS_VAR, com_stat[0]);
3723   char *ptr;
3724   uint i;
3725   uint com_index;
3726 
3727   for (i= 0; i < ((uint) SQLCOM_END + 1); i++)
3728     sql_statement_names[i]= empty;
3729 
3730   SHOW_VAR *var= &com_status_vars[0];
3731   while (var->name != NULL)
3732   {
3733     ptr= var->value;
3734     if ((first_com <= ptr) && (ptr <= last_com))
3735     {
3736       com_index= ((int)(ptr - first_com))/record_size;
3737       DBUG_ASSERT(com_index < (uint) SQLCOM_END);
3738       sql_statement_names[com_index].str= var->name;
3739       /* TODO: Change SHOW_VAR::name to a LEX_STRING, to avoid strlen() */
3740       sql_statement_names[com_index].length= strlen(var->name);
3741     }
3742     var++;
3743   }
3744 
3745   DBUG_ASSERT(strcmp(sql_statement_names[(uint) SQLCOM_SELECT].str, "select") == 0);
3746   DBUG_ASSERT(strcmp(sql_statement_names[(uint) SQLCOM_SIGNAL].str, "signal") == 0);
3747 
3748   sql_statement_names[(uint) SQLCOM_END].str= "error";
3749 }
3750 
3751 #ifdef HAVE_PSI_STATEMENT_INTERFACE
3752 PSI_statement_info sql_statement_info[(uint) SQLCOM_END + 1];
3753 PSI_statement_info com_statement_info[(uint) COM_END + 1];
3754 
3755 /**
3756   Initialize the command names array.
3757   Since we do not want to maintain a separate array,
3758   this is populated from data mined in com_status_vars,
3759   which already has one name for each command.
3760 */
init_sql_statement_info()3761 void init_sql_statement_info()
3762 {
3763   uint i;
3764 
3765   for (i= 0; i < ((uint) SQLCOM_END + 1); i++)
3766   {
3767     sql_statement_info[i].m_name= sql_statement_names[i].str;
3768     sql_statement_info[i].m_flags= 0;
3769   }
3770 
3771   /* "statement/sql/error" represents broken queries (syntax error). */
3772   sql_statement_info[(uint) SQLCOM_END].m_name= "error";
3773   sql_statement_info[(uint) SQLCOM_END].m_flags= 0;
3774 }
3775 
init_com_statement_info()3776 void init_com_statement_info()
3777 {
3778   uint index;
3779 
3780   for (index= 0; index < (uint) COM_END + 1; index++)
3781   {
3782     com_statement_info[index].m_name= command_name[index].str;
3783     com_statement_info[index].m_flags= 0;
3784   }
3785 
3786   /* "statement/abstract/query" can mutate into "statement/sql/..." */
3787   com_statement_info[(uint) COM_QUERY].m_flags= PSI_FLAG_MUTABLE;
3788 }
3789 #endif
3790 
3791 /**
3792   Create the name of the default general log file
3793 
3794   @param[IN] buff    Location for building new string.
3795   @param[IN] log_ext The extension for the file (e.g .log)
3796   @returns Pointer to a new string containing the name
3797 */
make_default_log_name(char * buff,const char * log_ext)3798 static inline char *make_default_log_name(char *buff,const char* log_ext)
3799 {
3800   return make_log_name(buff, default_logfile_name, log_ext);
3801 }
3802 
3803 /**
3804   Create a replication file name or base for file names.
3805 
3806   @param[in] opt Value of option, or NULL
3807   @param[in] def Default value if option value is not set.
3808   @param[in] ext Extension to use for the path
3809 
3810   @returns Pointer to string containing the full file path, or NULL if
3811   it was not possible to create the path.
3812  */
3813 static inline const char *
rpl_make_log_name(const char * opt,const char * def,const char * ext)3814 rpl_make_log_name(const char *opt,
3815                   const char *def,
3816                   const char *ext)
3817 {
3818   DBUG_ENTER("rpl_make_log_name");
3819   DBUG_PRINT("enter", ("opt: %s, def: %s, ext: %s", opt, def, ext));
3820   char buff[FN_REFLEN];
3821   const char *base= opt ? opt : def;
3822   unsigned int options=
3823     MY_REPLACE_EXT | MY_UNPACK_FILENAME | MY_SAFE_PATH;
3824 
3825   /* mysql_real_data_home_ptr  may be null if no value of datadir has been
3826      specified through command-line or througha cnf file. If that is the
3827      case we make mysql_real_data_home_ptr point to mysql_real_data_home
3828      which, in that case holds the default path for data-dir.
3829   */
3830   if(mysql_real_data_home_ptr == NULL)
3831     mysql_real_data_home_ptr= mysql_real_data_home;
3832 
3833   if (fn_format(buff, base, mysql_real_data_home_ptr, ext, options))
3834     DBUG_RETURN(strdup(buff));
3835   else
3836     DBUG_RETURN(NULL);
3837 }
3838 
3839 
init_common_variables()3840 int init_common_variables()
3841 {
3842   umask(((~my_umask) & 0666));
3843   connection_errors_select= 0;
3844   connection_errors_accept= 0;
3845   connection_errors_tcpwrap= 0;
3846   connection_errors_internal= 0;
3847   connection_errors_max_connection= 0;
3848   connection_errors_peer_addr= 0;
3849   my_decimal_set_zero(&decimal_zero); // set decimal_zero constant;
3850   tzset();      // Set tzname
3851 
3852   max_system_variables.pseudo_thread_id= (ulong)~0;
3853   server_start_time= flush_status_time= my_time(0);
3854 
3855   rpl_filter= new Rpl_filter;
3856   binlog_filter= new Rpl_filter;
3857   if (!rpl_filter || !binlog_filter)
3858   {
3859     sql_perror("Could not allocate replication and binlog filters");
3860     return 1;
3861   }
3862 
3863   if (init_thread_environment() ||
3864       mysql_init_variables())
3865     return 1;
3866 
3867   if (ignore_db_dirs_init())
3868     return 1;
3869 
3870 #ifdef HAVE_TZNAME
3871   {
3872     struct tm tm_tmp;
3873     localtime_r(&server_start_time,&tm_tmp);
3874     strmake(system_time_zone, tzname[tm_tmp.tm_isdst != 0 ? 1 : 0],
3875             sizeof(system_time_zone)-1);
3876 
3877  }
3878 #endif
3879   /*
3880     We set SYSTEM time zone as reasonable default and
3881     also for failure of my_tz_init() and bootstrap mode.
3882     If user explicitly set time zone with --default-time-zone
3883     option we will change this value in my_tz_init().
3884   */
3885   global_system_variables.time_zone= my_tz_SYSTEM;
3886 
3887 #ifdef HAVE_PSI_INTERFACE
3888   /*
3889     Complete the mysql_bin_log initialization.
3890     Instrumentation keys are known only after the performance schema initialization,
3891     and can not be set in the MYSQL_BIN_LOG constructor (called before main()).
3892   */
3893   mysql_bin_log.set_psi_keys(key_BINLOG_LOCK_index,
3894                              key_BINLOG_LOCK_commit,
3895                              key_BINLOG_LOCK_commit_queue,
3896                              key_BINLOG_LOCK_done,
3897                              key_BINLOG_LOCK_flush_queue,
3898                              key_BINLOG_LOCK_log,
3899                              key_BINLOG_LOCK_sync,
3900                              key_BINLOG_LOCK_sync_queue,
3901                              key_BINLOG_LOCK_xids,
3902                              key_BINLOG_COND_done,
3903                              key_BINLOG_update_cond,
3904                              key_BINLOG_prep_xids_cond,
3905                              key_file_binlog,
3906                              key_file_binlog_index);
3907 #endif
3908 
3909   /*
3910     Init mutexes for the global MYSQL_BIN_LOG objects.
3911     As safe_mutex depends on what MY_INIT() does, we can't init the mutexes of
3912     global MYSQL_BIN_LOGs in their constructors, because then they would be
3913     inited before MY_INIT(). So we do it here.
3914   */
3915   mysql_bin_log.init_pthread_objects();
3916 
3917   /* TODO: remove this when my_time_t is 64 bit compatible */
3918   if (!IS_TIME_T_VALID_FOR_TIMESTAMP(server_start_time))
3919   {
3920     sql_print_error("This MySQL server doesn't support dates later then 2038");
3921     return 1;
3922   }
3923 
3924   if (gethostname(glob_hostname,sizeof(glob_hostname)) < 0)
3925   {
3926     strmake(glob_hostname, STRING_WITH_LEN("localhost"));
3927     sql_print_warning("gethostname failed, using '%s' as hostname",
3928                       glob_hostname);
3929     strmake(default_logfile_name, STRING_WITH_LEN("mysql"));
3930   }
3931   else
3932     strmake(default_logfile_name, glob_hostname,
3933       sizeof(default_logfile_name)-5);
3934 
3935 #ifdef WITH_WSREP
3936   if (0 == wsrep_node_name || 0 == wsrep_node_name[0])
3937   {
3938     my_free((void *)wsrep_node_name);
3939     wsrep_node_name= my_strdup(glob_hostname, MYF(MY_WME));
3940   }
3941 #endif /* WITH_WSREP */
3942   strmake(pidfile_name, default_logfile_name, sizeof(pidfile_name)-5);
3943   strmov(fn_ext(pidfile_name),".pid");    // Add proper extension
3944 
3945 
3946   /*
3947     The default-storage-engine entry in my_long_options should have a
3948     non-null default value. It was earlier intialized as
3949     (longlong)"MyISAM" in my_long_options but this triggered a
3950     compiler error in the Sun Studio 12 compiler. As a work-around we
3951     set the def_value member to 0 in my_long_options and initialize it
3952     to the correct value here.
3953 
3954     From MySQL 5.5 onwards, the default storage engine is InnoDB
3955     (except in the embedded server, where the default continues to
3956     be MyISAM)
3957   */
3958 #ifdef EMBEDDED_LIBRARY
3959   default_storage_engine= const_cast<char *>("MyISAM");
3960 #else
3961   default_storage_engine= const_cast<char *>("InnoDB");
3962 #endif
3963   default_tmp_storage_engine= default_storage_engine;
3964 
3965   init_default_auth_plugin();
3966 
3967   /*
3968     Add server status variables to the dynamic list of
3969     status variables that is shown by SHOW STATUS.
3970     Later, in plugin_init, and mysql_install_plugin
3971     new entries could be added to that list.
3972   */
3973   if (add_status_vars(status_vars))
3974     return 1; // an error was already reported
3975 
3976 #ifndef DBUG_OFF
3977   /*
3978     We have few debug-only commands in com_status_vars, only visible in debug
3979     builds. for simplicity we enable the assert only in debug builds
3980 
3981     There are 8 Com_ variables which don't have corresponding SQLCOM_ values:
3982     (TODO strictly speaking they shouldn't be here, should not have Com_ prefix
3983     that is. Perhaps Stmt_ ? Comstmt_ ? Prepstmt_ ?)
3984 
3985       Com_admin_commands       => com_other
3986       Com_stmt_close           => com_stmt_close
3987       Com_stmt_execute         => com_stmt_execute
3988       Com_stmt_fetch           => com_stmt_fetch
3989       Com_stmt_prepare         => com_stmt_prepare
3990       Com_stmt_reprepare       => com_stmt_reprepare
3991       Com_stmt_reset           => com_stmt_reset
3992       Com_stmt_send_long_data  => com_stmt_send_long_data
3993 
3994     With this correction the number of Com_ variables (number of elements in
3995     the array, excluding the last element - terminator) must match the number
3996     of SQLCOM_ constants.
3997   */
3998   compile_time_assert(sizeof(com_status_vars)/sizeof(com_status_vars[0]) - 1 ==
3999                      SQLCOM_END + 8);
4000 #endif
4001 #ifdef WITH_WSREP
4002   /* This is a protection against mutually incompatible option values. */
4003   if (WSREP_ON && wsrep_check_opts (remaining_argc, remaining_argv))
4004     return 1;
4005 #endif /* WITH_WSREP */
4006   if (get_options(&remaining_argc, &remaining_argv))
4007     return 1;
4008   set_server_version();
4009 
4010   sql_print_information("%s (mysqld %s) starting as process %lu ...",
4011                         my_progname, server_version, (ulong) getpid());
4012 
4013 #ifndef EMBEDDED_LIBRARY
4014   if (opt_help && !opt_verbose)
4015     unireg_abort(0);
4016 #endif /*!EMBEDDED_LIBRARY*/
4017 
4018   DBUG_PRINT("info",("%s  Ver %s for %s on %s\n",my_progname,
4019          server_version, SYSTEM_TYPE,MACHINE_TYPE));
4020 
4021 #ifdef HAVE_LARGE_PAGES
4022   /* Initialize large page size */
4023   if (opt_large_pages && (opt_large_page_size= my_get_large_page_size()))
4024   {
4025       DBUG_PRINT("info", ("Large page set, large_page_size = %d",
4026                  opt_large_page_size));
4027       my_use_large_pages= 1;
4028       my_large_page_size= opt_large_page_size;
4029   }
4030   else
4031   {
4032     opt_large_pages= 0;
4033     /*
4034        Either not configured to use large pages or Linux haven't
4035        been compiled with large page support
4036     */
4037   }
4038 #endif /* HAVE_LARGE_PAGES */
4039 #ifdef HAVE_SOLARIS_LARGE_PAGES
4040 #define LARGE_PAGESIZE (4*1024*1024)  /* 4MB */
4041 #define SUPER_LARGE_PAGESIZE (256*1024*1024)  /* 256MB */
4042   if (opt_large_pages)
4043   {
4044   /*
4045     tell the kernel that we want to use 4/256MB page for heap storage
4046     and also for the stack. We use 4 MByte as default and if the
4047     super-large-page is set we increase it to 256 MByte. 256 MByte
4048     is for server installations with GBytes of RAM memory where
4049     the MySQL Server will have page caches and other memory regions
4050     measured in a number of GBytes.
4051     We use as big pages as possible which isn't bigger than the above
4052     desired page sizes.
4053   */
4054    int nelem;
4055    size_t max_desired_page_size;
4056    if (opt_super_large_pages)
4057      max_desired_page_size= SUPER_LARGE_PAGESIZE;
4058    else
4059      max_desired_page_size= LARGE_PAGESIZE;
4060    nelem = getpagesizes(NULL, 0);
4061    if (nelem > 0)
4062    {
4063      size_t *pagesize = (size_t *) malloc(sizeof(size_t) * nelem);
4064      if (pagesize != NULL && getpagesizes(pagesize, nelem) > 0)
4065      {
4066        size_t max_page_size= 0;
4067        for (int i= 0; i < nelem; i++)
4068        {
4069          if (pagesize[i] > max_page_size &&
4070              pagesize[i] <= max_desired_page_size)
4071             max_page_size= pagesize[i];
4072        }
4073        free(pagesize);
4074        if (max_page_size > 0)
4075        {
4076          struct memcntl_mha mpss;
4077 
4078          mpss.mha_cmd= MHA_MAPSIZE_BSSBRK;
4079          mpss.mha_pagesize= max_page_size;
4080          mpss.mha_flags= 0;
4081          memcntl(NULL, 0, MC_HAT_ADVISE, (caddr_t)&mpss, 0, 0);
4082          mpss.mha_cmd= MHA_MAPSIZE_STACK;
4083          memcntl(NULL, 0, MC_HAT_ADVISE, (caddr_t)&mpss, 0, 0);
4084        }
4085      }
4086    }
4087   }
4088 #endif /* HAVE_SOLARIS_LARGE_PAGES */
4089 
4090   longlong default_value;
4091   sys_var *var;
4092   /* Calculate and update default value for thread_cache_size. */
4093   if ((default_value= 8 + max_connections / 100) > 100)
4094     default_value= 100;
4095   var= intern_find_sys_var(STRING_WITH_LEN("thread_cache_size"));
4096   var->update_default(default_value);
4097 
4098   /* Calculate and update default value for host_cache_size. */
4099   if ((default_value= 128 + max_connections) > 628 &&
4100       (default_value= 628 + ((max_connections - 500) / 20)) > 2000)
4101     default_value= 2000;
4102   var= intern_find_sys_var(STRING_WITH_LEN("host_cache_size"));
4103   var->update_default(default_value);
4104 
4105   /* Fix thread_cache_size. */
4106   if (!thread_cache_size_specified &&
4107       (max_blocked_pthreads= 8 + max_connections / 100) > 100)
4108     max_blocked_pthreads= 100;
4109 
4110   /* Fix host_cache_size. */
4111   if (!host_cache_size_specified &&
4112       (host_cache_size= 128 + max_connections) > 628 &&
4113       (host_cache_size= 628 + ((max_connections - 500) / 20)) > 2000)
4114     host_cache_size= 2000;
4115 
4116   /* Fix back_log */
4117   if (back_log == 0 && (back_log= 50 + max_connections / 5) > 900)
4118     back_log= 900;
4119 
4120   unireg_init(opt_specialflag); /* Set up extern variabels */
4121   if (!(my_default_lc_messages=
4122         my_locale_by_name(lc_messages)))
4123   {
4124     sql_print_error("Unknown locale: '%s'", lc_messages);
4125     return 1;
4126   }
4127   global_system_variables.lc_messages= my_default_lc_messages;
4128   if (init_errmessage())  /* Read error messages from file */
4129     return 1;
4130   init_client_errs();
4131   mysql_client_plugin_init();
4132   lex_init();
4133   if (item_create_init())
4134     return 1;
4135   item_init();
4136 #ifndef EMBEDDED_LIBRARY
4137   my_regex_init(&my_charset_latin1, check_enough_stack_size);
4138   my_string_stack_guard= check_enough_stack_size;
4139 #else
4140   my_regex_init(&my_charset_latin1, NULL);
4141 #endif
4142   /*
4143     Process a comma-separated character set list and choose
4144     the first available character set. This is mostly for
4145     test purposes, to be able to start "mysqld" even if
4146     the requested character set is not available (see bug#18743).
4147   */
4148   for (;;)
4149   {
4150     char *next_character_set_name= strchr(default_character_set_name, ',');
4151     if (next_character_set_name)
4152       *next_character_set_name++= '\0';
4153     if (!(default_charset_info=
4154           get_charset_by_csname(default_character_set_name,
4155                                 MY_CS_PRIMARY, MYF(MY_WME))))
4156     {
4157       if (next_character_set_name)
4158       {
4159         default_character_set_name= next_character_set_name;
4160         default_collation_name= 0;          // Ignore collation
4161       }
4162       else
4163         return 1;                           // Eof of the list
4164     }
4165     else
4166       break;
4167   }
4168 
4169   if (default_collation_name)
4170   {
4171     CHARSET_INFO *default_collation;
4172     default_collation= get_charset_by_name(default_collation_name, MYF(0));
4173     if (!default_collation)
4174     {
4175 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
4176       buffered_logs.print();
4177       buffered_logs.cleanup();
4178 #endif
4179       sql_print_error(ER_DEFAULT(ER_UNKNOWN_COLLATION), default_collation_name);
4180       return 1;
4181     }
4182     if (!my_charset_same(default_charset_info, default_collation))
4183     {
4184       sql_print_error(ER_DEFAULT(ER_COLLATION_CHARSET_MISMATCH),
4185           default_collation_name,
4186           default_charset_info->csname);
4187       return 1;
4188     }
4189     default_charset_info= default_collation;
4190   }
4191   /* Set collactions that depends on the default collation */
4192   global_system_variables.collation_server=  default_charset_info;
4193   global_system_variables.collation_database=  default_charset_info;
4194 
4195   if (is_supported_parser_charset(default_charset_info))
4196   {
4197     global_system_variables.collation_connection= default_charset_info;
4198     global_system_variables.character_set_results= default_charset_info;
4199     global_system_variables.character_set_client= default_charset_info;
4200   }
4201   else
4202   {
4203     sql_print_information("'%s' can not be used as client character set. "
4204                           "'%s' will be used as default client character set.",
4205                           default_charset_info->csname,
4206                           my_charset_latin1.csname);
4207     global_system_variables.collation_connection= &my_charset_latin1;
4208     global_system_variables.character_set_results= &my_charset_latin1;
4209     global_system_variables.character_set_client= &my_charset_latin1;
4210   }
4211 
4212   if (!(character_set_filesystem=
4213         get_charset_by_csname(character_set_filesystem_name,
4214                               MY_CS_PRIMARY, MYF(MY_WME))))
4215     return 1;
4216   global_system_variables.character_set_filesystem= character_set_filesystem;
4217 
4218   if (!(my_default_lc_time_names=
4219         my_locale_by_name(lc_time_names_name)))
4220   {
4221     sql_print_error("Unknown locale: '%s'", lc_time_names_name);
4222     return 1;
4223   }
4224   global_system_variables.lc_time_names= my_default_lc_time_names;
4225 
4226   /* check log options and issue warnings if needed */
4227   if (opt_log && opt_logname && !(log_output_options & LOG_FILE) &&
4228       !(log_output_options & LOG_NONE))
4229     sql_print_warning("Although a path was specified for the "
4230                       "--general-log-file option, log tables are used. "
4231                       "To enable logging to files use the --log-output=file option.");
4232 
4233   if (opt_slow_log && opt_slow_logname && !(log_output_options & LOG_FILE)
4234       && !(log_output_options & LOG_NONE))
4235     sql_print_warning("Although a path was specified for the "
4236                       "--slow-query-log-file option, log tables are used. "
4237                       "To enable logging to files use the --log-output=file option.");
4238 
4239   if (!opt_logname || !*opt_logname)
4240     opt_logname= make_default_log_name(logname_path, ".log");
4241 
4242   if (!opt_slow_logname || !*opt_slow_logname)
4243     opt_slow_logname= make_default_log_name(slow_logname_path, "-slow.log");
4244 
4245   if (opt_logname &&
4246       !is_valid_log_name(opt_logname, strlen(opt_logname)))
4247   {
4248     sql_print_error("Invalid value for --general_log_file: %s",
4249                     opt_logname);
4250     return 1;
4251   }
4252 
4253   if (opt_slow_logname &&
4254       !is_valid_log_name(opt_slow_logname, strlen(opt_slow_logname)))
4255   {
4256     sql_print_error("Invalid value for --slow_query_log_file: %s",
4257                     opt_slow_logname);
4258     return 1;
4259   }
4260 
4261 #if defined(ENABLED_DEBUG_SYNC)
4262   /* Initialize the debug sync facility. See debug_sync.cc. */
4263   if (debug_sync_init())
4264     return 1; /* purecov: tested */
4265 #endif /* defined(ENABLED_DEBUG_SYNC) */
4266 
4267 #if (ENABLE_TEMP_POOL)
4268   if (use_temp_pool && bitmap_init(&temp_pool,0,1024,1))
4269     return 1;
4270 #else
4271   use_temp_pool= 0;
4272 #endif
4273 
4274   if (my_dboptions_cache_init())
4275     return 1;
4276 
4277   /*
4278     Ensure that lower_case_table_names is set on system where we have case
4279     insensitive names.  If this is not done the users MyISAM tables will
4280     get corrupted if accesses with names of different case.
4281   */
4282   DBUG_PRINT("info", ("lower_case_table_names: %d", lower_case_table_names));
4283   lower_case_file_system= test_if_case_insensitive(mysql_real_data_home);
4284   if (!lower_case_table_names && lower_case_file_system == 1)
4285   {
4286     if (lower_case_table_names_used)
4287     {
4288       sql_print_error("The server option 'lower_case_table_names' is "
4289                       "configured to use case sensitive table names but the "
4290                       "data directory is on a case-insensitive file system "
4291                       "which is an unsupported combination. Please consider "
4292                       "either using a case sensitive file system for your data "
4293                       "directory or switching to a case-insensitive table name "
4294                       "mode.");
4295       return 1;
4296     }
4297     else
4298     {
4299       if (log_warnings)
4300   sql_print_warning("Setting lower_case_table_names=2 because file system for %s is case insensitive", mysql_real_data_home);
4301       lower_case_table_names= 2;
4302     }
4303   }
4304   else if (lower_case_table_names == 2 &&
4305            !(lower_case_file_system=
4306              (test_if_case_insensitive(mysql_real_data_home) == 1)))
4307   {
4308     if (log_warnings)
4309       sql_print_warning("lower_case_table_names was set to 2, even though your "
4310                         "the file system '%s' is case sensitive.  Now setting "
4311                         "lower_case_table_names to 0 to avoid future problems.",
4312       mysql_real_data_home);
4313     lower_case_table_names= 0;
4314   }
4315   else
4316   {
4317     lower_case_file_system=
4318       (test_if_case_insensitive(mysql_real_data_home) == 1);
4319   }
4320 
4321   /* Reset table_alias_charset, now that lower_case_table_names is set. */
4322   table_alias_charset= (lower_case_table_names ?
4323       &my_charset_utf8_tolower_ci :
4324       &my_charset_bin);
4325 
4326   /*
4327     Build do_table and ignore_table rules to hush
4328     after the resetting of table_alias_charset
4329   */
4330   if (rpl_filter->build_do_table_hash() ||
4331       rpl_filter->build_ignore_table_hash())
4332   {
4333     sql_print_error("An error occurred while building do_table"
4334                     "and ignore_table rules to hush.");
4335     return 1;
4336   }
4337 
4338   if (ignore_db_dirs_process_additions())
4339   {
4340     sql_print_error("An error occurred while storing ignore_db_dirs to a hash.");
4341     return 1;
4342   }
4343 
4344   return 0;
4345 }
4346 
4347 
init_thread_environment()4348 static int init_thread_environment()
4349 {
4350   mysql_mutex_init(key_LOCK_thread_created,
4351                    &LOCK_thread_created, MY_MUTEX_INIT_FAST);
4352   mysql_mutex_init(key_LOCK_thread_count, &LOCK_thread_count, MY_MUTEX_INIT_FAST);
4353   mysql_mutex_init(key_LOCK_status, &LOCK_status, MY_MUTEX_INIT_FAST);
4354   mysql_mutex_init(key_LOCK_thd_remove,
4355                    &LOCK_thd_remove, MY_MUTEX_INIT_FAST);
4356   mysql_mutex_init(key_LOCK_delayed_insert,
4357                    &LOCK_delayed_insert, MY_MUTEX_INIT_FAST);
4358   mysql_mutex_init(key_LOCK_delayed_status,
4359                    &LOCK_delayed_status, MY_MUTEX_INIT_FAST);
4360   mysql_mutex_init(key_LOCK_delayed_create,
4361                    &LOCK_delayed_create, MY_MUTEX_INIT_SLOW);
4362   mysql_mutex_init(key_LOCK_manager,
4363                    &LOCK_manager, MY_MUTEX_INIT_FAST);
4364   mysql_mutex_init(key_LOCK_crypt, &LOCK_crypt, MY_MUTEX_INIT_FAST);
4365   mysql_mutex_init(key_LOCK_user_conn, &LOCK_user_conn, MY_MUTEX_INIT_FAST);
4366   mysql_mutex_init(key_LOCK_active_mi, &LOCK_active_mi, MY_MUTEX_INIT_FAST);
4367   mysql_mutex_init(key_LOCK_global_system_variables,
4368                    &LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
4369   mysql_rwlock_init(key_rwlock_LOCK_system_variables_hash,
4370                     &LOCK_system_variables_hash);
4371   mysql_mutex_init(key_LOCK_prepared_stmt_count,
4372                    &LOCK_prepared_stmt_count, MY_MUTEX_INIT_FAST);
4373   mysql_mutex_init(key_LOCK_sql_slave_skip_counter,
4374                    &LOCK_sql_slave_skip_counter, MY_MUTEX_INIT_FAST);
4375   mysql_mutex_init(key_LOCK_slave_net_timeout,
4376                    &LOCK_slave_net_timeout, MY_MUTEX_INIT_FAST);
4377   mysql_mutex_init(key_LOCK_error_messages,
4378                    &LOCK_error_messages, MY_MUTEX_INIT_FAST);
4379   mysql_mutex_init(key_LOCK_uuid_generator,
4380                    &LOCK_uuid_generator, MY_MUTEX_INIT_FAST);
4381   mysql_mutex_init(key_LOCK_sql_rand,
4382                    &LOCK_sql_rand, MY_MUTEX_INIT_FAST);
4383   mysql_mutex_init(key_LOCK_connection_count,
4384                    &LOCK_connection_count, MY_MUTEX_INIT_FAST);
4385   mysql_mutex_init(key_LOCK_log_throttle_qni,
4386                    &LOCK_log_throttle_qni, MY_MUTEX_INIT_FAST);
4387 #ifdef HAVE_OPENSSL
4388   mysql_mutex_init(key_LOCK_des_key_file,
4389                    &LOCK_des_key_file, MY_MUTEX_INIT_FAST);
4390 #if OPENSSL_VERSION_NUMBER < 0x10100000L
4391   openssl_stdlocks= (openssl_lock_t*) OPENSSL_malloc(CRYPTO_num_locks() *
4392                                                      sizeof(openssl_lock_t));
4393   for (int i= 0; i < CRYPTO_num_locks(); ++i)
4394     mysql_rwlock_init(key_rwlock_openssl, &openssl_stdlocks[i].lock);
4395   CRYPTO_set_dynlock_create_callback(openssl_dynlock_create);
4396   CRYPTO_set_dynlock_destroy_callback(openssl_dynlock_destroy);
4397   CRYPTO_set_dynlock_lock_callback(openssl_lock);
4398   CRYPTO_set_locking_callback(openssl_lock_function);
4399   CRYPTO_set_id_callback(openssl_id_function);
4400 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
4401 #endif
4402   mysql_rwlock_init(key_rwlock_LOCK_sys_init_connect, &LOCK_sys_init_connect);
4403   mysql_rwlock_init(key_rwlock_LOCK_sys_init_slave, &LOCK_sys_init_slave);
4404   mysql_rwlock_init(key_rwlock_LOCK_grant, &LOCK_grant);
4405   mysql_cond_init(key_COND_thread_count, &COND_thread_count, NULL);
4406   mysql_cond_init(key_COND_connection_count, &COND_connection_count, NULL);
4407   mysql_cond_init(key_COND_thread_cache, &COND_thread_cache, NULL);
4408   mysql_cond_init(key_COND_flush_thread_cache, &COND_flush_thread_cache, NULL);
4409   mysql_cond_init(key_COND_manager, &COND_manager, NULL);
4410   mysql_mutex_init(key_LOCK_server_started,
4411                    &LOCK_server_started, MY_MUTEX_INIT_FAST);
4412   mysql_cond_init(key_COND_server_started, &COND_server_started, NULL);
4413   sp_cache_init();
4414 #ifdef HAVE_EVENT_SCHEDULER
4415   Events::init_mutexes();
4416 #endif
4417   /* Parameter for threads created for connections */
4418   (void) pthread_attr_init(&connection_attrib);
4419   (void) pthread_attr_setdetachstate(&connection_attrib,
4420              PTHREAD_CREATE_DETACHED);
4421   pthread_attr_setscope(&connection_attrib, PTHREAD_SCOPE_SYSTEM);
4422 
4423   if (pthread_key_create(&THR_THD,NULL) ||
4424       pthread_key_create(&THR_MALLOC,NULL))
4425   {
4426     sql_print_error("Can't create thread-keys");
4427     return 1;
4428   }
4429 #ifdef WITH_WSREP
4430   mysql_mutex_init(key_LOCK_wsrep_ready,
4431                    &LOCK_wsrep_ready, MY_MUTEX_INIT_FAST);
4432   mysql_cond_init(key_COND_wsrep_ready, &COND_wsrep_ready, NULL);
4433   mysql_mutex_init(key_LOCK_wsrep_sst,
4434                    &LOCK_wsrep_sst, MY_MUTEX_INIT_FAST);
4435   mysql_cond_init(key_COND_wsrep_sst, &COND_wsrep_sst, NULL);
4436   mysql_mutex_init(key_LOCK_wsrep_sst_init,
4437                    &LOCK_wsrep_sst_init, MY_MUTEX_INIT_FAST);
4438   mysql_cond_init(key_COND_wsrep_sst_init, &COND_wsrep_sst_init, NULL);
4439   mysql_mutex_init(key_LOCK_wsrep_rollback,
4440                    &LOCK_wsrep_rollback, MY_MUTEX_INIT_FAST);
4441   mysql_cond_init(key_COND_wsrep_rollback, &COND_wsrep_rollback, NULL);
4442   mysql_mutex_init(key_LOCK_wsrep_replaying,
4443                    &LOCK_wsrep_replaying, MY_MUTEX_INIT_FAST);
4444   mysql_cond_init(key_COND_wsrep_replaying, &COND_wsrep_replaying, NULL);
4445   mysql_mutex_init(key_LOCK_wsrep_slave_threads,
4446                    &LOCK_wsrep_slave_threads, MY_MUTEX_INIT_FAST);
4447   mysql_mutex_init(key_LOCK_wsrep_desync,
4448                    &LOCK_wsrep_desync, MY_MUTEX_INIT_FAST);
4449 #endif
4450   return 0;
4451 }
4452 
4453 
4454 #if defined(HAVE_OPENSSL)
4455 
4456 /*
4457   OpenSSL 1.1 supports native platform threads,
4458   so we don't need the following callback functions.
4459 */
4460 #if OPENSSL_VERSION_NUMBER < 0x10100000L
4461 
openssl_id_function()4462 static unsigned long openssl_id_function()
4463 {
4464   return (unsigned long) pthread_self();
4465 }
4466 
4467 
openssl_dynlock_create(const char * file,int line)4468 static openssl_lock_t *openssl_dynlock_create(const char *file, int line)
4469 {
4470   openssl_lock_t *lock= new openssl_lock_t;
4471   mysql_rwlock_init(key_rwlock_openssl, &lock->lock);
4472   return lock;
4473 }
4474 
4475 
openssl_dynlock_destroy(openssl_lock_t * lock,const char * file,int line)4476 static void openssl_dynlock_destroy(openssl_lock_t *lock, const char *file,
4477             int line)
4478 {
4479   mysql_rwlock_destroy(&lock->lock);
4480   delete lock;
4481 }
4482 
4483 
openssl_lock_function(int mode,int n,const char * file,int line)4484 static void openssl_lock_function(int mode, int n, const char *file, int line)
4485 {
4486   if (n < 0 || n > CRYPTO_num_locks())
4487   {
4488     /* Lock number out of bounds. */
4489     sql_print_error("Fatal: OpenSSL interface problem (n = %d)", n);
4490     abort();
4491   }
4492   openssl_lock(mode, &openssl_stdlocks[n], file, line);
4493 }
4494 
4495 
openssl_lock(int mode,openssl_lock_t * lock,const char * file,int line)4496 static void openssl_lock(int mode, openssl_lock_t *lock, const char *file,
4497        int line)
4498 {
4499   int err;
4500   char const *what;
4501 
4502   switch (mode) {
4503   case CRYPTO_LOCK|CRYPTO_READ:
4504     what = "read lock";
4505     err= mysql_rwlock_rdlock(&lock->lock);
4506     break;
4507   case CRYPTO_LOCK|CRYPTO_WRITE:
4508     what = "write lock";
4509     err= mysql_rwlock_wrlock(&lock->lock);
4510     break;
4511   case CRYPTO_UNLOCK|CRYPTO_READ:
4512   case CRYPTO_UNLOCK|CRYPTO_WRITE:
4513     what = "unlock";
4514     err= mysql_rwlock_unlock(&lock->lock);
4515     break;
4516   default:
4517     /* Unknown locking mode. */
4518     sql_print_error("Fatal: OpenSSL interface problem (mode=0x%x)", mode);
4519     abort();
4520   }
4521   if (err)
4522   {
4523     sql_print_error("Fatal: can't %s OpenSSL lock", what);
4524     abort();
4525   }
4526 }
4527 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
4528 #endif /* HAVE_OPENSSL */
4529 
4530 
init_ssl()4531 static int init_ssl()
4532 {
4533 #ifdef HAVE_OPENSSL
4534 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
4535   CRYPTO_malloc_init();
4536 #else /* OPENSSL_VERSION_NUMBER < 0x10100000L */
4537   OPENSSL_malloc_init();
4538 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
4539   ssl_start();
4540 #ifndef EMBEDDED_LIBRARY
4541   if (opt_use_ssl)
4542   {
4543     enum enum_ssl_init_error error= SSL_INITERR_NOERROR;
4544 
4545     /* having ssl_acceptor_fd != 0 signals the use of SSL */
4546     ssl_acceptor_fd= new_VioSSLAcceptorFd(opt_ssl_key, opt_ssl_cert,
4547 					  opt_ssl_ca, opt_ssl_capath,
4548 					  opt_ssl_cipher, &error,
4549                                           opt_ssl_crl, opt_ssl_crlpath);
4550     DBUG_PRINT("info",("ssl_acceptor_fd: 0x%lx", (long) ssl_acceptor_fd));
4551 #if OPENSSL_VERSION_NUMBER < 0x10100000L
4552     ERR_remove_thread_state(0);
4553 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
4554     if (!ssl_acceptor_fd)
4555     {
4556       sql_print_warning("Failed to setup SSL");
4557       sql_print_warning("SSL error: %s", sslGetErrString(error));
4558       opt_use_ssl = 0;
4559       have_ssl= SHOW_OPTION_DISABLED;
4560     }
4561   }
4562   else
4563   {
4564     have_ssl= SHOW_OPTION_DISABLED;
4565   }
4566 #else
4567   have_ssl= SHOW_OPTION_DISABLED;
4568 #endif /* ! EMBEDDED_LIBRARY */
4569   if (des_key_file)
4570     load_des_key_file(des_key_file);
4571   if (init_rsa_keys())
4572     return 1;
4573 #endif /* HAVE_OPENSSL */
4574   return 0;
4575 }
4576 
4577 
end_ssl()4578 static void end_ssl()
4579 {
4580 #ifdef HAVE_OPENSSL
4581 #ifndef EMBEDDED_LIBRARY
4582   if (ssl_acceptor_fd)
4583   {
4584     free_vio_ssl_acceptor_fd(ssl_acceptor_fd);
4585     ssl_acceptor_fd= 0;
4586   }
4587 #endif /* ! EMBEDDED_LIBRARY */
4588   deinit_rsa_keys();
4589 #endif /* HAVE_OPENSSL */
4590 }
4591 
4592 /**
4593   Generate a UUID and save it into server_uuid variable.
4594 
4595   @return Retur 0 or 1 if an error occurred.
4596  */
generate_server_uuid()4597 static int generate_server_uuid()
4598 {
4599   THD *thd;
4600   Item_func_uuid *func_uuid;
4601   String uuid;
4602 
4603   /*
4604     To be able to run this from boot, we allocate a temporary THD
4605    */
4606   if (!(thd=new THD))
4607   {
4608     sql_print_error("Failed to generate a server UUID because it is failed"
4609                     " to allocate the THD.");
4610     return 1;
4611   }
4612   thd->thread_stack= (char*) &thd;
4613   thd->store_globals();
4614   lex_start(thd);
4615   func_uuid= new (thd->mem_root) Item_func_uuid();
4616   func_uuid->fixed= 1;
4617   func_uuid->val_str(&uuid);
4618   delete thd;
4619   /* Remember that we don't have a THD */
4620   my_pthread_setspecific_ptr(THR_THD,  0);
4621 
4622   strncpy(server_uuid, uuid.c_ptr(), UUID_LENGTH);
4623   server_uuid[UUID_LENGTH]= '\0';
4624   return 0;
4625 }
4626 
4627 /**
4628   Save all options which was auto-generated by server-self into the given file.
4629 
4630   @param fname The name of the file in which the auto-generated options will b
4631   e saved.
4632 
4633   @return Return 0 or 1 if an error occurred.
4634  */
flush_auto_options(const char * fname)4635 int flush_auto_options(const char* fname)
4636 {
4637   File fd;
4638   IO_CACHE io_cache;
4639   int result= 0;
4640 
4641   if ((fd= my_open((const char *)fname, O_CREAT|O_RDWR, MYF(MY_WME))) < 0)
4642   {
4643     sql_print_error("Failed to create file(file: '%s', errno %d)", fname, my_errno);
4644     return 1;
4645   }
4646 
4647   if (init_io_cache(&io_cache, fd, IO_SIZE*2, WRITE_CACHE, 0L, 0, MYF(MY_WME)))
4648   {
4649     sql_print_error("Failed to create a cache on (file: %s', errno %d)", fname, my_errno);
4650     my_close(fd, MYF(MY_WME));
4651     return 1;
4652   }
4653 
4654   my_b_seek(&io_cache, 0L);
4655   my_b_printf(&io_cache, "%s\n", "[auto]");
4656   my_b_printf(&io_cache, "server-uuid=%s\n", server_uuid);
4657 
4658   if (flush_io_cache(&io_cache) || my_sync(fd, MYF(MY_WME)))
4659     result= 1;
4660 
4661   my_close(fd, MYF(MY_WME));
4662   end_io_cache(&io_cache);
4663   return result;
4664 }
4665 
4666 /**
4667   File 'auto.cnf' resides in the data directory to hold values of options that
4668   server evaluates itself and that needs to be durable to sustain the server
4669   restart. There is only a section ['auto'] in the file. All these options are
4670   in the section. Only one option exists now, it is server_uuid.
4671   Note, the user may not supply any literal value to these auto-options, and
4672   only allowed to trigger (re)evaluation.
4673   For instance, 'server_uuid' value will be evaluated and stored if there is
4674   no corresponding line in the file.
4675   Because of the specifics of the auto-options, they need a seperate storage.
4676   Meanwhile, it is the 'auto.cnf' that has the same structure as 'my.cnf'.
4677 
4678   @todo consider to implement sql-query-able persistent storage by WL#5279.
4679   @return Return 0 or 1 if an error occurred.
4680  */
init_server_auto_options()4681 static int init_server_auto_options()
4682 {
4683   bool flush= false;
4684   char fname[FN_REFLEN];
4685   char *name= (char *)"auto";
4686   const char *groups[]= {"auto", NULL};
4687   char *uuid= 0;
4688   my_option auto_options[]= {
4689     {"server-uuid", 0, "", &uuid, &uuid,
4690       0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
4691     {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
4692   };
4693 
4694   DBUG_ENTER("init_server_auto_options");
4695 
4696   if (NULL == fn_format(fname, "auto.cnf", mysql_data_home, "",
4697                         MY_UNPACK_FILENAME | MY_SAFE_PATH))
4698     DBUG_RETURN(1);
4699 
4700   /* load_defaults require argv[0] is not null */
4701   char **argv= &name;
4702   int argc= 1;
4703   if (!check_file_permissions(fname, false))
4704   {
4705     /*
4706       Found a world writable file hence removing it as it is dangerous to write
4707       a new UUID into the same file.
4708      */
4709     my_delete(fname,MYF(MY_WME));
4710     sql_print_warning("World-writable config file '%s' has been removed.\n",
4711                       fname);
4712   }
4713 
4714   /* load all options in 'auto.cnf'. */
4715   if (my_load_defaults(fname, groups, &argc, &argv, NULL))
4716     DBUG_RETURN(1);
4717 
4718   /*
4719     Record the origial pointer allocated by my_load_defaults for free,
4720     because argv will be changed by handle_options
4721    */
4722   char **old_argv= argv;
4723   if (handle_options(&argc, &argv, auto_options, mysqld_get_one_option))
4724     DBUG_RETURN(1);
4725 
4726   DBUG_PRINT("info", ("uuid=%p=%s server_uuid=%s", uuid, uuid, server_uuid));
4727   if (uuid)
4728   {
4729     if (!Uuid::is_valid(uuid))
4730     {
4731       sql_print_error("The server_uuid stored in auto.cnf file is not a valid UUID.");
4732       goto err;
4733     }
4734     /*
4735       Uuid::is_valid() cannot do strict check on the length as it will be
4736       called by GTID::is_valid() as well (GTID = UUID:seq_no). We should
4737       explicitly add the *length check* here in this function.
4738 
4739       If UUID length is less than '36' (UUID_LENGTH), that error case would have
4740       got caught in above is_valid check. The below check is to make sure that
4741       length is not greater than UUID_LENGTH i.e., there are no extra characters
4742       (Garbage) at the end of the valid UUID.
4743     */
4744     if (strlen(uuid) > UUID_LENGTH)
4745     {
4746       sql_print_error("Garbage characters found at the end of the server_uuid "
4747                       "value in auto.cnf file. It should be of length '%d' "
4748                       "(UUID_LENGTH). Clear it and restart the server. ",
4749                       UUID_LENGTH);
4750       goto err;
4751     }
4752     strcpy(server_uuid, uuid);
4753   }
4754   else
4755   {
4756     DBUG_PRINT("info", ("generating server_uuid"));
4757     flush= TRUE;
4758     /* server_uuid will be set in the function */
4759     if (generate_server_uuid())
4760       goto err;
4761     DBUG_PRINT("info", ("generated server_uuid=%s", server_uuid));
4762     sql_print_warning("No existing UUID has been found, so we assume that this"
4763                       " is the first time that this server has been started."
4764                       " Generating a new UUID: %s.",
4765                       server_uuid);
4766   }
4767   /*
4768     The uuid has been copied to server_uuid, so the memory allocated by
4769     my_load_defaults can be freed now.
4770    */
4771   free_defaults(old_argv);
4772 
4773   if (flush)
4774     DBUG_RETURN(flush_auto_options(fname));
4775   DBUG_RETURN(0);
4776 err:
4777   free_defaults(argv);
4778   DBUG_RETURN(1);
4779 }
4780 
4781 
4782 static bool
initialize_storage_engine(char * se_name,const char * se_kind,plugin_ref * dest_plugin)4783 initialize_storage_engine(char *se_name, const char *se_kind,
4784                           plugin_ref *dest_plugin)
4785 {
4786   LEX_STRING name= { se_name, strlen(se_name) };
4787   plugin_ref plugin;
4788   handlerton *hton;
4789   if ((plugin= ha_resolve_by_name(0, &name, FALSE)))
4790     hton= plugin_data(plugin, handlerton*);
4791   else
4792   {
4793     sql_print_error("Unknown/unsupported storage engine: %s", se_name);
4794     return true;
4795   }
4796   if (!ha_storage_engine_is_enabled(hton))
4797   {
4798     if (!opt_bootstrap)
4799     {
4800       sql_print_error("Default%s storage engine (%s) is not available",
4801                       se_kind, se_name);
4802       return true;
4803     }
4804     DBUG_ASSERT(*dest_plugin);
4805   }
4806   else
4807   {
4808     /*
4809       Need to unlock as global_system_variables.table_plugin
4810       was acquired during plugin_init()
4811     */
4812     plugin_ref old_dest_plugin = *dest_plugin;
4813     *dest_plugin = plugin;
4814     plugin_unlock(0, old_dest_plugin);
4815   }
4816   return false;
4817 }
4818 
init_server_components()4819 static int init_server_components()
4820 {
4821   DBUG_ENTER("init_server_components");
4822   /*
4823     We need to call each of these following functions to ensure that
4824     all things are initialized so that unireg_abort() doesn't fail
4825   */
4826   mdl_init();
4827   if (table_def_init() | hostname_cache_init(host_cache_size))
4828     unireg_abort(1);
4829 
4830   query_cache_set_min_res_unit(query_cache_min_res_unit);
4831   query_cache_init();
4832   query_cache_resize(query_cache_size);
4833   randominit(&sql_rand,(ulong) server_start_time,(ulong) server_start_time/2);
4834   setup_fpu();
4835   init_thr_lock();
4836 #ifdef HAVE_REPLICATION
4837   init_slave_list();
4838 #endif
4839 
4840   /* Setup logs */
4841 
4842   /*
4843     Enable old-fashioned error log, except when the user has requested
4844     help information. Since the implementation of plugin server
4845     variables the help output is now written much later.
4846   */
4847   if (opt_error_log && !opt_help)
4848   {
4849     if (!log_error_file_ptr[0])
4850       fn_format(log_error_file, pidfile_name, mysql_data_home, ".err",
4851                 MY_REPLACE_EXT); /* replace '.<domain>' by '.err', bug#4997 */
4852     else
4853       fn_format(log_error_file, log_error_file_ptr, mysql_data_home, ".err",
4854                 MY_UNPACK_FILENAME | MY_SAFE_PATH);
4855     /*
4856       _ptr may have been set to my_disabled_option or "" if no argument was
4857       passed, but we need to show the real name in SHOW VARIABLES:
4858     */
4859     log_error_file_ptr= log_error_file;
4860     if (!log_error_file[0])
4861       opt_error_log= 0;                         // Too long file name
4862     else
4863     {
4864       my_bool res;
4865 #ifndef EMBEDDED_LIBRARY
4866       res= reopen_fstreams(log_error_file, stdout, stderr);
4867 #else
4868       res= reopen_fstreams(log_error_file, NULL, stderr);
4869 #endif
4870 
4871       if (!res)
4872         setbuf(stderr, NULL);
4873     }
4874   }
4875 
4876   proc_info_hook= set_thd_stage_info;
4877 
4878   /*
4879     Parsing the performance schema command line option and
4880     adjusting the values for options such as "open_files_limit",
4881     "max_connections", and "table_cache_size" may have reported
4882     warnings/information messages.
4883     Now that the logger is finally available, and redirected
4884     to the proper file when the --log--error option is used,
4885     print the buffered messages to the log.
4886   */
4887   buffered_logs.print();
4888   buffered_logs.cleanup();
4889 
4890   /*
4891     Now that the logger is available, redirect character set
4892     errors directly to the logger
4893     (instead of the buffered_logs used at the server startup time).
4894   */
4895   my_charset_error_reporter= charset_error_reporter;
4896 
4897   if (xid_cache_init())
4898   {
4899     sql_print_error("Out of memory");
4900     unireg_abort(1);
4901   }
4902 
4903   /*
4904     initialize delegates for extension observers, errors have already
4905     been reported in the function
4906   */
4907   if (delegates_init())
4908     unireg_abort(1);
4909 
4910   /* need to configure logging before initializing storage engines */
4911   if (opt_log_slave_updates && !opt_bin_log)
4912   {
4913     sql_print_warning("You need to use --log-bin to make "
4914                     "--log-slave-updates work.");
4915   }
4916 #ifdef WITH_WSREP
4917   if (!WSREP_ON && binlog_format_used && !opt_bin_log)
4918 #else
4919   if (binlog_format_used && !opt_bin_log)
4920 #endif
4921     sql_print_warning("You need to use --log-bin to make "
4922                       "--binlog-format work.");
4923 
4924   /* Check that we have not let the format to unspecified at this point */
4925   DBUG_ASSERT((uint)global_system_variables.binlog_format <=
4926               array_elements(binlog_format_names)-1);
4927 
4928 #ifdef HAVE_REPLICATION
4929   if (opt_log_slave_updates && replicate_same_server_id)
4930   {
4931     if (opt_bin_log)
4932     {
4933       sql_print_error("using --replicate-same-server-id in conjunction with \
4934 --log-slave-updates is impossible, it would lead to infinite loops in this \
4935 server.");
4936       unireg_abort(1);
4937     }
4938     else
4939       sql_print_warning("using --replicate-same-server-id in conjunction with \
4940 --log-slave-updates would lead to infinite loops in this server. However this \
4941 will be ignored as the --log-bin option is not defined.");
4942   }
4943 #endif
4944 
4945   opt_server_id_mask = ~ulong(0);
4946 #ifdef HAVE_REPLICATION
4947   opt_server_id_mask = (opt_server_id_bits == 32)?
4948     ~ ulong(0) : (1 << opt_server_id_bits) -1;
4949   if (server_id != (server_id & opt_server_id_mask))
4950   {
4951     sql_print_error("server-id configured is too large to represent with"
4952                     "server-id-bits configured.");
4953     unireg_abort(1);
4954   }
4955 #endif
4956 
4957   if (opt_bin_log)
4958   {
4959     /* Reports an error and aborts, if the --log-bin's path
4960        is a directory.*/
4961     if (opt_bin_logname &&
4962         opt_bin_logname[strlen(opt_bin_logname) - 1] == FN_LIBCHAR)
4963     {
4964       sql_print_error("Path '%s' is a directory name, please specify \
4965 a file name for --log-bin option", opt_bin_logname);
4966       unireg_abort(1);
4967     }
4968 
4969     /* Reports an error and aborts, if the --log-bin-index's path
4970        is a directory.*/
4971     if (opt_binlog_index_name &&
4972         opt_binlog_index_name[strlen(opt_binlog_index_name) - 1]
4973         == FN_LIBCHAR)
4974     {
4975       sql_print_error("Path '%s' is a directory name, please specify \
4976 a file name for --log-bin-index option", opt_binlog_index_name);
4977       unireg_abort(1);
4978     }
4979 
4980     char buf[FN_REFLEN];
4981     const char *ln;
4982     ln= mysql_bin_log.generate_name(opt_bin_logname, "-bin", 1, buf);
4983     if (!opt_bin_logname && !opt_binlog_index_name)
4984     {
4985       /*
4986         User didn't give us info to name the binlog index file.
4987         Picking `hostname`-bin.index like did in 4.x, causes replication to
4988         fail if the hostname is changed later. So, we would like to instead
4989         require a name. But as we don't want to break many existing setups, we
4990         only give warning, not error.
4991       */
4992       sql_print_warning("No argument was provided to --log-bin, and "
4993                         "--log-bin-index was not used; so replication "
4994                         "may break when this MySQL server acts as a "
4995                         "master and has his hostname changed!! Please "
4996                         "use '--log-bin=%s' to avoid this problem.", ln);
4997     }
4998     if (ln == buf)
4999     {
5000       my_free(opt_bin_logname);
5001       opt_bin_logname=my_strdup(buf, MYF(0));
5002     }
5003 #ifdef WITH_WSREP /* WSREP BEFORE SE */
5004     /*
5005       Wsrep initialization must happen at this point, because:
5006       - opt_bin_logname must be known when starting replication
5007         since SST may need it
5008       - SST may modify binlog index file, so it must be opened
5009         after SST has happened
5010      */
5011   }
5012 
5013   /* It's now safe to use thread specific memory */
5014   mysqld_server_initialized= 1;
5015 
5016   if (!wsrep_recovery)
5017   {
5018     if (opt_bootstrap) // bootsrap option given - disable wsrep functionality
5019     {
5020       wsrep_provider_init(WSREP_NONE);
5021       if (wsrep_init()) unireg_abort(1);
5022     }
5023     else // full wsrep initialization
5024     {
5025       // add basedir/bin to PATH to resolve wsrep script names
5026       char* const tmp_path((char*)alloca(strlen(mysql_home) +
5027                                            strlen("/bin") + 1));
5028       if (tmp_path)
5029       {
5030         strcpy(tmp_path, mysql_home);
5031         strcat(tmp_path, "/bin");
5032         wsrep_prepend_PATH(tmp_path);
5033       }
5034       else
5035       {
5036         WSREP_ERROR("Could not append %s/bin to PATH", mysql_home);
5037       }
5038 
5039       if (wsrep_before_SE())
5040       {
5041         set_ports(); // this is also called in network_init() later but we need
5042                      // to know mysqld_port now - lp:1071882
5043         wsrep_init_startup(true);
5044       }
5045     }
5046   }
5047   if (opt_bin_log)
5048   {
5049     /*
5050       Variable ln is not defined at this scope. We use opt_bin_logname instead.
5051       It should be the same as ln since
5052       - mysql_bin_log.generate_name() returns first argument if new log name
5053         is not generated
5054       - if new log name is generated, return value is assigned to ln and copied
5055         to opt_bin_logname above
5056      */
5057     if (mysql_bin_log.open_index_file(opt_binlog_index_name, opt_bin_logname,
5058                                       TRUE))
5059     {
5060       unireg_abort(1);
5061     }
5062 #else
5063     if (mysql_bin_log.open_index_file(opt_binlog_index_name, ln, TRUE))
5064     {
5065       unireg_abort(1);
5066     }
5067 #endif /* WITH_WSREP */
5068   }
5069 
5070   if (opt_bin_log)
5071   {
5072     log_bin_basename=
5073       rpl_make_log_name(opt_bin_logname, pidfile_name,
5074                         opt_bin_logname ? "" : "-bin");
5075     log_bin_index=
5076       rpl_make_log_name(opt_binlog_index_name, log_bin_basename, ".index");
5077     if (log_bin_basename == NULL || log_bin_index == NULL)
5078     {
5079       sql_print_error("Unable to create replication path names:"
5080                       " out of memory or path names too long"
5081                       " (path name exceeds " STRINGIFY_ARG(FN_REFLEN)
5082                       " or file name exceeds " STRINGIFY_ARG(FN_LEN) ").");
5083       unireg_abort(1);
5084     }
5085   }
5086 
5087 #ifndef EMBEDDED_LIBRARY
5088   DBUG_PRINT("debug",
5089              ("opt_bin_logname: %s, opt_relay_logname: %s, pidfile_name: %s",
5090               opt_bin_logname, opt_relay_logname, pidfile_name));
5091   if (opt_relay_logname)
5092   {
5093     relay_log_basename=
5094       rpl_make_log_name(opt_relay_logname, pidfile_name,
5095                         opt_relay_logname ? "" : "-relay-bin");
5096     relay_log_index=
5097       rpl_make_log_name(opt_relaylog_index_name, relay_log_basename, ".index");
5098     if (relay_log_basename == NULL || relay_log_index == NULL)
5099     {
5100       sql_print_error("Unable to create replication path names:"
5101                       " out of memory or path names too long"
5102                       " (path name exceeds " STRINGIFY_ARG(FN_REFLEN)
5103                       " or file name exceeds " STRINGIFY_ARG(FN_LEN) ").");
5104       unireg_abort(1);
5105     }
5106   }
5107 #endif /* !EMBEDDED_LIBRARY */
5108 
5109   /* call ha_init_key_cache() on all key caches to init them */
5110   process_key_caches(&ha_init_key_cache);
5111 
5112   /* Allow storage engine to give real error messages */
5113   if (ha_init_errors())
5114     DBUG_RETURN(1);
5115 
5116   if (opt_ignore_builtin_innodb)
5117     sql_print_warning("ignore-builtin-innodb is ignored "
5118                       "and will be removed in future releases.");
5119   if (gtid_server_init())
5120   {
5121     sql_print_error("Failed to initialize GTID structures.");
5122     unireg_abort(1);
5123   }
5124 
5125 #ifdef WITH_WSREP
5126   if (plugin_init(&remaining_argc, remaining_argv,
5127                   (opt_noacl ? PLUGIN_INIT_SKIP_PLUGIN_TABLE : 0) |
5128                   (opt_help ? PLUGIN_INIT_SKIP_INITIALIZATION : 0)))
5129   {
5130     sql_print_error("Failed to initialize plugins.");
5131     unireg_abort(1);
5132   }
5133   plugins_are_initialized= TRUE;  /* Don't separate from init function */
5134 #endif /* WITH_WSREP */
5135   /* we do want to exit if there are any other unknown options */
5136   if (remaining_argc > 1)
5137   {
5138     int ho_error;
5139     struct my_option no_opts[]=
5140     {
5141       {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
5142     };
5143     /*
5144       We need to eat any 'loose' arguments first before we conclude
5145       that there are unprocessed options.
5146     */
5147     my_getopt_skip_unknown= 0;
5148 
5149     if ((ho_error= handle_options(&remaining_argc, &remaining_argv, no_opts,
5150                                   mysqld_get_one_option)))
5151       unireg_abort(ho_error);
5152     /* Add back the program name handle_options removes */
5153     remaining_argc++;
5154     remaining_argv--;
5155     my_getopt_skip_unknown= TRUE;
5156 
5157     if (remaining_argc > 1)
5158     {
5159       fprintf(stderr, "%s: Too many arguments (first extra is '%s').\n"
5160               "Use --verbose --help to get a list of available options\n",
5161               my_progname, remaining_argv[1]);
5162       unireg_abort(1);
5163     }
5164   }
5165 
5166   if (opt_help)
5167     unireg_abort(0);
5168 
5169   /* if the errmsg.sys is not loaded, terminate to maintain behaviour */
5170   if (!DEFAULT_ERRMSGS[0][0])
5171     unireg_abort(1);
5172 
5173   /* We have to initialize the storage engines before CSV logging */
5174   if (ha_init())
5175   {
5176     sql_print_error("Can't init databases");
5177     unireg_abort(1);
5178   }
5179 
5180 #ifdef WITH_CSV_STORAGE_ENGINE
5181   if (opt_bootstrap)
5182     log_output_options= LOG_FILE;
5183   else
5184     logger.init_log_tables();
5185 
5186   if (log_output_options & LOG_NONE)
5187   {
5188     /*
5189       Issue a warining if there were specified additional options to the
5190       log-output along with NONE. Probably this wasn't what user wanted.
5191     */
5192     if ((log_output_options & LOG_NONE) && (log_output_options & ~LOG_NONE))
5193       sql_print_warning("There were other values specified to "
5194                         "log-output besides NONE. Disabling slow "
5195                         "and general logs anyway.");
5196     logger.set_handlers(LOG_FILE, LOG_NONE, LOG_NONE);
5197   }
5198   else
5199   {
5200     /* fall back to the log files if tables are not present */
5201     LEX_STRING csv_name={C_STRING_WITH_LEN("csv")};
5202     if (!plugin_is_ready(&csv_name, MYSQL_STORAGE_ENGINE_PLUGIN))
5203     {
5204       /* purecov: begin inspected */
5205       sql_print_error("CSV engine is not present, falling back to the "
5206                       "log files");
5207       log_output_options= (log_output_options & ~LOG_TABLE) | LOG_FILE;
5208       /* purecov: end */
5209     }
5210 
5211     logger.set_handlers(LOG_FILE, opt_slow_log ? log_output_options:LOG_NONE,
5212                         opt_log ? log_output_options:LOG_NONE);
5213   }
5214 #else
5215   logger.set_handlers(LOG_FILE, opt_slow_log ? LOG_FILE:LOG_NONE,
5216                       opt_log ? LOG_FILE:LOG_NONE);
5217 #endif
5218 
5219   /*
5220     Set the default storage engines
5221   */
5222   if (initialize_storage_engine(default_storage_engine, "",
5223                                 &global_system_variables.table_plugin))
5224     unireg_abort(1);
5225   if (initialize_storage_engine(default_tmp_storage_engine, " temp",
5226                                 &global_system_variables.temp_table_plugin))
5227     unireg_abort(1);
5228 
5229 #ifdef WITH_WSREP
5230   if (!opt_bin_log)
5231   {
5232     wsrep_emulate_bin_log= 1;
5233   }
5234 #endif
5235   if (total_ha_2pc > 1 || (1 == total_ha_2pc && opt_bin_log))
5236   {
5237     if (opt_bin_log)
5238       tc_log= &mysql_bin_log;
5239     else
5240 #ifdef WITH_WSREP
5241       if (WSREP_ON)
5242         tc_log=  &tc_log_dummy;
5243       else
5244         /*
5245          * wsrep hton grows total_ha_2pc count to 2, even in native mysql mode.
5246          * Have to force using tc_log_dummy here, as tc_log_mmap segfaults
5247          */
5248         tc_log=  &tc_log_dummy;
5249 #else
5250       tc_log= &tc_log_mmap;
5251 #endif /* WITH_WSREP */
5252   }
5253   else
5254     tc_log= &tc_log_dummy;
5255 
5256 #ifdef WITH_WSREP
5257   WSREP_DEBUG("Initial TC log open: %s",
5258               (tc_log == &mysql_bin_log) ? "binlog" :
5259               (tc_log == &tc_log_mmap) ? "mmap" :
5260               (tc_log == &tc_log_dummy) ? "dummy" : "unknown"
5261               );
5262 #endif
5263   if (tc_log->open(opt_bin_log ? opt_bin_logname : opt_tc_log_file))
5264   {
5265     sql_print_error("Can't init tc log");
5266     unireg_abort(1);
5267   }
5268 
5269   if (ha_recover(0))
5270   {
5271     unireg_abort(1);
5272   }
5273 
5274   if (gtid_mode >= 1 && opt_bootstrap)
5275   {
5276     sql_print_warning("Bootstrap mode disables GTIDs. Bootstrap mode "
5277     "should only be used by mysql_install_db which initializes the MySQL "
5278     "data directory and creates system tables.");
5279     gtid_mode= 0;
5280   }
5281   if (gtid_mode >= 1 && !(opt_bin_log && opt_log_slave_updates))
5282   {
5283     sql_print_error("--gtid-mode=ON or UPGRADE_STEP_1 or UPGRADE_STEP_2 requires --log-bin and --log-slave-updates");
5284     unireg_abort(1);
5285   }
5286   if (gtid_mode >= 2 && !enforce_gtid_consistency)
5287   {
5288     sql_print_error("--gtid-mode=ON or UPGRADE_STEP_1 requires --enforce-gtid-consistency");
5289     unireg_abort(1);
5290   }
5291   if (gtid_mode == 1 || gtid_mode == 2)
5292   {
5293     sql_print_error("--gtid-mode=UPGRADE_STEP_1 or --gtid-mode=UPGRADE_STEP_2 are not yet supported");
5294     unireg_abort(1);
5295   }
5296 
5297   if (opt_bin_log)
5298   {
5299     /*
5300       Configures what object is used by the current log to store processed
5301       gtid(s). This is necessary in the MYSQL_BIN_LOG::MYSQL_BIN_LOG to
5302       corretly compute the set of previous gtids.
5303     */
5304     mysql_bin_log.set_previous_gtid_set(
5305       const_cast<Gtid_set*>(gtid_state->get_logged_gtids()));
5306     if (mysql_bin_log.open_binlog(opt_bin_logname, 0,
5307                                   WRITE_CACHE, max_binlog_size, false,
5308                                   true/*need_lock_log=true*/,
5309                                   true/*need_lock_index=true*/,
5310                                   true/*need_sid_lock=true*/,
5311                                   NULL))
5312       unireg_abort(1);
5313   }
5314 
5315 #ifdef HAVE_REPLICATION
5316   if (opt_bin_log && expire_logs_days)
5317   {
5318     time_t purge_time= server_start_time - expire_logs_days*24*60*60;
5319     if (purge_time >= 0)
5320       mysql_bin_log.purge_logs_before_date(purge_time, true);
5321   }
5322 #endif
5323 
5324   if (opt_myisam_log)
5325     (void) mi_log(1);
5326 
5327 #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && !defined(EMBEDDED_LIBRARY)
5328   if (locked_in_memory && !getuid())
5329   {
5330     if (setreuid((uid_t)-1, 0) == -1)
5331     {                        // this should never happen
5332       sql_perror("setreuid");
5333       unireg_abort(1);
5334     }
5335     if (mlockall(MCL_CURRENT))
5336     {
5337       if (log_warnings)
5338   sql_print_warning("Failed to lock memory. Errno: %d\n",errno);
5339       locked_in_memory= 0;
5340     }
5341     if (user_info)
5342       set_user(mysqld_user, user_info);
5343   }
5344   else
5345 #endif
5346     locked_in_memory=0;
5347 
5348   ft_init_stopwords();
5349 
5350   init_max_user_conn();
5351   init_update_queries();
5352   DBUG_RETURN(0);
5353 }
5354 #ifndef EMBEDDED_LIBRARY
5355 
create_shutdown_thread()5356 static void create_shutdown_thread()
5357 {
5358 #ifdef __WIN__
5359   hEventShutdown=CreateEvent(0, FALSE, FALSE, shutdown_event_name);
5360   pthread_t hThread;
5361   int error;
5362   if ((error= mysql_thread_create(key_thread_handle_shutdown,
5363                                   &hThread, &connection_attrib,
5364                                   handle_shutdown, 0)))
5365     sql_print_warning("Can't create thread to handle shutdown requests"
5366                       " (errno= %d)", error);
5367 
5368   // On "Stop Service" we have to do regular shutdown
5369   Service.SetShutdownEvent(hEventShutdown);
5370 #endif /* __WIN__ */
5371 }
5372 
5373 #endif /* EMBEDDED_LIBRARY */
5374 
5375 #ifdef WITH_WSREP
start_wsrep_THD(void * arg)5376 pthread_handler_t start_wsrep_THD(void *arg)
5377 {
5378   THD *thd;
5379   wsrep_thd_processor_fun processor= (wsrep_thd_processor_fun)arg;
5380 
5381   if (my_thread_init())
5382   {
5383     WSREP_ERROR("Could not initialize thread");
5384     return(NULL);
5385   }
5386 
5387   if (!(thd= new THD(true, true)))
5388   {
5389     return(NULL);
5390   }
5391   mysql_mutex_lock(&LOCK_thread_count);
5392   thd->thread_id=thread_id++;
5393 
5394   thd->real_id=pthread_self(); // Keep purify happy
5395   add_global_thread(thd);
5396   thread_created++;
5397 
5398   my_net_init(&thd->net,(st_vio*) 0);
5399 
5400   DBUG_PRINT("wsrep",(("creating thread %lld"), (long long)thd->thread_id));
5401   thd->prior_thr_create_utime= thd->start_utime= my_micro_time();
5402   (void) mysql_mutex_unlock(&LOCK_thread_count);
5403 
5404   /* from bootstrap()... */
5405   thd->bootstrap=1;
5406   thd->max_client_packet_length= thd->net.max_packet;
5407   thd->security_ctx->master_access= ~(ulong)0;
5408 
5409   /* from handle_one_connection... */
5410   pthread_detach_this_thread();
5411 
5412   mysql_thread_set_psi_id(thd->thread_id);
5413   thd->thr_create_utime= my_micro_time();
5414   if (MYSQL_CALLBACK_ELSE(thread_scheduler, init_new_connection_thread, (), 0))
5415   {
5416     close_connection(thd, ER_OUT_OF_RESOURCES, 1);
5417     statistic_increment(aborted_connects,&LOCK_status);
5418     MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0));
5419 
5420     return(NULL);
5421   }
5422 
5423   /* now that we've called my_thread_init(), it is safe to call DBUG_* */
5424 
5425   thd->thread_stack= (char*) &thd;
5426   if (thd->store_globals())
5427   {
5428     close_connection(thd, ER_OUT_OF_RESOURCES, 1);
5429     statistic_increment(aborted_connects,&LOCK_status);
5430     MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0));
5431     delete thd;
5432 
5433     return(NULL);
5434   }
5435 
5436   /* from handle_bootstrap() */
5437 
5438   thd->system_thread= SYSTEM_THREAD_SLAVE_SQL;
5439   thd->security_ctx->skip_grants();
5440 
5441   /* handle_one_connection() again... */
5442   //thd->version= refresh_version;
5443   thd->proc_info= 0;
5444   thd->set_command(COM_SLEEP);
5445   thd->set_time();
5446   thd->init_for_queries();
5447 
5448   mysql_mutex_lock(&LOCK_thread_count);
5449   wsrep_running_threads++;
5450   mysql_cond_broadcast(&COND_thread_count);
5451   mysql_mutex_unlock(&LOCK_thread_count);
5452 
5453   mysql_mutex_lock(&LOCK_connection_count);
5454   ++connection_count;
5455   mysql_mutex_unlock(&LOCK_connection_count);
5456 
5457   processor(thd);
5458 
5459   close_connection(thd, 0, 1);
5460 
5461   mysql_mutex_lock(&LOCK_thread_count);
5462   wsrep_running_threads--;
5463   WSREP_DEBUG("wsrep running threads now: %lu", wsrep_running_threads);
5464   mysql_cond_broadcast(&COND_thread_count);
5465   mysql_mutex_unlock(&LOCK_thread_count);
5466 
5467   // Note: We can't call THD destructor without crashing
5468   // if plugins have not been initialized. However, in most of the
5469   // cases this means that pre SE initialization SST failed and
5470   // we are going to exit anyway.
5471   if (plugins_are_initialized)
5472   {
5473     net_end(&thd->net);
5474     MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 1));
5475   }
5476   else
5477   {
5478     // TODO: lightweight cleanup to get rid of:
5479     // 'Error in my_thread_global_end(): 2 threads didn't exit'
5480     // at server shutdown
5481   }
5482   return(NULL);
5483 }
5484 
5485 /**/
abort_replicated(THD * thd)5486 static bool abort_replicated(THD *thd)
5487 {
5488   bool ret_code= false;
5489   if (thd->wsrep_query_state== QUERY_COMMITTING)
5490   {
5491     if (wsrep_debug) WSREP_INFO("aborting replicated trx: %ju", (uintmax_t)thd->real_id);
5492 
5493     (void)wsrep_abort_thd(thd, thd, TRUE);
5494     ret_code= true;
5495   }
5496   return ret_code;
5497 }
5498 /**/
is_client_connection(THD * thd)5499 static inline bool is_client_connection(THD *thd)
5500 {
5501 #if REMOVE
5502 // REMOVE THIS LATER (lp:777201). Below we had to add an explicit check for
5503 // wsrep_applier since wsrep_exec_mode didn't seem to always work
5504 if (thd->wsrep_applier && thd->wsrep_exec_mode != REPL_RECV)
5505 WSREP_WARN("applier has wsrep_exec_mode = %d", thd->wsrep_exec_mode);
5506 
5507   if ( thd->slave_thread               || /* declared as mysql slave  */
5508        thd->system_thread              || /* declared as system thread */
5509       !thd->vio_ok()                   || /* server internal thread */
5510        thd->wsrep_exec_mode==REPL_RECV || /* applier or replaying thread */
5511        thd->wsrep_applier              || /* wsrep slave applier */
5512       !thd->variables.wsrep_on)           /* client, but fenced outside wsrep */
5513     return false;
5514 
5515   return true;
5516 #else
5517   return (thd->wsrep_client_thread && thd->variables.wsrep_on);
5518 #endif /* REMOVE */
5519 }
5520 
is_replaying_connection(THD * thd)5521 static inline bool is_replaying_connection(THD *thd)
5522 {
5523   bool ret;
5524 
5525   mysql_mutex_lock(&thd->LOCK_wsrep_thd);
5526   ret=  (thd->wsrep_conflict_state == REPLAYING) ? true : false;
5527   mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
5528 
5529   return ret;
5530 }
5531 
is_committing_connection(THD * thd)5532 static inline bool is_committing_connection(THD *thd)
5533 {
5534   bool ret;
5535 
5536   mysql_mutex_lock(&thd->LOCK_wsrep_thd);
5537   ret=  (thd->wsrep_query_state == QUERY_COMMITTING) ? true : false;
5538   mysql_mutex_unlock(&thd->LOCK_wsrep_thd);
5539 
5540   return ret;
5541 }
5542 
have_client_connections()5543 static bool have_client_connections()
5544 {
5545   Thread_iterator it= global_thread_list->begin();
5546   for (; it != global_thread_list->end(); ++it)
5547   {
5548     THD *tmp= *it;
5549     DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
5550                         tmp->thread_id));
5551     if (is_client_connection(tmp) && tmp->killed == THD::KILL_CONNECTION)
5552     {
5553       (void)abort_replicated(tmp);
5554       return true;
5555     }
5556   }
5557   return false;
5558 }
5559 
5560 /*
5561    returns the number of wsrep appliers running.
5562    However, the caller (thd parameter) is not taken in account
5563  */
have_wsrep_appliers(THD * thd)5564 static int have_wsrep_appliers(THD *thd)
5565 {
5566   int ret= 0;
5567 
5568   Thread_iterator it= global_thread_list->begin();
5569   for (; it != global_thread_list->end(); ++it)
5570   {
5571     THD *tmp= *it;
5572     ret+= (tmp != thd && tmp->wsrep_applier);
5573   }
5574   return ret;
5575 }
5576 
wsrep_close_thread(THD * thd)5577 static void wsrep_close_thread(THD *thd)
5578 {
5579   thd->killed= THD::KILL_CONNECTION;
5580   MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (thd));
5581   if (thd->mysys_var)
5582   {
5583     thd->mysys_var->abort=1;
5584     mysql_mutex_lock(&thd->mysys_var->mutex);
5585     if (thd->mysys_var->current_cond)
5586     {
5587       mysql_mutex_lock(thd->mysys_var->current_mutex);
5588       mysql_cond_broadcast(thd->mysys_var->current_cond);
5589       mysql_mutex_unlock(thd->mysys_var->current_mutex);
5590     }
5591     mysql_mutex_unlock(&thd->mysys_var->mutex);
5592   }
5593 }
5594 
have_committing_connections()5595 static my_bool have_committing_connections()
5596 {
5597   Thread_iterator it= global_thread_list->begin();
5598   for (; it != global_thread_list->end(); ++it)
5599   {
5600     THD *tmp= *it;
5601 
5602     if (!is_client_connection(tmp))
5603       continue;
5604 
5605     if (is_committing_connection(tmp))
5606     {
5607       return TRUE;
5608     }
5609   }
5610   return FALSE;
5611 }
5612 
wsrep_wait_committing_connections_close(int wait_time)5613 int wsrep_wait_committing_connections_close(int wait_time)
5614 {
5615   int sleep_time= 100;
5616 
5617   while (have_committing_connections() && wait_time > 0)
5618   {
5619     WSREP_DEBUG("wait for committing transaction to close: %d", wait_time);
5620     my_sleep(sleep_time);
5621     wait_time -= sleep_time;
5622   }
5623   if (have_committing_connections())
5624   {
5625     return 1;
5626   }
5627   return 0;
5628 }
5629 
wsrep_close_client_connections(my_bool wait_to_end)5630 void wsrep_close_client_connections(my_bool wait_to_end)
5631 {
5632   /*
5633     First signal all threads that it's time to die
5634   */
5635 
5636   /* Kill blocked pthreads */
5637   kill_blocked_pthreads_flag++;
5638   kill_blocked_pthreads();
5639 
5640   mysql_mutex_lock(&LOCK_thread_count); // For unlink from list
5641 
5642   Thread_iterator it= global_thread_list->begin();
5643   for (; it != global_thread_list->end(); ++it)
5644   {
5645     THD *tmp= *it;
5646     DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
5647                         tmp->thread_id));
5648     /* We skip slave threads & scheduler on this first loop through. */
5649     if (!is_client_connection(tmp))
5650       continue;
5651 
5652     if (is_replaying_connection(tmp))
5653     {
5654       tmp->killed= THD::KILL_CONNECTION;
5655       continue;
5656     }
5657 
5658     /* replicated transactions must be skipped */
5659     if (abort_replicated(tmp))
5660       continue;
5661 
5662     WSREP_DEBUG("closing connection %ld", tmp->thread_id);
5663     wsrep_close_thread(tmp);
5664   }
5665   mysql_mutex_unlock(&LOCK_thread_count);
5666 
5667   if (get_thread_count() > 0)
5668     sleep(2);                               // Give threads time to die
5669 
5670   mysql_mutex_lock(&LOCK_thread_count);
5671   /*
5672     Force remaining threads to die by closing the connection to the client
5673   */
5674 
5675   for (it= global_thread_list->begin(); it != global_thread_list->end(); ++it)
5676   {
5677     THD *tmp= *it;
5678 #ifndef __bsdi__				// Bug in BSDI kernel
5679     if (is_client_connection(tmp) &&
5680         !abort_replicated(tmp)    &&
5681 	!is_replaying_connection(tmp))
5682     {
5683       WSREP_INFO("killing local connection: %ld",tmp->thread_id);
5684       close_connection(tmp,0,0);
5685     }
5686 #endif
5687   }
5688 
5689   DBUG_PRINT("quit",("Waiting for threads to die (count=%u)", get_thread_count()));
5690   if (wsrep_debug)
5691     WSREP_INFO("waiting for client connections to close: %u",
5692                get_thread_count());
5693 
5694   while (wait_to_end && have_client_connections())
5695   {
5696     mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
5697     DBUG_PRINT("quit",("One thread died (count=%u)", get_thread_count()));
5698   }
5699 
5700   mysql_mutex_unlock(&LOCK_thread_count);
5701 
5702   /* All client connection threads have now been aborted */
5703 }
5704 
wsrep_close_applier(THD * thd)5705 void wsrep_close_applier(THD *thd)
5706 {
5707   WSREP_DEBUG("closing applier %ld", thd->thread_id);
5708   wsrep_close_thread(thd);
5709 }
5710 
wsrep_close_threads(THD * thd)5711 static void wsrep_close_threads(THD *thd)
5712 {
5713   mysql_mutex_lock(&LOCK_thread_count); // For unlink from list
5714 
5715   Thread_iterator it= global_thread_list->begin();
5716   for (; it != global_thread_list->end(); ++it)
5717   {
5718     THD *tmp= *it;
5719     DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
5720                        tmp->thread_id));
5721     /* We skip slave threads & scheduler on this first loop through. */
5722     if (tmp->wsrep_applier && tmp != thd)
5723     {
5724       WSREP_DEBUG("closing wsrep thread %ld", tmp->thread_id);
5725       wsrep_close_thread (tmp);
5726     }
5727   }
5728 
5729   mysql_mutex_unlock(&LOCK_thread_count);
5730 }
5731 
wsrep_close_applier_threads(int count)5732 void wsrep_close_applier_threads(int count)
5733 {
5734   mysql_mutex_lock(&LOCK_thread_count); // For unlink from list
5735 
5736   Thread_iterator it= global_thread_list->begin();
5737   for (; it != global_thread_list->end(); ++it)
5738   {
5739     THD *tmp= *it;
5740     DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
5741                        tmp->thread_id));
5742     /* We skip slave threads & scheduler on this first loop through. */
5743     if (tmp->wsrep_applier)
5744     {
5745       WSREP_DEBUG("closing wsrep applier thread %ld", tmp->thread_id);
5746       tmp->wsrep_applier_closing= TRUE;
5747       count--;
5748     }
5749   }
5750 
5751   mysql_mutex_unlock(&LOCK_thread_count);
5752 }
5753 
wsrep_wait_appliers_close(THD * thd)5754 void wsrep_wait_appliers_close(THD *thd)
5755 {
5756   /* Wait for wsrep appliers to gracefully exit */
5757   mysql_mutex_lock(&LOCK_thread_count);
5758   while (have_wsrep_appliers(thd) > 1)
5759   // 1 is for rollbacker thread which needs to be killed explicitly.
5760   // This gotta be fixed in a more elegant manner if we gonna have arbitrary
5761   // number of non-applier wsrep threads.
5762   {
5763     mysql_cond_wait(&COND_thread_count,&LOCK_thread_count);
5764     DBUG_PRINT("quit",("One applier died (count=%u)", get_thread_count()));
5765   }
5766   mysql_mutex_unlock(&LOCK_thread_count);
5767   /* Now kill remaining wsrep threads: rollbacker */
5768   wsrep_close_threads (thd);
5769   /* and wait for them to die */
5770   mysql_mutex_lock(&LOCK_thread_count);
5771   while (have_wsrep_appliers(thd) > 0)
5772   {
5773     mysql_cond_wait(&COND_thread_count,&LOCK_thread_count);
5774     DBUG_PRINT("quit",("One thread died (count=%u)", get_thread_count()));
5775   }
5776   mysql_mutex_unlock(&LOCK_thread_count);
5777 
5778   /* All wsrep applier threads have now been aborted. However, if this thread
5779      is also applier, we are still running...
5780   */
5781 }
5782 
wsrep_kill_mysql(THD * thd)5783 void wsrep_kill_mysql(THD *thd)
5784 {
5785   if (mysqld_server_started)
5786   {
5787     if (!shutdown_in_progress)
5788     {
5789       WSREP_INFO("starting shutdown");
5790       kill_mysql();
5791     }
5792   }
5793   else
5794   {
5795     unireg_abort(1);
5796   }
5797 }
5798 #endif /* WITH_WSREP */
5799 
5800 #if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
handle_connections_methods()5801 static void handle_connections_methods()
5802 {
5803   pthread_t hThread;
5804   int error;
5805   DBUG_ENTER("handle_connections_methods");
5806   if (hPipe == INVALID_HANDLE_VALUE &&
5807       (!have_tcpip || opt_disable_networking) &&
5808       !opt_enable_shared_memory)
5809   {
5810     sql_print_error("TCP/IP, --shared-memory, or --named-pipe should be configured on NT OS");
5811     unireg_abort(1);        // Will not return
5812   }
5813 
5814   mysql_mutex_lock(&LOCK_thread_count);
5815   mysql_cond_init(key_COND_handler_count, &COND_handler_count, NULL);
5816   handler_count=0;
5817   mysql_rwlock_init(key_rwlock_LOCK_named_pipe_full_access_group,
5818                     &LOCK_named_pipe_full_access_group);
5819   if (hPipe != INVALID_HANDLE_VALUE)
5820   {
5821     handler_count++;
5822     if ((error= mysql_thread_create(key_thread_handle_con_namedpipes,
5823                                     &hThread, &connection_attrib,
5824                                     handle_connections_namedpipes, 0)))
5825     {
5826       sql_print_warning("Can't create thread to handle named pipes"
5827                         " (errno= %d)", error);
5828       handler_count--;
5829     }
5830   }
5831   if (have_tcpip && !opt_disable_networking)
5832   {
5833     handler_count++;
5834     if ((error= mysql_thread_create(key_thread_handle_con_sockets,
5835                                     &hThread, &connection_attrib,
5836                                     handle_connections_sockets_thread, 0)))
5837     {
5838       sql_print_warning("Can't create thread to handle TCP/IP",
5839                         " (errno= %d)", error);
5840       handler_count--;
5841     }
5842   }
5843 #ifdef HAVE_SMEM
5844   if (opt_enable_shared_memory)
5845   {
5846     handler_count++;
5847     if ((error= mysql_thread_create(key_thread_handle_con_sharedmem,
5848                                     &hThread, &connection_attrib,
5849                                     handle_connections_shared_memory, 0)))
5850     {
5851       sql_print_warning("Can't create thread to handle shared memory",
5852                         " (errno= %d)", error);
5853       handler_count--;
5854     }
5855   }
5856 #endif
5857 
5858   while (handler_count > 0)
5859     mysql_cond_wait(&COND_handler_count, &LOCK_thread_count);
5860   mysql_mutex_unlock(&LOCK_thread_count);
5861   DBUG_VOID_RETURN;
5862 }
5863 
decrement_handler_count()5864 void decrement_handler_count()
5865 {
5866   mysql_mutex_lock(&LOCK_thread_count);
5867   handler_count--;
5868   mysql_cond_signal(&COND_handler_count);
5869   mysql_mutex_unlock(&LOCK_thread_count);
5870   my_thread_end();
5871 }
5872 #else
5873 #define decrement_handler_count()
5874 #endif /* defined(_WIN32) || defined(HAVE_SMEM) */
5875 
5876 
5877 #ifndef EMBEDDED_LIBRARY
5878 #ifndef DBUG_OFF
5879 /*
5880   Debugging helper function to keep the locale database
5881   (see sql_locale.cc) and max_month_name_length and
5882   max_day_name_length variable values in consistent state.
5883 */
test_lc_time_sz()5884 static void test_lc_time_sz()
5885 {
5886   DBUG_ENTER("test_lc_time_sz");
5887   for (MY_LOCALE **loc= my_locales; *loc; loc++)
5888   {
5889     uint max_month_len= 0;
5890     uint max_day_len = 0;
5891     for (const char **month= (*loc)->month_names->type_names; *month; month++)
5892     {
5893       set_if_bigger(max_month_len,
5894                     my_numchars_mb(&my_charset_utf8_general_ci,
5895                                    *month, *month + strlen(*month)));
5896     }
5897     for (const char **day= (*loc)->day_names->type_names; *day; day++)
5898     {
5899       set_if_bigger(max_day_len,
5900                     my_numchars_mb(&my_charset_utf8_general_ci,
5901                                    *day, *day + strlen(*day)));
5902     }
5903     if ((*loc)->max_month_name_length != max_month_len ||
5904         (*loc)->max_day_name_length != max_day_len)
5905     {
5906       DBUG_PRINT("Wrong max day name(or month name) length for locale:",
5907                  ("%s", (*loc)->name));
5908       DBUG_ASSERT(0);
5909     }
5910   }
5911   DBUG_VOID_RETURN;
5912 }
5913 #endif//DBUG_OFF
5914 
5915 #ifdef __WIN__
win_main(int argc,char ** argv)5916 int win_main(int argc, char **argv)
5917 #else
5918 int mysqld_main(int argc, char **argv)
5919 #endif
5920 {
5921   /*
5922     Perform basic thread library and malloc initialization,
5923     to be able to read defaults files and parse options.
5924   */
5925   my_progname= argv[0];
5926 
5927 #ifndef _WIN32
5928   // For windows, my_init() is called from the win specific mysqld_main
5929   if (my_init())                 // init my_sys library & pthreads
5930   {
5931     fprintf(stderr, "my_init() failed.");
5932     return 1;
5933   }
5934 #endif
5935 #ifdef WITH_WSREP
5936   mysqld_server_initialized= 0;
5937   wsrep_filter_new_cluster (&argc, argv);
5938 #endif /* WITH_WSREP */
5939 
5940   orig_argc= argc;
5941   orig_argv= argv;
5942   my_getopt_use_args_separator= TRUE;
5943   my_defaults_read_login_file= FALSE;
5944   if (load_defaults(MYSQL_CONFIG_NAME, load_default_groups, &argc, &argv))
5945     return 1;
5946   my_getopt_use_args_separator= FALSE;
5947   defaults_argc= argc;
5948   defaults_argv= argv;
5949   remaining_argc= argc;
5950   remaining_argv= argv;
5951 
5952   /* Must be initialized early for comparison of options name */
5953   system_charset_info= &my_charset_utf8_general_ci;
5954 
5955   init_sql_statement_names();
5956   sys_var_init();
5957 
5958   int ho_error;
5959 
5960 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
5961   /*
5962     Initialize the array of performance schema instrument configurations.
5963   */
5964   init_pfs_instrument_array();
5965 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
5966 
5967   ho_error= handle_early_options();
5968 
5969   {
5970     ulong requested_open_files;
5971     adjust_related_options(&requested_open_files);
5972 
5973 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
5974     if (ho_error == 0)
5975     {
5976       if (pfs_param.m_enabled && !opt_help && !opt_bootstrap)
5977       {
5978         /* Add sizing hints from the server sizing parameters. */
5979         pfs_param.m_hints.m_table_definition_cache= table_def_size;
5980         pfs_param.m_hints.m_table_open_cache= table_cache_size;
5981         pfs_param.m_hints.m_max_connections= max_connections;
5982 	pfs_param.m_hints.m_open_files_limit= requested_open_files;
5983         PSI_hook= initialize_performance_schema(&pfs_param);
5984         if (PSI_hook == NULL)
5985         {
5986           pfs_param.m_enabled= false;
5987           buffered_logs.buffer(WARNING_LEVEL,
5988                                "Performance schema disabled (reason: init failed).");
5989         }
5990       }
5991     }
5992 #else
5993   /*
5994     Other provider of the instrumentation interface should
5995     initialize PSI_hook here:
5996     - HAVE_PSI_INTERFACE is for the instrumentation interface
5997     - WITH_PERFSCHEMA_STORAGE_ENGINE is for one implementation
5998       of the interface,
5999     but there could be alternate implementations, which is why
6000     these two defines are kept separate.
6001   */
6002 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
6003   }
6004 
6005 #ifdef HAVE_PSI_INTERFACE
6006   /*
6007     Obtain the current performance schema instrumentation interface,
6008     if available.
6009   */
6010   if (PSI_hook)
6011   {
6012     PSI *psi_server= (PSI*) PSI_hook->get_interface(PSI_CURRENT_VERSION);
6013     if (likely(psi_server != NULL))
6014     {
6015       set_psi_server(psi_server);
6016 
6017       /*
6018         Now that we have parsed the command line arguments, and have initialized
6019         the performance schema itself, the next step is to register all the
6020         server instruments.
6021       */
6022       init_server_psi_keys();
6023       /* Instrument the main thread */
6024       PSI_thread *psi= PSI_THREAD_CALL(new_thread)(key_thread_main, NULL, 0);
6025       PSI_THREAD_CALL(set_thread)(psi);
6026 
6027       /*
6028         Now that some instrumentation is in place,
6029         recreate objects which were initialised early,
6030         so that they are instrumented as well.
6031       */
6032       my_thread_global_reinit();
6033     }
6034   }
6035 #endif /* HAVE_PSI_INTERFACE */
6036 
6037   init_error_log_mutex();
6038 
6039   /* Set signal used to kill MySQL */
6040 #if defined(SIGUSR2)
6041   thr_kill_signal= SIGUSR2;
6042 #else
6043   thr_kill_signal= SIGINT;
6044 #endif
6045 
6046   /* Initialize audit interface globals. Audit plugins are inited later. */
6047   mysql_audit_initialize();
6048 
6049   /*
6050     Perform basic logger initialization logger. Should be called after
6051     MY_INIT, as it initializes mutexes. Log tables are inited later.
6052   */
6053   logger.init_base();
6054 
6055   if (ho_error)
6056   {
6057     /*
6058       Parsing command line option failed,
6059       Since we don't have a workable remaining_argc/remaining_argv
6060       to continue the server initialization, this is as far as this
6061       code can go.
6062       This is the best effort to log meaningful messages:
6063       - messages will be printed to stderr, which is not redirected yet,
6064       - messages will be printed in the NT event log, for windows.
6065     */
6066     buffered_logs.print();
6067     buffered_logs.cleanup();
6068     /*
6069       Not enough initializations for unireg_abort()
6070       Using exit() for windows.
6071     */
6072     exit (ho_error);
6073   }
6074 
6075 #ifdef _CUSTOMSTARTUPCONFIG_
6076   if (_cust_check_startup())
6077   {
6078     / * _cust_check_startup will report startup failure error * /
6079     exit(1);
6080   }
6081 #endif
6082 
6083   if (init_common_variables())
6084     unireg_abort(1);        // Will do exit
6085 
6086   my_init_signals();
6087 
6088   size_t guardize= 0;
6089   int retval= pthread_attr_getguardsize(&connection_attrib, &guardize);
6090   DBUG_ASSERT(retval == 0);
6091   if (retval != 0)
6092     guardize= my_thread_stack_size;
6093 
6094 #if defined(__ia64__) || defined(__ia64)
6095   /*
6096     Peculiar things with ia64 platforms - it seems we only have half the
6097     stack size in reality, so we have to double it here
6098   */
6099   guardize= my_thread_stack_size;
6100 #endif
6101 
6102   pthread_attr_setstacksize(&connection_attrib,
6103                             my_thread_stack_size + guardize);
6104 
6105 #ifdef HAVE_PTHREAD_ATTR_GETSTACKSIZE
6106   {
6107     /* Retrieve used stack size;  Needed for checking stack overflows */
6108     size_t stack_size= 0;
6109     pthread_attr_getstacksize(&connection_attrib, &stack_size);
6110 
6111     /* We must check if stack_size = 0 as Solaris 2.9 can return 0 here */
6112     if (stack_size && stack_size < (my_thread_stack_size + guardize))
6113     {
6114       if (log_warnings)
6115         sql_print_warning("Asked for %lu thread stack, but got %ld",
6116                           my_thread_stack_size + guardize, (long) stack_size);
6117 #if defined(__ia64__) || defined(__ia64)
6118       my_thread_stack_size= stack_size / 2;
6119 #else
6120       my_thread_stack_size= stack_size - guardize;
6121 #endif
6122     }
6123   }
6124 #endif
6125 
6126   (void) thr_setconcurrency(concurrency); // 10 by default
6127 
6128   select_thread=pthread_self();
6129   select_thread_in_use=1;
6130 
6131 #ifdef HAVE_LIBWRAP
6132   libwrapName= my_progname+dirname_length(my_progname);
6133   openlog(libwrapName, LOG_PID, LOG_AUTH);
6134 #endif /* HAVE_LIBWRAP */
6135 
6136 #ifndef DBUG_OFF
6137   test_lc_time_sz();
6138   srand(time(NULL));
6139 #endif
6140 
6141   /*
6142     We have enough space for fiddling with the argv, continue
6143   */
6144   check_data_home(mysql_real_data_home);
6145   if (my_setwd(mysql_real_data_home,MYF(MY_WME)) && !opt_help)
6146     unireg_abort(1);        /* purecov: inspected */
6147 
6148   if ((user_info= check_user(mysqld_user)))
6149   {
6150 #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
6151     if (locked_in_memory) // getuid() == 0 here
6152       set_effective_user(user_info);
6153     else
6154 #endif
6155       set_user(mysqld_user, user_info);
6156   }
6157 
6158   if (opt_bin_log && server_id == 0)
6159   {
6160     server_id= 1;
6161 #ifdef EXTRA_DEBUG
6162     sql_print_warning("You have enabled the binary log, but you haven't set "
6163                       "server-id to a non-zero value: we force server id to 1; "
6164                       "updates will be logged to the binary log, but "
6165                       "connections from slaves will not be accepted.");
6166 #endif
6167   }
6168 
6169   /*
6170    The subsequent calls may take a long time : e.g. innodb log read.
6171    Thus set the long running service control manager timeout
6172   */
6173 #if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
6174   Service.SetSlowStarting(slow_start_timeout);
6175 #endif
6176 
6177 #ifdef WITH_WSREP
6178   /*
6179     Make sure that SSL library gets initialized before WSREP provider
6180     is loaded. This is to ensure that possible server side initialization
6181     does not have any side effects while the provider is already running
6182     with open SSL sessions.
6183   */
6184   ssl_start();
6185 #endif /* */
6186   if (init_server_components())
6187     unireg_abort(1);
6188 
6189   /*
6190     Each server should have one UUID. We will create it automatically, if it
6191     does not exist.
6192    */
6193   if (!opt_bootstrap)
6194   {
6195     if (init_server_auto_options())
6196     {
6197       sql_print_error("Initialzation of the server's UUID failed because it could"
6198                       " not be read from the auto.cnf file. If this is a new"
6199                       " server, the initialization failed because it was not"
6200                       " possible to generate a new UUID.");
6201       unireg_abort(1);
6202     }
6203 
6204     if (opt_bin_log)
6205     {
6206       /*
6207         Add server_uuid to the sid_map.  This must be done after
6208         server_uuid has been initialized in init_server_auto_options and
6209         after the binary log (and sid_map file) has been initialized in
6210         init_server_components().
6211 
6212         No error message is needed: init_sid_map() prints a message.
6213       */
6214       global_sid_lock->rdlock();
6215       int ret= gtid_state->init();
6216       global_sid_lock->unlock();
6217       if (ret)
6218         unireg_abort(1);
6219 
6220       if (mysql_bin_log.init_gtid_sets(
6221             const_cast<Gtid_set *>(gtid_state->get_logged_gtids()),
6222             const_cast<Gtid_set *>(gtid_state->get_lost_gtids()),
6223             NULL,
6224             opt_master_verify_checksum,
6225             true/*true=need lock*/, true))
6226         unireg_abort(1);
6227 
6228       /*
6229         Write the previous set of gtids at this point because during
6230         the creation of the binary log this is not done as we cannot
6231         move the init_gtid_sets() to a place before openning the binary
6232         log. This requires some investigation.
6233 
6234         /Alfranio
6235       */
6236       if (gtid_mode > 0)
6237       {
6238         global_sid_lock->wrlock();
6239         const Gtid_set *logged_gtids= gtid_state->get_logged_gtids();
6240         if (gtid_mode > 1 || !logged_gtids->is_empty())
6241         {
6242           Previous_gtids_log_event prev_gtids_ev(logged_gtids);
6243           global_sid_lock->unlock();
6244 
6245           prev_gtids_ev.checksum_alg= binlog_checksum_options;
6246 
6247           if (prev_gtids_ev.write(mysql_bin_log.get_log_file()))
6248             unireg_abort(1);
6249           mysql_bin_log.add_bytes_written(prev_gtids_ev.data_written);
6250 
6251           if (flush_io_cache(mysql_bin_log.get_log_file()) ||
6252               mysql_file_sync(mysql_bin_log.get_log_file()->file, MYF(MY_WME)))
6253             unireg_abort(1);
6254         }
6255         else
6256           global_sid_lock->unlock();
6257       }
6258     }
6259   }
6260 
6261   if (init_ssl())
6262     unireg_abort(1);
6263   network_init();
6264 
6265 #ifdef __WIN__
6266   if (!opt_console)
6267   {
6268     if (reopen_fstreams(log_error_file, stdout, stderr))
6269       unireg_abort(1);
6270     setbuf(stderr, NULL);
6271   }
6272 #endif
6273 
6274   /*
6275    Initialize my_str_malloc(), my_str_realloc() and my_str_free()
6276   */
6277   my_str_malloc= &my_str_malloc_mysqld;
6278   my_str_free= &my_str_free_mysqld;
6279   my_str_realloc= &my_str_realloc_mysqld;
6280 
6281 #ifdef WITH_WSREP /* WSREP AFTER SE */
6282   if (wsrep_recovery)
6283   {
6284     select_thread_in_use= 0;
6285     wsrep_recover();
6286     unireg_abort(0);
6287   }
6288 #endif /* WITH_WSREP */
6289   /*
6290     init signals & alarm
6291     After this we can't quit by a simple unireg_abort
6292   */
6293   error_handler_hook= my_message_sql;
6294   start_signal_handler();       // Creates pidfile
6295   sql_print_warning_hook = sql_print_warning;
6296 
6297   if (mysql_rm_tmp_tables() || acl_init(opt_noacl) ||
6298       my_tz_init((THD *)0, default_tz_name, opt_bootstrap))
6299   {
6300     abort_loop=1;
6301     select_thread_in_use=0;
6302 
6303     (void) pthread_kill(signal_thread, MYSQL_KILL_SIGNAL);
6304 
6305     delete_pid_file(MYF(MY_WME));
6306 
6307     if (mysql_socket_getfd(unix_sock) != INVALID_SOCKET)
6308       unlink(mysqld_unix_port);
6309     exit(1);
6310   }
6311 
6312   if (!opt_noacl)
6313     (void) grant_init();
6314 
6315   if (!opt_bootstrap)
6316     servers_init(0);
6317 
6318   if (!opt_noacl)
6319   {
6320 #ifdef HAVE_DLOPEN
6321     udf_init();
6322 #endif
6323   }
6324 
6325   init_status_vars();
6326   /* If running with bootstrap, do not start replication. */
6327   if (opt_bootstrap)
6328     opt_skip_slave_start= 1;
6329 
6330   check_binlog_cache_size(NULL);
6331   check_binlog_stmt_cache_size(NULL);
6332 
6333   binlog_unsafe_map_init();
6334 
6335   /* If running with bootstrap, do not start replication. */
6336   if (!opt_bootstrap)
6337   {
6338     // Make @@slave_skip_errors show the nice human-readable value.
6339     set_slave_skip_errors(&opt_slave_skip_errors);
6340 
6341     /*
6342       init_slave() must be called after the thread keys are created.
6343     */
6344     if (server_id != 0)
6345       init_slave(); /* Ignoring errors while configuring replication. */
6346   }
6347 
6348 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
6349   initialize_performance_schema_acl(opt_bootstrap);
6350   /*
6351     Do not check the structure of the performance schema tables
6352     during bootstrap:
6353     - the tables are not supposed to exist yet, bootstrap will create them
6354     - a check would print spurious error messages
6355   */
6356   if (! opt_bootstrap)
6357     check_performance_schema();
6358 #endif
6359 
6360   initialize_information_schema_acl();
6361 
6362   execute_ddl_log_recovery();
6363 
6364   if (Events::init(opt_noacl || opt_bootstrap))
6365     unireg_abort(1);
6366 
6367 #ifdef WITH_WSREP /* WSREP AFTER SE */
6368   if (opt_bootstrap)
6369   {
6370     /*! bootstrap wsrep init was taken care of above */
6371   }
6372   else
6373   {
6374     wsrep_SE_initialized(WSREP_SE_INIT_RESULT_SUCCESS);
6375     if (wsrep_before_SE())
6376     {
6377       /*! in case of SST wsrep waits for wsrep->sst_received */
6378       wsrep_sst_continue();
6379     }
6380     else
6381     {
6382       wsrep_init_startup (false);
6383     }
6384 
6385     wsrep_create_appliers(wsrep_slave_threads - 1);
6386   }
6387 #endif /* WITH_WSREP */
6388   if (opt_bootstrap)
6389   {
6390     select_thread_in_use= 0;                    // Allow 'kill' to work
6391     /* Signal threads waiting for server to be started */
6392     mysql_mutex_lock(&LOCK_server_started);
6393     mysqld_server_started= 1;
6394     mysql_cond_broadcast(&COND_server_started);
6395     mysql_mutex_unlock(&LOCK_server_started);
6396 
6397     bootstrap(mysql_stdin);
6398     unireg_abort(bootstrap_error ? 1 : 0);
6399   }
6400   if (opt_init_file && *opt_init_file)
6401   {
6402     if (read_init_file(opt_init_file))
6403       unireg_abort(1);
6404   }
6405 
6406   create_shutdown_thread();
6407   start_handle_manager();
6408 
6409   sql_print_information(ER_DEFAULT(ER_STARTUP),my_progname,server_version,
6410                         ((mysql_socket_getfd(unix_sock) == INVALID_SOCKET) ? (char*) ""
6411                                                        : mysqld_unix_port),
6412                          mysqld_port,
6413                          MYSQL_COMPILATION_COMMENT);
6414 #if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
6415   Service.SetRunning();
6416 #endif
6417 
6418 
6419   /* Signal threads waiting for server to be started */
6420   mysql_mutex_lock(&LOCK_server_started);
6421   mysqld_server_started= 1;
6422   mysql_cond_broadcast(&COND_server_started);
6423   mysql_mutex_unlock(&LOCK_server_started);
6424 
6425 #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
6426   /* engine specific hook, to be made generic */
6427   if (ndb_wait_setup_func && ndb_wait_setup_func(opt_ndb_wait_setup))
6428   {
6429     sql_print_warning("NDB : Tables not available after %lu seconds."
6430                       "  Consider increasing --ndb-wait-setup value",
6431                       opt_ndb_wait_setup);
6432   }
6433 #endif
6434 
6435   MYSQL_SET_STAGE(0 ,__FILE__, __LINE__);
6436 
6437 #if defined(_WIN32) || defined(HAVE_SMEM)
6438   handle_connections_methods();
6439 #else
6440   handle_connections_sockets();
6441 #endif /* _WIN32 || HAVE_SMEM */
6442 
6443   /* (void) pthread_attr_destroy(&connection_attrib); */
6444 
6445   DBUG_PRINT("quit",("Exiting main thread"));
6446 
6447 #ifndef __WIN__
6448 #ifdef EXTRA_DEBUG2
6449   sql_print_error("Before Lock_thread_count");
6450 #endif
6451 #ifdef WITH_WSREP
6452   WSREP_DEBUG("Before Lock_thread_count");
6453 #endif
6454   mysql_mutex_lock(&LOCK_thread_count);
6455   DBUG_PRINT("quit", ("Got thread_count mutex"));
6456   select_thread_in_use=0;     // For close_connections
6457   mysql_mutex_unlock(&LOCK_thread_count);
6458   mysql_cond_broadcast(&COND_thread_count);
6459 #ifdef EXTRA_DEBUG2
6460   sql_print_error("After lock_thread_count");
6461 #endif
6462 #endif /* __WIN__ */
6463 
6464 #ifdef HAVE_PSI_THREAD_INTERFACE
6465   /*
6466     Disable the main thread instrumentation,
6467     to avoid recording events during the shutdown.
6468   */
6469   PSI_THREAD_CALL(delete_current_thread)();
6470 #endif
6471 
6472   /* Wait until cleanup is done */
6473   mysql_mutex_lock(&LOCK_thread_count);
6474   while (!ready_to_exit)
6475     mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
6476   mysql_mutex_unlock(&LOCK_thread_count);
6477 
6478 #if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
6479   if (Service.IsNT() && start_mode)
6480     Service.Stop();
6481   else
6482   {
6483     Service.SetShutdownEvent(0);
6484     if (hEventShutdown)
6485       CloseHandle(hEventShutdown);
6486   }
6487 #endif
6488   clean_up(1);
6489   mysqld_exit(0);
6490 }
6491 
6492 #endif /* !EMBEDDED_LIBRARY */
6493 
6494 
6495 /****************************************************************************
6496   Main and thread entry function for Win32
6497   (all this is needed only to run mysqld as a service on WinNT)
6498 ****************************************************************************/
6499 
6500 #if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
mysql_service(void * p)6501 int mysql_service(void *p)
6502 {
6503   if (my_thread_init())
6504     return 1;
6505 
6506   if (use_opt_args)
6507     win_main(opt_argc, opt_argv);
6508   else
6509     win_main(Service.my_argc, Service.my_argv);
6510 
6511   my_thread_end();
6512   return 0;
6513 }
6514 
6515 
6516 /* Quote string if it contains space, else copy */
6517 
add_quoted_string(char * to,const char * from,char * to_end)6518 static char *add_quoted_string(char *to, const char *from, char *to_end)
6519 {
6520   uint length= (uint) (to_end-to);
6521 
6522   if (!strchr(from, ' '))
6523     return strmake(to, from, length-1);
6524   return strxnmov(to, length-1, "\"", from, "\"", NullS);
6525 }
6526 
6527 
6528 /**
6529   Handle basic handling of services, like installation and removal.
6530 
6531   @param argv             Pointer to argument list
6532   @param servicename    Internal name of service
6533   @param displayname    Display name of service (in taskbar ?)
6534   @param file_path    Path to this program
6535   @param startup_option Startup option to mysqld
6536 
6537   @retval
6538     0   option handled
6539   @retval
6540     1   Could not handle option
6541 */
6542 
6543 static bool
default_service_handling(char ** argv,const char * servicename,const char * displayname,const char * file_path,const char * extra_opt,const char * account_name)6544 default_service_handling(char **argv,
6545        const char *servicename,
6546        const char *displayname,
6547        const char *file_path,
6548        const char *extra_opt,
6549        const char *account_name)
6550 {
6551   char path_and_service[FN_REFLEN+FN_REFLEN+32], *pos, *end;
6552   const char *opt_delim;
6553   end= path_and_service + sizeof(path_and_service)-3;
6554 
6555   /* We have to quote filename if it contains spaces */
6556   pos= add_quoted_string(path_and_service, file_path, end);
6557   if (extra_opt && *extra_opt)
6558   {
6559     /*
6560      Add option after file_path. There will be zero or one extra option.  It's
6561      assumed to be --defaults-file=file but isn't checked.  The variable (not
6562      the option name) should be quoted if it contains a string.
6563     */
6564     *pos++= ' ';
6565     if (opt_delim= strchr(extra_opt, '='))
6566     {
6567       size_t length= ++opt_delim - extra_opt;
6568       pos= strnmov(pos, extra_opt, length);
6569     }
6570     else
6571       opt_delim= extra_opt;
6572 
6573     pos= add_quoted_string(pos, opt_delim, end);
6574   }
6575   /* We must have servicename last */
6576   *pos++= ' ';
6577   (void) add_quoted_string(pos, servicename, end);
6578 
6579   if (Service.got_service_option(argv, "install"))
6580   {
6581     Service.Install(1, servicename, displayname, path_and_service,
6582                     account_name);
6583     return 0;
6584   }
6585   if (Service.got_service_option(argv, "install-manual"))
6586   {
6587     Service.Install(0, servicename, displayname, path_and_service,
6588                     account_name);
6589     return 0;
6590   }
6591   if (Service.got_service_option(argv, "remove"))
6592   {
6593     Service.Remove(servicename);
6594     return 0;
6595   }
6596   return 1;
6597 }
6598 
6599 
mysqld_main(int argc,char ** argv)6600 int mysqld_main(int argc, char **argv)
6601 {
6602   /*
6603     When several instances are running on the same machine, we
6604     need to have an  unique  named  hEventShudown  through the
6605     application PID e.g.: MySQLShutdown1890; MySQLShutdown2342
6606   */
6607   int10_to_str((int) GetCurrentProcessId(),strmov(shutdown_event_name,
6608                                                   "MySQLShutdown"), 10);
6609 
6610   /* Must be initialized early for comparison of service name */
6611   system_charset_info= &my_charset_utf8_general_ci;
6612 
6613   if (my_init())
6614   {
6615     fprintf(stderr, "my_init() failed.");
6616     return 1;
6617   }
6618 
6619   if (Service.GetOS())  /* true NT family */
6620   {
6621     char file_path[FN_REFLEN];
6622     my_path(file_path, argv[0], "");          /* Find name in path */
6623     fn_format(file_path,argv[0],file_path,"",
6624         MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_RESOLVE_SYMLINKS);
6625 
6626     if (argc == 2)
6627     {
6628       if (!default_service_handling(argv, MYSQL_SERVICENAME, MYSQL_SERVICENAME,
6629            file_path, "", NULL))
6630   return 0;
6631       if (Service.IsService(argv[1]))        /* Start an optional service */
6632       {
6633   /*
6634     Only add the service name to the groups read from the config file
6635     if it's not "MySQL". (The default service name should be 'mysqld'
6636     but we started a bad tradition by calling it MySQL from the start
6637     and we are now stuck with it.
6638   */
6639   if (my_strcasecmp(system_charset_info, argv[1],"mysql"))
6640     load_default_groups[load_default_groups_sz-2]= argv[1];
6641         start_mode= 1;
6642         Service.Init(argv[1], mysql_service);
6643         return 0;
6644       }
6645     }
6646     else if (argc == 3) /* install or remove any optional service */
6647     {
6648       if (!default_service_handling(argv, argv[2], argv[2], file_path, "",
6649                                     NULL))
6650   return 0;
6651       if (Service.IsService(argv[2]))
6652       {
6653   /*
6654     mysqld was started as
6655     mysqld --defaults-file=my_path\my.ini service-name
6656   */
6657   use_opt_args=1;
6658   opt_argc= 2;        // Skip service-name
6659   opt_argv=argv;
6660   start_mode= 1;
6661   if (my_strcasecmp(system_charset_info, argv[2],"mysql"))
6662     load_default_groups[load_default_groups_sz-2]= argv[2];
6663   Service.Init(argv[2], mysql_service);
6664   return 0;
6665       }
6666     }
6667     else if (argc == 4 || argc == 5)
6668     {
6669       /*
6670         This may seem strange, because we handle --local-service while
6671         preserving 4.1's behavior of allowing any one other argument that is
6672         passed to the service on startup. (The assumption is that this is
6673         --defaults-file=file, but that was not enforced in 4.1, so we don't
6674         enforce it here.)
6675       */
6676       const char *extra_opt= NullS;
6677       const char *account_name = NullS;
6678       int index;
6679       for (index = 3; index < argc; index++)
6680       {
6681         if (!strcmp(argv[index], "--local-service"))
6682           account_name= "NT AUTHORITY\\LocalService";
6683         else
6684           extra_opt= argv[index];
6685       }
6686 
6687       if (argc == 4 || account_name)
6688         if (!default_service_handling(argv, argv[2], argv[2], file_path,
6689                                       extra_opt, account_name))
6690           return 0;
6691     }
6692     else if (argc == 1 && Service.IsService(MYSQL_SERVICENAME))
6693     {
6694       /* start the default service */
6695       start_mode= 1;
6696       Service.Init(MYSQL_SERVICENAME, mysql_service);
6697       return 0;
6698     }
6699   }
6700   /* Start as standalone server */
6701   Service.my_argc=argc;
6702   Service.my_argv=argv;
6703   mysql_service(NULL);
6704   return 0;
6705 }
6706 #endif
6707 
6708 
6709 /**
6710   Execute all commands from a file. Used by the mysql_install_db script to
6711   create MySQL privilege tables without having to start a full MySQL server.
6712 */
6713 
bootstrap(MYSQL_FILE * file)6714 static void bootstrap(MYSQL_FILE *file)
6715 {
6716   DBUG_ENTER("bootstrap");
6717 
6718   THD *thd= new THD;
6719 #ifdef WITH_WSREP
6720   thd->variables.wsrep_on= 0;
6721 #endif
6722   thd->bootstrap=1;
6723   my_net_init(&thd->net,(st_vio*) 0);
6724   thd->max_client_packet_length= thd->net.max_packet;
6725   thd->security_ctx->master_access= ~(ulong)0;
6726   thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
6727 
6728   in_bootstrap= TRUE;
6729 
6730   bootstrap_file=file;
6731 #ifndef EMBEDDED_LIBRARY      // TODO:  Enable this
6732   int error;
6733   if ((error= mysql_thread_create(key_thread_bootstrap,
6734                                   &thd->real_id, &connection_attrib,
6735                                   handle_bootstrap,
6736                                   (void*) thd)))
6737   {
6738     sql_print_warning("Can't create thread to handle bootstrap (errno= %d)",
6739                       error);
6740     bootstrap_error=-1;
6741     DBUG_VOID_RETURN;
6742   }
6743   /* Wait for thread to die */
6744   mysql_mutex_lock(&LOCK_thread_count);
6745   while (in_bootstrap)
6746   {
6747     mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
6748     DBUG_PRINT("quit", ("One thread died (count=%u)", get_thread_count()));
6749   }
6750   mysql_mutex_unlock(&LOCK_thread_count);
6751 #else
6752   thd->mysql= 0;
6753   do_handle_bootstrap(thd);
6754 #endif
6755 
6756   DBUG_VOID_RETURN;
6757 }
6758 
6759 
read_init_file(char * file_name)6760 static bool read_init_file(char *file_name)
6761 {
6762   MYSQL_FILE *file;
6763   DBUG_ENTER("read_init_file");
6764   DBUG_PRINT("enter",("name: %s",file_name));
6765 
6766   sql_print_information("Execution of init_file \'%s\' started.", file_name);
6767 
6768   if (!(file= mysql_file_fopen(key_file_init, file_name,
6769                                O_RDONLY, MYF(MY_WME))))
6770     DBUG_RETURN(TRUE);
6771   bootstrap(file);
6772   mysql_file_fclose(file, MYF(MY_WME));
6773 
6774   sql_print_information("Execution of init_file \'%s\' ended.", file_name);
6775 
6776   DBUG_RETURN(FALSE);
6777 }
6778 
6779 
6780 /**
6781   Increment number of created threads
6782 */
inc_thread_created(void)6783 void inc_thread_created(void)
6784 {
6785   mysql_mutex_lock(&LOCK_thread_created);
6786   thread_created++;
6787   mysql_mutex_unlock(&LOCK_thread_created);
6788 }
6789 
6790 #ifndef EMBEDDED_LIBRARY
6791 
6792 /*
6793    Simple scheduler that use the main thread to handle the request
6794 
6795    NOTES
6796      This is only used for debugging, when starting mysqld with
6797      --thread-handling=no-threads or --one-thread
6798 
6799      When we enter this function, LOCK_thread_count is held!
6800 */
6801 
handle_connection_in_main_thread(THD * thd)6802 void handle_connection_in_main_thread(THD *thd)
6803 {
6804   mysql_mutex_assert_owner(&LOCK_thread_count);
6805   max_blocked_pthreads= 0;      // Safety
6806   add_global_thread(thd);
6807   mysql_mutex_unlock(&LOCK_thread_count);
6808   thd->start_utime= my_micro_time();
6809   do_handle_one_connection(thd);
6810 }
6811 
6812 
6813 /*
6814   Scheduler that uses one thread per connection
6815 */
6816 
create_thread_to_handle_connection(THD * thd)6817 void create_thread_to_handle_connection(THD *thd)
6818 {
6819   mysql_mutex_assert_owner(&LOCK_thread_count);
6820   if (blocked_pthread_count >  wake_pthread)
6821   {
6822     /* Wake up blocked pthread */
6823     DBUG_PRINT("info", ("waiting_thd_list->push %p", thd));
6824     waiting_thd_list->push_back(thd);
6825     wake_pthread++;
6826     mysql_cond_signal(&COND_thread_cache);
6827   }
6828   else
6829   {
6830     char error_message_buff[MYSQL_ERRMSG_SIZE];
6831     /* Create new thread to handle connection */
6832     int error;
6833     inc_thread_created();
6834     DBUG_PRINT("info",(("creating thread %lu"), thd->thread_id));
6835     thd->prior_thr_create_utime= thd->start_utime= my_micro_time();
6836     if ((error= mysql_thread_create(key_thread_one_connection,
6837                                     &thd->real_id, &connection_attrib,
6838                                     handle_one_connection,
6839                                     (void*) thd)))
6840     {
6841       /* purecov: begin inspected */
6842       DBUG_PRINT("error",
6843                  ("Can't create thread to handle request (error %d)",
6844                   error));
6845       if (!err_log_throttle.log(thd))
6846         sql_print_error("Can't create thread to handle request (errno= %d)",
6847                         error);
6848       thd->killed= THD::KILL_CONNECTION;      // Safety
6849       mysql_mutex_unlock(&LOCK_thread_count);
6850 
6851       mysql_mutex_lock(&LOCK_connection_count);
6852       --connection_count;
6853       if (connection_count == 0)
6854         mysql_cond_signal(&COND_connection_count);
6855       mysql_mutex_unlock(&LOCK_connection_count);
6856 
6857       statistic_increment(aborted_connects,&LOCK_status);
6858       statistic_increment(connection_errors_internal, &LOCK_status);
6859       /* Can't use my_error() since store_globals has not been called. */
6860       my_snprintf(error_message_buff, sizeof(error_message_buff),
6861                   ER_THD(thd, ER_CANT_CREATE_THREAD), error);
6862       net_send_error(thd, ER_CANT_CREATE_THREAD, error_message_buff, NULL);
6863 #ifdef WITH_WSREP
6864       close_connection(thd,0,0);
6865 #else
6866       close_connection(thd);
6867 #endif
6868       delete thd;
6869       return;
6870       /* purecov: end */
6871     }
6872     add_global_thread(thd);
6873   }
6874   mysql_mutex_unlock(&LOCK_thread_count);
6875   DBUG_PRINT("info",("Thread created"));
6876 }
6877 
6878 
6879 /**
6880   Create new thread to handle incoming connection.
6881 
6882     This function will create new thread to handle the incoming
6883     connection.  If there are idle cached threads one will be used.
6884 
6885     In single-threaded mode (\#define ONE_THREAD) connection will be
6886     handled inside this function.
6887 
6888   @param[in,out] thd    Thread handle of future thread.
6889 */
6890 
create_new_thread(THD * thd)6891 static void create_new_thread(THD *thd)
6892 {
6893   DBUG_ENTER("create_new_thread");
6894 
6895   /*
6896     Don't allow too many connections. We roughly check here that we allow
6897     only (max_connections + 1) connections.
6898   */
6899 
6900   mysql_mutex_lock(&LOCK_connection_count);
6901 
6902   if (connection_count >= max_connections + 1 || abort_loop)
6903   {
6904     mysql_mutex_unlock(&LOCK_connection_count);
6905 
6906     DBUG_PRINT("error",("Too many connections"));
6907     /*
6908       The server just accepted the socket connection from the network,
6909       and we already have too many connections.
6910       Note that the server knows nothing of the client yet,
6911       and in particular thd->client_capabilities has not been negotiated.
6912       ER_CON_COUNT_ERROR is normally associated with SQLSTATE '08004',
6913       but sending a SQLSTATE in the network assumes CLIENT_PROTOCOL_41.
6914       See net_send_error_packet().
6915       The error packet returned here will only contain the error code,
6916       with no sqlstate.
6917       A client expecting a SQLSTATE will not find any, and assume 'HY000'.
6918     */
6919 #ifdef WITH_WSREP
6920     close_connection(thd, ER_CON_COUNT_ERROR, 1);
6921 #else
6922     close_connection(thd, ER_CON_COUNT_ERROR);
6923 #endif
6924     delete thd;
6925     statistic_increment(connection_errors_max_connection, &LOCK_status);
6926     DBUG_VOID_RETURN;
6927   }
6928 
6929   ++connection_count;
6930 
6931   if (connection_count > max_used_connections)
6932     max_used_connections= connection_count;
6933 
6934   mysql_mutex_unlock(&LOCK_connection_count);
6935 
6936   /* Start a new thread to handle connection. */
6937 
6938   mysql_mutex_lock(&LOCK_thread_count);
6939 
6940   /*
6941     The initialization of thread_id is done in create_embedded_thd() for
6942     the embedded library.
6943     TODO: refactor this to avoid code duplication there
6944   */
6945   thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
6946 
6947   MYSQL_CALLBACK(thread_scheduler, add_connection, (thd));
6948 
6949   DBUG_VOID_RETURN;
6950 }
6951 #endif /* EMBEDDED_LIBRARY */
6952 
6953 
6954 #ifdef SIGNALS_DONT_BREAK_READ
kill_broken_server()6955 inline void kill_broken_server()
6956 {
6957   /* hack to get around signals ignored in syscalls for problem OS's */
6958   if (mysql_get_fd(unix_sock) == INVALID_SOCKET ||
6959       (!opt_disable_networking && mysql_socket_getfd(ip_sock) == INVALID_SOCKET))
6960   {
6961     select_thread_in_use = 0;
6962     /* The following call will never return */
6963     kill_server((void*) MYSQL_KILL_SIGNAL);
6964   }
6965 }
6966 #define MAYBE_BROKEN_SYSCALL kill_broken_server();
6967 #else
6968 #define MAYBE_BROKEN_SYSCALL
6969 #endif
6970 
6971   /* Handle new connections and spawn new process to handle them */
6972 
6973 #ifndef EMBEDDED_LIBRARY
6974 
handle_connections_sockets()6975 void handle_connections_sockets()
6976 {
6977   MYSQL_SOCKET sock= mysql_socket_invalid();
6978   MYSQL_SOCKET new_sock= mysql_socket_invalid();
6979   uint error_count=0;
6980   THD *thd;
6981   struct sockaddr_storage cAddr;
6982   int ip_flags=0,socket_flags=0,flags=0,retval;
6983   st_vio *vio_tmp;
6984 #ifdef HAVE_POLL
6985   int socket_count= 0;
6986   struct pollfd fds[2]; // for ip_sock and unix_sock
6987   MYSQL_SOCKET pfs_fds[2]; // for performance schema
6988 #else
6989   fd_set readFDs,clientFDs;
6990   uint max_used_connection= max<uint>(mysql_socket_getfd(ip_sock), mysql_socket_getfd(unix_sock)) + 1;
6991 #endif
6992 
6993   DBUG_ENTER("handle_connections_sockets");
6994 
6995   (void) ip_flags;
6996   (void) socket_flags;
6997 
6998 #ifndef HAVE_POLL
6999   FD_ZERO(&clientFDs);
7000 #endif
7001 
7002   if (mysql_socket_getfd(ip_sock) != INVALID_SOCKET)
7003   {
7004     mysql_socket_set_thread_owner(ip_sock);
7005 #ifdef HAVE_POLL
7006     fds[socket_count].fd= mysql_socket_getfd(ip_sock);
7007     fds[socket_count].events= POLLIN;
7008     pfs_fds[socket_count]= ip_sock;
7009     socket_count++;
7010 #else
7011     FD_SET(mysql_socket_getfd(ip_sock), &clientFDs);
7012 #endif
7013 #ifdef HAVE_FCNTL
7014     ip_flags = fcntl(mysql_socket_getfd(ip_sock), F_GETFL, 0);
7015 #endif
7016   }
7017 #ifdef HAVE_SYS_UN_H
7018   mysql_socket_set_thread_owner(unix_sock);
7019 #ifdef HAVE_POLL
7020   fds[socket_count].fd= mysql_socket_getfd(unix_sock);
7021   fds[socket_count].events= POLLIN;
7022   pfs_fds[socket_count]= unix_sock;
7023   socket_count++;
7024 #else
7025   FD_SET(mysql_socket_getfd(unix_sock), &clientFDs);
7026 #endif
7027 #ifdef HAVE_FCNTL
7028   socket_flags=fcntl(mysql_socket_getfd(unix_sock), F_GETFL, 0);
7029 #endif
7030 #endif
7031 
7032   DBUG_PRINT("general",("Waiting for connections."));
7033   MAYBE_BROKEN_SYSCALL;
7034   while (!abort_loop)
7035   {
7036 #ifdef HAVE_POLL
7037     retval= poll(fds, socket_count, -1);
7038 #else
7039     readFDs=clientFDs;
7040 
7041     retval= select((int) max_used_connection,&readFDs,0,0,0);
7042 #endif
7043 
7044     if (retval < 0)
7045     {
7046       if (socket_errno != SOCKET_EINTR)
7047       {
7048         /*
7049           select(2)/poll(2) failed on the listening port.
7050           There is not much details to report about the client,
7051           increment the server global status variable.
7052         */
7053         statistic_increment(connection_errors_select, &LOCK_status);
7054         if (!select_errors++ && !abort_loop)  /* purecov: inspected */
7055           sql_print_error("mysqld: Got error %d from select",socket_errno); /* purecov: inspected */
7056       }
7057       MAYBE_BROKEN_SYSCALL
7058       continue;
7059     }
7060 
7061     if (abort_loop)
7062     {
7063       MAYBE_BROKEN_SYSCALL;
7064       break;
7065     }
7066 
7067     /* Is this a new connection request ? */
7068 #ifdef HAVE_POLL
7069     for (int i= 0; i < socket_count; ++i)
7070     {
7071       if (fds[i].revents & POLLIN)
7072       {
7073         sock= pfs_fds[i];
7074 #ifdef HAVE_FCNTL
7075         flags= fcntl(mysql_socket_getfd(sock), F_GETFL, 0);
7076 #else
7077         flags= 0;
7078 #endif // HAVE_FCNTL
7079         break;
7080       }
7081     }
7082 #else  // HAVE_POLL
7083 #ifdef HAVE_SYS_UN_H
7084     if (FD_ISSET(mysql_socket_getfd(unix_sock), &readFDs))
7085     {
7086       sock = unix_sock;
7087       flags= socket_flags;
7088     }
7089     else
7090 #endif // HAVE_SYS_UN_H
7091     {
7092       sock = ip_sock;
7093       flags= ip_flags;
7094     }
7095 #endif // HAVE_POLL
7096 
7097 #if !defined(NO_FCNTL_NONBLOCK)
7098     if (!(test_flags & TEST_BLOCKING))
7099     {
7100 #if defined(O_NONBLOCK)
7101       fcntl(mysql_socket_getfd(sock), F_SETFL, flags | O_NONBLOCK);
7102 #elif defined(O_NDELAY)
7103       fcntl(mysql_socket_getfd(sock), F_SETFL, flags | O_NDELAY);
7104 #endif
7105     }
7106 #endif /* NO_FCNTL_NONBLOCK */
7107     for (uint retry=0; retry < MAX_ACCEPT_RETRY; retry++)
7108     {
7109       size_socket length= sizeof(struct sockaddr_storage);
7110       new_sock= mysql_socket_accept(key_socket_client_connection, sock,
7111                                     (struct sockaddr *)(&cAddr), &length);
7112       if (mysql_socket_getfd(new_sock) != INVALID_SOCKET ||
7113           (socket_errno != SOCKET_EINTR && socket_errno != SOCKET_EAGAIN))
7114         break;
7115       MAYBE_BROKEN_SYSCALL;
7116 #if !defined(NO_FCNTL_NONBLOCK)
7117       if (!(test_flags & TEST_BLOCKING))
7118       {
7119         if (retry == MAX_ACCEPT_RETRY - 1)
7120           fcntl(mysql_socket_getfd(sock), F_SETFL, flags);    // Try without O_NONBLOCK
7121       }
7122 #endif
7123     }
7124 #if !defined(NO_FCNTL_NONBLOCK)
7125     if (!(test_flags & TEST_BLOCKING))
7126       fcntl(mysql_socket_getfd(sock), F_SETFL, flags);
7127 #endif
7128     if (mysql_socket_getfd(new_sock) == INVALID_SOCKET)
7129     {
7130       /*
7131         accept(2) failed on the listening port, after many retries.
7132         There is not much details to report about the client,
7133         increment the server global status variable.
7134       */
7135       statistic_increment(connection_errors_accept, &LOCK_status);
7136       if ((error_count++ & 255) == 0)   // This can happen often
7137         sql_perror("Error in accept");
7138       MAYBE_BROKEN_SYSCALL;
7139       if (socket_errno == SOCKET_ENFILE || socket_errno == SOCKET_EMFILE)
7140         sleep(1);       // Give other threads some time
7141       continue;
7142     }
7143 #if defined(WITH_WSREP) && defined(HAVE_FCNTL) && defined(FD_CLOEXEC)
7144     (void) fcntl(mysql_socket_getfd(new_sock), F_SETFD, FD_CLOEXEC);
7145 #endif /* WITH_WSREP */
7146 
7147 #ifdef HAVE_LIBWRAP
7148     {
7149       if (mysql_socket_getfd(sock) == mysql_socket_getfd(ip_sock))
7150       {
7151         struct request_info req;
7152         signal(SIGCHLD, SIG_DFL);
7153         request_init(&req, RQ_DAEMON, libwrapName, RQ_FILE, mysql_socket_getfd(new_sock), NULL);
7154         my_fromhost(&req);
7155 
7156         if (!my_hosts_access(&req))
7157         {
7158           /*
7159             This may be stupid but refuse() includes an exit(0)
7160             which we surely don't want...
7161             clean_exit() - same stupid thing ...
7162           */
7163           syslog(deny_severity, "refused connect from %s",
7164           my_eval_client(&req));
7165 
7166           /*
7167             C++ sucks (the gibberish in front just translates the supplied
7168             sink function pointer in the req structure from a void (*sink)();
7169             to a void(*sink)(int) if you omit the cast, the C++ compiler
7170             will cry...
7171           */
7172           if (req.sink)
7173             ((void (*)(int))req.sink)(req.fd);
7174 
7175           mysql_socket_shutdown(new_sock, SHUT_RDWR);
7176           mysql_socket_close(new_sock);
7177           /*
7178             The connection was refused by TCP wrappers.
7179             There are no details (by client IP) available to update the host_cache.
7180           */
7181           statistic_increment(connection_errors_tcpwrap, &LOCK_status);
7182           continue;
7183         }
7184       }
7185     }
7186 #endif /* HAVE_LIBWRAP */
7187 
7188     /*
7189     ** Don't allow too many connections
7190     */
7191 
7192     if (!(thd= new THD))
7193     {
7194       (void) mysql_socket_shutdown(new_sock, SHUT_RDWR);
7195       (void) mysql_socket_close(new_sock);
7196       statistic_increment(connection_errors_internal, &LOCK_status);
7197       continue;
7198     }
7199 
7200     bool is_unix_sock= (mysql_socket_getfd(sock) == mysql_socket_getfd(unix_sock));
7201     enum_vio_type vio_type= (is_unix_sock ? VIO_TYPE_SOCKET : VIO_TYPE_TCPIP);
7202     uint vio_flags= (is_unix_sock ? VIO_LOCALHOST : 0);
7203 
7204     vio_tmp= mysql_socket_vio_new(new_sock, vio_type, vio_flags);
7205 
7206     if (!vio_tmp || my_net_init(&thd->net, vio_tmp))
7207     {
7208       /*
7209         Only delete the temporary vio if we didn't already attach it to the
7210         NET object. The destructor in THD will delete any initialized net
7211         structure.
7212       */
7213       if (vio_tmp && thd->net.vio != vio_tmp)
7214         vio_delete(vio_tmp);
7215       else
7216       {
7217         (void) mysql_socket_shutdown(new_sock, SHUT_RDWR);
7218         (void) mysql_socket_close(new_sock);
7219       }
7220       delete thd;
7221       statistic_increment(connection_errors_internal, &LOCK_status);
7222       continue;
7223     }
7224     init_net_server_extension(thd);
7225     if (mysql_socket_getfd(sock) == mysql_socket_getfd(unix_sock))
7226       thd->security_ctx->set_host((char*) my_localhost);
7227 
7228     create_new_thread(thd);
7229   }
7230   DBUG_VOID_RETURN;
7231 }
7232 
7233 
7234 #ifdef _WIN32
handle_connections_sockets_thread(void * arg)7235 pthread_handler_t handle_connections_sockets_thread(void *arg)
7236 {
7237   my_thread_init();
7238   handle_connections_sockets();
7239   decrement_handler_count();
7240   return 0;
7241 }
7242 
handle_connections_namedpipes(void * arg)7243 pthread_handler_t handle_connections_namedpipes(void *arg)
7244 {
7245   HANDLE hConnectedPipe;
7246   OVERLAPPED connectOverlapped= {0};
7247   THD *thd;
7248   TCHAR last_error_msg[256];
7249   my_thread_init();
7250   DBUG_ENTER("handle_connections_namedpipes");
7251   connectOverlapped.hEvent= CreateEvent(NULL, TRUE, FALSE, NULL);
7252   if (!connectOverlapped.hEvent)
7253   {
7254     sql_print_error("Can't create event, last error=%u", GetLastError());
7255     unireg_abort(1);
7256   }
7257   DBUG_PRINT("general",("Waiting for named pipe connections."));
7258   while (!abort_loop)
7259   {
7260     /* wait for named pipe connection */
7261     BOOL fConnected= ConnectNamedPipe(hPipe, &connectOverlapped);
7262     if (!fConnected && (GetLastError() == ERROR_IO_PENDING))
7263     {
7264         /*
7265           ERROR_IO_PENDING says async IO has started but not yet finished.
7266           GetOverlappedResult will wait for completion.
7267         */
7268         DWORD bytes;
7269         fConnected= GetOverlappedResult(hPipe, &connectOverlapped,&bytes, TRUE);
7270     }
7271     if (abort_loop)
7272       break;
7273     if (!fConnected)
7274       fConnected = GetLastError() == ERROR_PIPE_CONNECTED;
7275     if (!fConnected)
7276     {
7277       CloseHandle(hPipe);
7278       mysql_rwlock_rdlock(&LOCK_named_pipe_full_access_group);
7279       hPipe= CreateNamedPipe(pipe_name,
7280                              PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED |
7281                                WRITE_DAC,
7282                              PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
7283                              PIPE_UNLIMITED_INSTANCES,
7284                              (int) global_system_variables.net_buffer_length,
7285                              (int) global_system_variables.net_buffer_length,
7286                              NMPWAIT_USE_DEFAULT_WAIT,
7287                              psaPipeSecurity);
7288       mysql_rwlock_unlock(&LOCK_named_pipe_full_access_group);
7289       if (hPipe == INVALID_HANDLE_VALUE)
7290       {
7291         DWORD last_error_num= GetLastError();
7292         FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
7293                         FORMAT_MESSAGE_MAX_WIDTH_MASK,
7294                       NULL, last_error_num,
7295                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), last_error_msg,
7296                       sizeof(last_error_msg) / sizeof(TCHAR), NULL);
7297         sql_print_error("Can't create new named pipe: %s", last_error_msg);
7298         break;					// Abort
7299       }
7300     }
7301     hConnectedPipe = hPipe;
7302     /* create new pipe for new connection */
7303     mysql_rwlock_rdlock(&LOCK_named_pipe_full_access_group);
7304     hPipe= CreateNamedPipe(pipe_name,
7305                             PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED |
7306                               WRITE_DAC,
7307 			                      PIPE_TYPE_BYTE |PIPE_READMODE_BYTE | PIPE_WAIT,
7308 			                      PIPE_UNLIMITED_INSTANCES,
7309 			                      (int) global_system_variables.net_buffer_length,
7310 			                      (int) global_system_variables.net_buffer_length,
7311 			                      NMPWAIT_USE_DEFAULT_WAIT,
7312 			                      psaPipeSecurity);
7313     mysql_rwlock_unlock(&LOCK_named_pipe_full_access_group);
7314     if (hPipe == INVALID_HANDLE_VALUE)
7315     {
7316       DWORD last_error_num = GetLastError();
7317       FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
7318                       FORMAT_MESSAGE_MAX_WIDTH_MASK,
7319                     NULL, last_error_num,
7320                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), last_error_msg,
7321                     sizeof(last_error_msg) / sizeof(TCHAR), NULL);
7322       sql_print_error("Can't create new named pipe: %s", last_error_msg);
7323       hPipe=hConnectedPipe;
7324       continue;					// We have to try again
7325     }
7326 
7327     if (!(thd = new THD))
7328     {
7329       DisconnectNamedPipe(hConnectedPipe);
7330       CloseHandle(hConnectedPipe);
7331       continue;
7332     }
7333     if (!(thd->net.vio= vio_new_win32pipe(hConnectedPipe)) ||
7334   my_net_init(&thd->net, thd->net.vio))
7335     {
7336 #ifdef WITH_WSREP
7337       close_connection(thd, ER_OUT_OF_RESOURCES, 1);
7338 #else
7339       close_connection(thd, ER_OUT_OF_RESOURCES);
7340 #endif
7341       delete thd;
7342       continue;
7343     }
7344     /* Host is unknown */
7345     thd->security_ctx->set_host(my_strdup(my_localhost, MYF(0)));
7346     create_new_thread(thd);
7347   }
7348   CloseHandle(connectOverlapped.hEvent);
7349   DBUG_LEAVE;
7350   decrement_handler_count();
7351   return 0;
7352 }
7353 #endif /* _WIN32 */
7354 
7355 
7356 #ifdef HAVE_SMEM
7357 
7358 /**
7359   Thread of shared memory's service.
7360 
7361   @param arg                              Arguments of thread
7362 */
handle_connections_shared_memory(void * arg)7363 pthread_handler_t handle_connections_shared_memory(void *arg)
7364 {
7365   /* file-mapping object, use for create shared memory */
7366   HANDLE handle_connect_file_map= 0;
7367   char  *handle_connect_map= 0;                 // pointer on shared memory
7368   HANDLE event_connect_answer= 0;
7369   ulong smem_buffer_length= shared_memory_buffer_length + 4;
7370   ulong connect_number= 1;
7371   char *tmp= NULL;
7372   char *suffix_pos;
7373   char connect_number_char[22], *p;
7374   const char *errmsg= 0;
7375   SECURITY_ATTRIBUTES *sa_event= 0, *sa_mapping= 0;
7376   my_thread_init();
7377   DBUG_ENTER("handle_connections_shared_memorys");
7378   DBUG_PRINT("general",("Waiting for allocated shared memory."));
7379 
7380   /*
7381      get enough space base-name + '_' + longest suffix we might ever send
7382    */
7383   if (!(tmp= (char *)my_malloc(strlen(shared_memory_base_name) + 32L, MYF(MY_FAE))))
7384     goto error;
7385 
7386   if (my_security_attr_create(&sa_event, &errmsg,
7387                               GENERIC_ALL, SYNCHRONIZE | EVENT_MODIFY_STATE))
7388     goto error;
7389 
7390   if (my_security_attr_create(&sa_mapping, &errmsg,
7391                              GENERIC_ALL, FILE_MAP_READ | FILE_MAP_WRITE))
7392     goto error;
7393 
7394   /*
7395     The name of event and file-mapping events create agree next rule:
7396       shared_memory_base_name+unique_part
7397     Where:
7398       shared_memory_base_name is unique value for each server
7399       unique_part is unique value for each object (events and file-mapping)
7400   */
7401   suffix_pos= strxmov(tmp,shared_memory_base_name,"_",NullS);
7402   strmov(suffix_pos, "CONNECT_REQUEST");
7403   if ((smem_event_connect_request= CreateEvent(sa_event,
7404                                                FALSE, FALSE, tmp)) == 0)
7405   {
7406     errmsg= "Could not create request event";
7407     goto error;
7408   }
7409   strmov(suffix_pos, "CONNECT_ANSWER");
7410   if ((event_connect_answer= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
7411   {
7412     errmsg="Could not create answer event";
7413     goto error;
7414   }
7415   strmov(suffix_pos, "CONNECT_DATA");
7416   if ((handle_connect_file_map=
7417        CreateFileMapping(INVALID_HANDLE_VALUE, sa_mapping,
7418                          PAGE_READWRITE, 0, sizeof(connect_number), tmp)) == 0)
7419   {
7420     errmsg= "Could not create file mapping";
7421     goto error;
7422   }
7423   if ((handle_connect_map= (char *)MapViewOfFile(handle_connect_file_map,
7424               FILE_MAP_WRITE,0,0,
7425               sizeof(DWORD))) == 0)
7426   {
7427     errmsg= "Could not create shared memory service";
7428     goto error;
7429   }
7430 
7431   while (!abort_loop)
7432   {
7433     /* Wait a request from client */
7434     WaitForSingleObject(smem_event_connect_request,INFINITE);
7435 
7436     /*
7437        it can be after shutdown command
7438     */
7439     if (abort_loop)
7440       goto error;
7441 
7442     HANDLE handle_client_file_map= 0;
7443     char  *handle_client_map= 0;
7444     HANDLE event_client_wrote= 0;
7445     HANDLE event_client_read= 0;    // for transfer data server <-> client
7446     HANDLE event_server_wrote= 0;
7447     HANDLE event_server_read= 0;
7448     HANDLE event_conn_closed= 0;
7449     THD *thd= 0;
7450 
7451     p= int10_to_str(connect_number, connect_number_char, 10);
7452     /*
7453       The name of event and file-mapping events create agree next rule:
7454         shared_memory_base_name+unique_part+number_of_connection
7455         Where:
7456     shared_memory_base_name is uniquel value for each server
7457     unique_part is unique value for each object (events and file-mapping)
7458     number_of_connection is connection-number between server and client
7459     */
7460     suffix_pos= strxmov(tmp,shared_memory_base_name,"_",connect_number_char,
7461        "_",NullS);
7462     strmov(suffix_pos, "DATA");
7463     if ((handle_client_file_map=
7464          CreateFileMapping(INVALID_HANDLE_VALUE, sa_mapping,
7465                            PAGE_READWRITE, 0, smem_buffer_length, tmp)) == 0)
7466     {
7467       errmsg= "Could not create file mapping";
7468       goto errorconn;
7469     }
7470     if ((handle_client_map= (char*)MapViewOfFile(handle_client_file_map,
7471               FILE_MAP_WRITE,0,0,
7472               smem_buffer_length)) == 0)
7473     {
7474       errmsg= "Could not create memory map";
7475       goto errorconn;
7476     }
7477     strmov(suffix_pos, "CLIENT_WROTE");
7478     if ((event_client_wrote= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
7479     {
7480       errmsg= "Could not create client write event";
7481       goto errorconn;
7482     }
7483     strmov(suffix_pos, "CLIENT_READ");
7484     if ((event_client_read= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
7485     {
7486       errmsg= "Could not create client read event";
7487       goto errorconn;
7488     }
7489     strmov(suffix_pos, "SERVER_READ");
7490     if ((event_server_read= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
7491     {
7492       errmsg= "Could not create server read event";
7493       goto errorconn;
7494     }
7495     strmov(suffix_pos, "SERVER_WROTE");
7496     if ((event_server_wrote= CreateEvent(sa_event,
7497                                          FALSE, FALSE, tmp)) == 0)
7498     {
7499       errmsg= "Could not create server write event";
7500       goto errorconn;
7501     }
7502     strmov(suffix_pos, "CONNECTION_CLOSED");
7503     if ((event_conn_closed= CreateEvent(sa_event,
7504                                         TRUE, FALSE, tmp)) == 0)
7505     {
7506       errmsg= "Could not create closed connection event";
7507       goto errorconn;
7508     }
7509     if (abort_loop)
7510       goto errorconn;
7511     if (!(thd= new THD))
7512       goto errorconn;
7513     /* Send number of connection to client */
7514     int4store(handle_connect_map, connect_number);
7515     if (!SetEvent(event_connect_answer))
7516     {
7517       errmsg= "Could not send answer event";
7518       goto errorconn;
7519     }
7520     /* Set event that client should receive data */
7521     if (!SetEvent(event_client_read))
7522     {
7523       errmsg= "Could not set client to read mode";
7524       goto errorconn;
7525     }
7526     if (!(thd->net.vio= vio_new_win32shared_memory(handle_client_file_map,
7527                                                    handle_client_map,
7528                                                    event_client_wrote,
7529                                                    event_client_read,
7530                                                    event_server_wrote,
7531                                                    event_server_read,
7532                                                    event_conn_closed)) ||
7533                         my_net_init(&thd->net, thd->net.vio))
7534     {
7535 #ifdef WITH_WSREP
7536       close_connection(thd, ER_OUT_OF_RESOURCES, 1);
7537 #else
7538       close_connection(thd, ER_OUT_OF_RESOURCES);
7539 #endif
7540       errmsg= 0;
7541       goto errorconn;
7542     }
7543     thd->security_ctx->set_host(my_strdup(my_localhost, MYF(0))); /* Host is unknown */
7544     create_new_thread(thd);
7545     connect_number++;
7546     continue;
7547 
7548 errorconn:
7549     /* Could not form connection;  Free used handlers/memort and retry */
7550     if (errmsg)
7551     {
7552       char buff[180];
7553       strxmov(buff, "Can't create shared memory connection: ", errmsg, ".",
7554         NullS);
7555       sql_perror(buff);
7556     }
7557     if (handle_client_file_map)
7558       CloseHandle(handle_client_file_map);
7559     if (handle_client_map)
7560       UnmapViewOfFile(handle_client_map);
7561     if (event_server_wrote)
7562       CloseHandle(event_server_wrote);
7563     if (event_server_read)
7564       CloseHandle(event_server_read);
7565     if (event_client_wrote)
7566       CloseHandle(event_client_wrote);
7567     if (event_client_read)
7568       CloseHandle(event_client_read);
7569     if (event_conn_closed)
7570       CloseHandle(event_conn_closed);
7571     delete thd;
7572   }
7573 
7574   /* End shared memory handling */
7575 error:
7576   if (tmp)
7577     my_free(tmp);
7578 
7579   if (errmsg)
7580   {
7581     char buff[180];
7582     strxmov(buff, "Can't create shared memory service: ", errmsg, ".", NullS);
7583     sql_perror(buff);
7584   }
7585   my_security_attr_free(sa_event);
7586   my_security_attr_free(sa_mapping);
7587   if (handle_connect_map) UnmapViewOfFile(handle_connect_map);
7588   if (handle_connect_file_map)  CloseHandle(handle_connect_file_map);
7589   if (event_connect_answer) CloseHandle(event_connect_answer);
7590   if (smem_event_connect_request) CloseHandle(smem_event_connect_request);
7591   DBUG_LEAVE;
7592   decrement_handler_count();
7593   return 0;
7594 }
7595 #endif /* HAVE_SMEM */
7596 #endif /* EMBEDDED_LIBRARY */
7597 
7598 
7599 /****************************************************************************
7600   Handle start options
7601 ******************************************************************************/
7602 
7603 /**
7604   Process command line options flagged as 'early'.
7605   Some components needs to be initialized as early as possible,
7606   because the rest of the server initialization depends on them.
7607   Options that needs to be parsed early includes:
7608   - the performance schema, when compiled in,
7609   - options related to the help,
7610   - options related to the bootstrap
7611   The performance schema needs to be initialized as early as possible,
7612   before to-be-instrumented objects of the server are initialized.
7613 */
handle_early_options()7614 int handle_early_options()
7615 {
7616   int ho_error;
7617   vector<my_option> all_early_options;
7618   all_early_options.reserve(100);
7619 
7620   my_getopt_register_get_addr(NULL);
7621   /* Skip unknown options so that they may be processed later */
7622   my_getopt_skip_unknown= TRUE;
7623 
7624   /* Add the system variables parsed early */
7625   sys_var_add_options(&all_early_options, sys_var::PARSE_EARLY);
7626 
7627   /* Add the command line options parsed early */
7628   for (my_option *opt= my_long_early_options;
7629        opt->name != NULL;
7630        opt++)
7631     all_early_options.push_back(*opt);
7632 
7633   add_terminator(&all_early_options);
7634 
7635   /*
7636     Logs generated while parsing the command line
7637     options are buffered and printed later.
7638   */
7639   buffered_logs.init();
7640   my_getopt_error_reporter= buffered_option_error_reporter;
7641   my_charset_error_reporter= buffered_option_error_reporter;
7642 
7643   ho_error= handle_options(&remaining_argc, &remaining_argv,
7644                            &all_early_options[0], mysqld_get_one_option);
7645   if (ho_error == 0)
7646   {
7647     /* Add back the program name handle_options removes */
7648     remaining_argc++;
7649     remaining_argv--;
7650   }
7651 
7652   // Swap with an empty vector, i.e. delete elements and free allocated space.
7653   vector<my_option>().swap(all_early_options);
7654 
7655   return ho_error;
7656 }
7657 
7658 /**
7659   Adjust @c open_files_limit.
7660   Computation is  based on:
7661   - @c max_connections,
7662   - @c table_cache_size,
7663   - the platform max open file limit.
7664 */
adjust_open_files_limit(ulong * requested_open_files)7665 void adjust_open_files_limit(ulong *requested_open_files)
7666 {
7667   ulong limit_1;
7668   ulong limit_2;
7669   ulong limit_3;
7670   ulong request_open_files;
7671   ulong effective_open_files;
7672 
7673   /* MyISAM requires two file handles per table. */
7674   limit_1= 10 + max_connections + table_cache_size * 2;
7675 
7676   /*
7677     We are trying to allocate no less than max_connections*5 file
7678     handles (i.e. we are trying to set the limit so that they will
7679     be available).
7680   */
7681   limit_2= max_connections * 5;
7682 
7683   /* Try to allocate no less than 5000 by default. */
7684   limit_3= open_files_limit ? open_files_limit : 5000;
7685 
7686   request_open_files= max<ulong>(max<ulong>(limit_1, limit_2), limit_3);
7687 
7688   /* Notice: my_set_max_open_files() may return more than requested. */
7689   effective_open_files= my_set_max_open_files(request_open_files);
7690 
7691   if (effective_open_files < request_open_files)
7692   {
7693     char msg[1024];
7694 
7695     if (open_files_limit == 0)
7696     {
7697       snprintf(msg, sizeof(msg),
7698                "Changed limits: max_open_files: %lu (requested %lu)",
7699                effective_open_files, request_open_files);
7700       buffered_logs.buffer(WARNING_LEVEL, msg);
7701     }
7702     else
7703     {
7704       snprintf(msg, sizeof(msg),
7705                "Could not increase number of max_open_files to "
7706                "more than %lu (request: %lu)",
7707                effective_open_files, request_open_files);
7708       buffered_logs.buffer(WARNING_LEVEL, msg);
7709     }
7710   }
7711 
7712   open_files_limit= effective_open_files;
7713   if (requested_open_files)
7714     *requested_open_files= min<ulong>(effective_open_files, request_open_files);
7715 }
7716 
adjust_max_connections(ulong requested_open_files)7717 void adjust_max_connections(ulong requested_open_files)
7718 {
7719   ulong limit;
7720 
7721   limit= requested_open_files - 10 - TABLE_OPEN_CACHE_MIN * 2;
7722 
7723   if (limit < max_connections)
7724   {
7725     char msg[1024];
7726 
7727     snprintf(msg, sizeof(msg),
7728              "Changed limits: max_connections: %lu (requested %lu)",
7729              limit, max_connections);
7730     buffered_logs.buffer(WARNING_LEVEL, msg);
7731 
7732     max_connections= limit;
7733   }
7734 }
7735 
adjust_table_cache_size(ulong requested_open_files)7736 void adjust_table_cache_size(ulong requested_open_files)
7737 {
7738   ulong limit;
7739 
7740   limit= max<ulong>((requested_open_files - 10 - max_connections) / 2,
7741                     TABLE_OPEN_CACHE_MIN);
7742 
7743   if (limit < table_cache_size)
7744   {
7745     char msg[1024];
7746 
7747     snprintf(msg, sizeof(msg),
7748              "Changed limits: table_open_cache: %lu (requested %lu)",
7749              limit, table_cache_size);
7750     buffered_logs.buffer(WARNING_LEVEL, msg);
7751 
7752     table_cache_size= limit;
7753   }
7754 
7755   table_cache_size_per_instance= table_cache_size / table_cache_instances;
7756 }
7757 
adjust_table_def_size()7758 void adjust_table_def_size()
7759 {
7760   longlong default_value;
7761   sys_var *var;
7762 
7763   default_value= min<longlong> (400 + table_cache_size / 2, 2000);
7764   var= intern_find_sys_var(STRING_WITH_LEN("table_definition_cache"));
7765   DBUG_ASSERT(var != NULL);
7766   var->update_default(default_value);
7767 
7768   if (! table_definition_cache_specified)
7769     table_def_size= default_value;
7770 }
7771 
adjust_related_options(ulong * requested_open_files)7772 void adjust_related_options(ulong *requested_open_files)
7773 {
7774   /* In bootstrap, disable grant tables (we are about to create them) */
7775   if (opt_bootstrap)
7776     opt_noacl= 1;
7777 
7778   /* The order is critical here, because of dependencies. */
7779   adjust_open_files_limit(requested_open_files);
7780   adjust_max_connections(*requested_open_files);
7781   adjust_table_cache_size(*requested_open_files);
7782   adjust_table_def_size();
7783 }
7784 
7785 vector<my_option> all_options;
7786 
7787 struct my_option my_long_early_options[]=
7788 {
7789 #ifndef DISABLE_GRANT_OPTIONS
7790   {"bootstrap", OPT_BOOTSTRAP, "Used by mysql installation scripts.", 0, 0, 0,
7791    GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
7792 #endif
7793 #ifndef DISABLE_GRANT_OPTIONS
7794   {"skip-grant-tables", 0,
7795    "Start without grant tables. This gives all users FULL ACCESS to all tables.",
7796    &opt_noacl, &opt_noacl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
7797    0},
7798 #endif
7799   {"help", '?', "Display this help and exit.",
7800    &opt_help, &opt_help, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
7801    0, 0},
7802   {"verbose", 'v', "Used with --help option for detailed help.",
7803    &opt_verbose, &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
7804   {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
7805    NO_ARG, 0, 0, 0, 0, 0, 0},
7806   {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
7807 };
7808 
7809 /**
7810   System variables are automatically command-line options (few
7811   exceptions are documented in sys_var.h), so don't need
7812   to be listed here.
7813 */
7814 
7815 struct my_option my_long_options[]=
7816 {
7817 #ifdef HAVE_REPLICATION
7818   {"abort-slave-event-count", 0,
7819    "Option used by mysql-test for debugging and testing of replication.",
7820    &abort_slave_event_count,  &abort_slave_event_count,
7821    0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
7822 #endif /* HAVE_REPLICATION */
7823   {"allow-suspicious-udfs", 0,
7824    "Allows use of UDFs consisting of only one symbol xxx() "
7825    "without corresponding xxx_init() or xxx_deinit(). That also means "
7826    "that one can load any function from any library, for example exit() "
7827    "from libc.so",
7828    &opt_allow_suspicious_udfs, &opt_allow_suspicious_udfs,
7829    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
7830   {"ansi", 'a', "Use ANSI SQL syntax instead of MySQL syntax. This mode "
7831    "will also set transaction isolation level 'serializable'.", 0, 0, 0,
7832    GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
7833   /*
7834     Because Sys_var_bit does not support command-line options, we need to
7835     explicitely add one for --autocommit
7836   */
7837   {"autocommit", 0, "Set default value for autocommit (0 or 1)",
7838    &opt_autocommit, &opt_autocommit, 0,
7839    GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, NULL},
7840   {"binlog-do-db", OPT_BINLOG_DO_DB,
7841    "Tells the master it should log updates for the specified database, "
7842    "and exclude all others not explicitly mentioned.",
7843    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
7844   {"binlog-ignore-db", OPT_BINLOG_IGNORE_DB,
7845    "Tells the master that updates to the given database should not be logged to the binary log.",
7846    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
7847   {"binlog-row-event-max-size", 0,
7848    "The maximum size of a row-based binary log event in bytes. Rows will be "
7849    "grouped into events smaller than this size if possible. "
7850    "The value has to be a multiple of 256.",
7851    &opt_binlog_rows_event_max_size, &opt_binlog_rows_event_max_size,
7852    0, GET_ULONG, REQUIRED_ARG,
7853    /* def_value */ 8192, /* min_value */  256, /* max_value */ ULONG_MAX,
7854    /* sub_size */     0, /* block_size */ 256,
7855    /* app_type */ 0
7856   },
7857   {"character-set-client-handshake", 0,
7858    "Don't ignore client side character set value sent during handshake.",
7859    &opt_character_set_client_handshake,
7860    &opt_character_set_client_handshake,
7861     0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
7862   {"character-set-filesystem", 0,
7863    "Set the filesystem character set.",
7864    &character_set_filesystem_name,
7865    &character_set_filesystem_name,
7866    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
7867   {"character-set-server", 'C', "Set the default character set.",
7868    &default_character_set_name, &default_character_set_name,
7869    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
7870   {"chroot", 'r', "Chroot mysqld daemon during startup.",
7871    &mysqld_chroot, &mysqld_chroot, 0, GET_STR, REQUIRED_ARG,
7872    0, 0, 0, 0, 0, 0},
7873   {"collation-server", 0, "Set the default collation.",
7874    &default_collation_name, &default_collation_name,
7875    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
7876   {"console", OPT_CONSOLE, "Write error output on screen; don't remove the console window on windows.",
7877    &opt_console, &opt_console, 0, GET_BOOL, NO_ARG, 0, 0, 0,
7878    0, 0, 0},
7879   {"core-file", OPT_WANT_CORE, "Write core on errors.", 0, 0, 0, GET_NO_ARG,
7880    NO_ARG, 0, 0, 0, 0, 0, 0},
7881   /* default-storage-engine should have "MyISAM" as def_value. Instead
7882      of initializing it here it is done in init_common_variables() due
7883      to a compiler bug in Sun Studio compiler. */
7884   {"default-storage-engine", 0, "The default storage engine for new tables",
7885    &default_storage_engine, 0, 0, GET_STR, REQUIRED_ARG,
7886    0, 0, 0, 0, 0, 0 },
7887   {"default-tmp-storage-engine", 0,
7888     "The default storage engine for new explict temporary tables",
7889    &default_tmp_storage_engine, 0, 0, GET_STR, REQUIRED_ARG,
7890    0, 0, 0, 0, 0, 0 },
7891   {"default-time-zone", 0, "Set the default time zone.",
7892    &default_tz_name, &default_tz_name,
7893    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
7894 #ifdef HAVE_OPENSSL
7895   {"des-key-file", 0,
7896    "Load keys for des_encrypt() and des_encrypt from given file.",
7897    &des_key_file, &des_key_file, 0, GET_STR, REQUIRED_ARG,
7898    0, 0, 0, 0, 0, 0},
7899 #endif /* HAVE_OPENSSL */
7900 #ifdef HAVE_REPLICATION
7901   {"disconnect-slave-event-count", 0,
7902    "Option used by mysql-test for debugging and testing of replication.",
7903    &disconnect_slave_event_count, &disconnect_slave_event_count,
7904    0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
7905 #endif /* HAVE_REPLICATION */
7906   {"exit-info", 'T', "Used for debugging. Use at your own risk.", 0, 0, 0,
7907    GET_LONG, OPT_ARG, 0, 0, 0, 0, 0, 0},
7908 
7909   {"external-locking", 0, "Use system (external) locking (disabled by "
7910    "default).  With this option enabled you can run myisamchk to test "
7911    "(not repair) tables while the MySQL server is running. Disable with "
7912    "--skip-external-locking.", &opt_external_locking, &opt_external_locking,
7913    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
7914   /* We must always support the next option to make scripts like mysqltest
7915      easier to do */
7916   {"gdb", 0,
7917    "Set up signals usable for debugging.",
7918    &opt_debugging, &opt_debugging,
7919    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
7920 #ifdef HAVE_LARGE_PAGE_OPTION
7921   {"super-large-pages", 0, "Enable support for super large pages.",
7922    &opt_super_large_pages, &opt_super_large_pages, 0,
7923    GET_BOOL, OPT_ARG, 0, 0, 1, 0, 1, 0},
7924 #endif
7925   {"ignore-db-dir", OPT_IGNORE_DB_DIRECTORY,
7926    "Specifies a directory to add to the ignore list when collecting "
7927    "database names from the datadir. Put a blank argument to reset "
7928    "the list accumulated so far.", 0, 0, 0, GET_STR, REQUIRED_ARG,
7929    0, 0, 0, 0, 0, 0},
7930   {"language", 'L',
7931    "Client error messages in given language. May be given as a full path. "
7932    "Deprecated. Use --lc-messages-dir instead.",
7933    &lc_messages_dir_ptr, &lc_messages_dir_ptr, 0,
7934    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
7935   {"lc-messages", 0,
7936    "Set the language used for the error messages.",
7937    &lc_messages, &lc_messages, 0, GET_STR, REQUIRED_ARG,
7938    0, 0, 0, 0, 0, 0 },
7939   {"lc-time-names", 0,
7940    "Set the language used for the month names and the days of the week.",
7941    &lc_time_names_name, &lc_time_names_name,
7942    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
7943   {"log-bin", OPT_BIN_LOG,
7944    "Log update queries in binary format. Optional (but strongly recommended "
7945    "to avoid replication problems if server's hostname changes) argument "
7946    "should be the chosen location for the binary log files.",
7947    &opt_bin_logname, &opt_bin_logname, 0, GET_STR_ALLOC,
7948    OPT_ARG, 0, 0, 0, 0, 0, 0},
7949   {"log-bin-index", 0,
7950    "File that holds the names for binary log files.",
7951    &opt_binlog_index_name, &opt_binlog_index_name, 0, GET_STR,
7952    REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
7953   {"relay-log-index", 0,
7954    "File that holds the names for relay log files.",
7955    &opt_relaylog_index_name, &opt_relaylog_index_name, 0, GET_STR,
7956    REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
7957   {"log-isam", OPT_ISAM_LOG, "Log all MyISAM changes to file.",
7958    &myisam_log_filename, &myisam_log_filename, 0, GET_STR,
7959    OPT_ARG, 0, 0, 0, 0, 0, 0},
7960   {"log-raw", 0,
7961    "Log to general log before any rewriting of the query. For use in debugging, not production as "
7962    "sensitive information may be logged.",
7963    &opt_log_raw, &opt_log_raw,
7964    0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0 },
7965   {"log-short-format", 0,
7966    "Don't log extra information to update and slow-query logs.",
7967    &opt_short_log_format, &opt_short_log_format,
7968    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
7969   {"log-tc", 0,
7970    "Path to transaction coordinator log (used for transactions that affect "
7971    "more than one storage engine, when binary log is disabled).",
7972    &opt_tc_log_file, &opt_tc_log_file, 0, GET_STR,
7973    REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
7974 #ifdef HAVE_MMAP
7975   {"log-tc-size", 0, "Size of transaction coordinator log.",
7976    &opt_tc_log_size, &opt_tc_log_size, 0, GET_ULONG,
7977    REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, ULONG_MAX, 0,
7978    TC_LOG_PAGE_SIZE, 0},
7979 #endif
7980   {"master-info-file", 0,
7981    "The location and name of the file that remembers the master and where "
7982    "the I/O replication thread is in the master's binlogs.",
7983    &master_info_file, &master_info_file, 0, GET_STR,
7984    REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
7985   {"master-retry-count", OPT_MASTER_RETRY_COUNT,
7986    "The number of tries the slave will make to connect to the master before giving up. "
7987    "Deprecated option, use 'CHANGE MASTER TO master_retry_count = <num>' instead.",
7988    &master_retry_count, &master_retry_count, 0, GET_ULONG,
7989    REQUIRED_ARG, 3600*24, 0, 0, 0, 0, 0},
7990 #ifdef HAVE_REPLICATION
7991   {"max-binlog-dump-events", 0,
7992    "Option used by mysql-test for debugging and testing of replication.",
7993    &max_binlog_dump_events, &max_binlog_dump_events, 0,
7994    GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
7995 #endif /* HAVE_REPLICATION */
7996   {"memlock", 0, "Lock mysqld in memory.", &locked_in_memory,
7997    &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
7998   {"old-style-user-limits", 0,
7999    "Enable old-style user limits (before 5.0.3, user resources were counted "
8000    "per each user+host vs. per account).",
8001    &opt_old_style_user_limits, &opt_old_style_user_limits,
8002    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
8003   {"port-open-timeout", 0,
8004    "Maximum time in seconds to wait for the port to become free. "
8005    "(Default: No wait).", &mysqld_port_timeout, &mysqld_port_timeout, 0,
8006    GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
8007   {"replicate-do-db", OPT_REPLICATE_DO_DB,
8008    "Tells the slave thread to restrict replication to the specified database. "
8009    "To specify more than one database, use the directive multiple times, "
8010    "once for each database. Note that this will only work if you do not use "
8011    "cross-database queries such as UPDATE some_db.some_table SET foo='bar' "
8012    "while having selected a different or no database. If you need cross "
8013    "database updates to work, make sure you have 3.23.28 or later, and use "
8014    "replicate-wild-do-table=db_name.%.",
8015    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
8016   {"replicate-do-table", OPT_REPLICATE_DO_TABLE,
8017    "Tells the slave thread to restrict replication to the specified table. "
8018    "To specify more than one table, use the directive multiple times, once "
8019    "for each table. This will work for cross-database updates, in contrast "
8020    "to replicate-do-db.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
8021   {"replicate-ignore-db", OPT_REPLICATE_IGNORE_DB,
8022    "Tells the slave thread to not replicate to the specified database. To "
8023    "specify more than one database to ignore, use the directive multiple "
8024    "times, once for each database. This option will not work if you use "
8025    "cross database updates. If you need cross database updates to work, "
8026    "make sure you have 3.23.28 or later, and use replicate-wild-ignore-"
8027    "table=db_name.%. ", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
8028   {"replicate-ignore-table", OPT_REPLICATE_IGNORE_TABLE,
8029    "Tells the slave thread to not replicate to the specified table. To specify "
8030    "more than one table to ignore, use the directive multiple times, once for "
8031    "each table. This will work for cross-database updates, in contrast to "
8032    "replicate-ignore-db.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
8033   {"replicate-rewrite-db", OPT_REPLICATE_REWRITE_DB,
8034    "Updates to a database with a different name than the original. Example: "
8035    "replicate-rewrite-db=master_db_name->slave_db_name.",
8036    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
8037 #ifdef HAVE_REPLICATION
8038   {"replicate-same-server-id", 0,
8039    "In replication, if set to 1, do not skip events having our server id. "
8040    "Default value is 0 (to break infinite loops in circular replication). "
8041    "Can't be set to 1 if --log-slave-updates is used.",
8042    &replicate_same_server_id, &replicate_same_server_id,
8043    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
8044 #endif
8045   {"replicate-wild-do-table", OPT_REPLICATE_WILD_DO_TABLE,
8046    "Tells the slave thread to restrict replication to the tables that match "
8047    "the specified wildcard pattern. To specify more than one table, use the "
8048    "directive multiple times, once for each table. This will work for cross-"
8049    "database updates. Example: replicate-wild-do-table=foo%.bar% will "
8050    "replicate only updates to tables in all databases that start with foo "
8051    "and whose table names start with bar.",
8052    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
8053   {"replicate-wild-ignore-table", OPT_REPLICATE_WILD_IGNORE_TABLE,
8054    "Tells the slave thread to not replicate to the tables that match the "
8055    "given wildcard pattern. To specify more than one table to ignore, use "
8056    "the directive multiple times, once for each table. This will work for "
8057    "cross-database updates. Example: replicate-wild-ignore-table=foo%.bar% "
8058    "will not do updates to tables in databases that start with foo and whose "
8059    "table names start with bar.",
8060    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
8061   {"safe-user-create", 0,
8062    "Don't allow new user creation by the user who has no write privileges to the mysql.user table.",
8063    &opt_safe_user_create, &opt_safe_user_create, 0, GET_BOOL,
8064    NO_ARG, 0, 0, 0, 0, 0, 0},
8065   {"show-slave-auth-info", 0,
8066    "Show user and password in SHOW SLAVE HOSTS on this master.",
8067    &opt_show_slave_auth_info, &opt_show_slave_auth_info, 0,
8068    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
8069   {"skip-host-cache", OPT_SKIP_HOST_CACHE, "Don't cache host names.", 0, 0, 0,
8070    GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
8071   {"skip-new", OPT_SKIP_NEW, "Don't use new, possibly wrong routines.",
8072    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
8073   {"skip-slave-start", 0,
8074    "If set, slave is not autostarted.", &opt_skip_slave_start,
8075    &opt_skip_slave_start, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
8076   {"skip-stack-trace", OPT_SKIP_STACK_TRACE,
8077    "Don't print a stack trace on failure.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
8078    0, 0, 0, 0},
8079 #if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
8080   {"slow-start-timeout", 0,
8081    "Maximum number of milliseconds that the service control manager should wait "
8082    "before trying to kill the windows service during startup"
8083    "(Default: 15000).", &slow_start_timeout, &slow_start_timeout, 0,
8084    GET_ULONG, REQUIRED_ARG, 15000, 0, 0, 0, 0, 0},
8085 #endif
8086 #ifdef HAVE_REPLICATION
8087   {"sporadic-binlog-dump-fail", 0,
8088    "Option used by mysql-test for debugging and testing of replication.",
8089    &opt_sporadic_binlog_dump_fail,
8090    &opt_sporadic_binlog_dump_fail, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
8091    0},
8092 #endif /* HAVE_REPLICATION */
8093 #ifdef HAVE_OPENSSL
8094   {"ssl", 0,
8095    "Enable SSL for connection (automatically enabled with other flags).",
8096    &opt_use_ssl, &opt_use_ssl, 0, GET_BOOL, OPT_ARG, 0, 0, 0,
8097    0, 0, 0},
8098 #endif
8099 #ifdef __WIN__
8100   {"standalone", 0,
8101   "Dummy option to start as a standalone program (NT).", 0, 0, 0, GET_NO_ARG,
8102    NO_ARG, 0, 0, 0, 0, 0, 0},
8103 #endif
8104   {"symbolic-links", 's', "Enable symbolic link support.",
8105    &my_use_symdir, &my_use_symdir, 0, GET_BOOL, NO_ARG,
8106    /*
8107      The system call realpath() produces warnings under valgrind and
8108      purify. These are not suppressed: instead we disable symlinks
8109      option if compiled with valgrind support.
8110    */
8111    IF_PURIFY(0,1), 0, 0, 0, 0, 0},
8112   {"sysdate-is-now", 0,
8113    "Non-default option to alias SYSDATE() to NOW() to make it safe-replicable. "
8114    "Since 5.0, SYSDATE() returns a `dynamic' value different for different "
8115    "invocations, even within the same statement.",
8116    &global_system_variables.sysdate_is_now,
8117    0, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
8118   {"tc-heuristic-recover", 0,
8119    "Decision to use in heuristic recover process. Possible values are COMMIT "
8120    "or ROLLBACK.", &tc_heuristic_recover, &tc_heuristic_recover,
8121    &tc_heuristic_recover_typelib, GET_ENUM, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
8122 #if defined(ENABLED_DEBUG_SYNC)
8123   {"debug-sync-timeout", OPT_DEBUG_SYNC_TIMEOUT,
8124    "Enable the debug sync facility "
8125    "and optionally specify a default wait timeout in seconds. "
8126    "A zero value keeps the facility disabled.",
8127    &opt_debug_sync_timeout, 0,
8128    0, GET_UINT, OPT_ARG, 0, 0, UINT_MAX, 0, 0, 0},
8129 #endif /* defined(ENABLED_DEBUG_SYNC) */
8130   {"temp-pool", 0,
8131 #if (ENABLE_TEMP_POOL)
8132    "Using this option will cause most temporary files created to use a small "
8133    "set of names, rather than a unique name for each new file.",
8134 #else
8135    "This option is ignored on this OS.",
8136 #endif
8137    &use_temp_pool, &use_temp_pool, 0, GET_BOOL, NO_ARG, 1,
8138    0, 0, 0, 0, 0},
8139   {"transaction-isolation", 0,
8140    "Default transaction isolation level.",
8141    &global_system_variables.tx_isolation,
8142    &global_system_variables.tx_isolation, &tx_isolation_typelib,
8143    GET_ENUM, REQUIRED_ARG, ISO_REPEATABLE_READ, 0, 0, 0, 0, 0},
8144   {"transaction-read-only", 0,
8145    "Default transaction access mode. "
8146    "True if transactions are read-only.",
8147    &global_system_variables.tx_read_only,
8148    &global_system_variables.tx_read_only, 0,
8149    GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
8150   {"user", 'u', "Run mysqld daemon as user.", 0, 0, 0, GET_STR, REQUIRED_ARG,
8151    0, 0, 0, 0, 0, 0},
8152   {"plugin-load", OPT_PLUGIN_LOAD,
8153    "Optional semicolon-separated list of plugins to load, where each plugin is "
8154    "identified as name=library, where name is the plugin name and library "
8155    "is the plugin library in plugin_dir.",
8156    0, 0, 0,
8157    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
8158   {"plugin-load-add", OPT_PLUGIN_LOAD_ADD,
8159    "Optional semicolon-separated list of plugins to load, where each plugin is "
8160    "identified as name=library, where name is the plugin name and library "
8161    "is the plugin library in plugin_dir. This option adds to the list "
8162    "speficied by --plugin-load in an incremental way. "
8163    "Multiple --plugin-load-add are supported.",
8164    0, 0, 0,
8165    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
8166   {"default_authentication_plugin", OPT_DEFAULT_AUTH,
8167    "Defines what password- and authentication algorithm to use per default",
8168    0, 0, 0,
8169    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
8170   {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
8171 };
8172 
8173 
show_queries(THD * thd,SHOW_VAR * var,char * buff)8174 static int show_queries(THD *thd, SHOW_VAR *var, char *buff)
8175 {
8176   var->type= SHOW_LONGLONG;
8177   var->value= (char *)&thd->query_id;
8178   return 0;
8179 }
8180 
8181 
show_net_compression(THD * thd,SHOW_VAR * var,char * buff)8182 static int show_net_compression(THD *thd, SHOW_VAR *var, char *buff)
8183 {
8184   var->type= SHOW_MY_BOOL;
8185   var->value= (char *)&thd->net.compress;
8186   return 0;
8187 }
8188 
show_starttime(THD * thd,SHOW_VAR * var,char * buff)8189 static int show_starttime(THD *thd, SHOW_VAR *var, char *buff)
8190 {
8191   var->type= SHOW_LONGLONG;
8192   var->value= buff;
8193   *((longlong *)buff)= (longlong) (thd->query_start() - server_start_time);
8194   return 0;
8195 }
8196 
8197 #ifdef ENABLED_PROFILING
show_flushstatustime(THD * thd,SHOW_VAR * var,char * buff)8198 static int show_flushstatustime(THD *thd, SHOW_VAR *var, char *buff)
8199 {
8200   var->type= SHOW_LONGLONG;
8201   var->value= buff;
8202   *((longlong *)buff)= (longlong) (thd->query_start() - flush_status_time);
8203   return 0;
8204 }
8205 #endif
8206 
8207 #ifdef HAVE_REPLICATION
show_slave_running(THD * thd,SHOW_VAR * var,char * buff)8208 static int show_slave_running(THD *thd, SHOW_VAR *var, char *buff)
8209 {
8210   var->type= SHOW_MY_BOOL;
8211   var->value= buff;
8212   *((my_bool *)buff)= (my_bool) (active_mi &&
8213                                  active_mi->slave_running == MYSQL_SLAVE_RUN_CONNECT &&
8214                                  active_mi->rli->slave_running);
8215   return 0;
8216 }
8217 
show_slave_retried_trans(THD * thd,SHOW_VAR * var,char * buff)8218 static int show_slave_retried_trans(THD *thd, SHOW_VAR *var, char *buff)
8219 {
8220   /*
8221     TODO: with multimaster, have one such counter per line in
8222     SHOW SLAVE STATUS, and have the sum over all lines here.
8223   */
8224   if (active_mi)
8225   {
8226     var->type= SHOW_LONG;
8227     var->value= buff;
8228     *((long *)buff)= (long)active_mi->rli->retried_trans;
8229   }
8230   else
8231     var->type= SHOW_UNDEF;
8232   return 0;
8233 }
8234 
show_slave_received_heartbeats(THD * thd,SHOW_VAR * var,char * buff)8235 static int show_slave_received_heartbeats(THD *thd, SHOW_VAR *var, char *buff)
8236 {
8237   if (active_mi)
8238   {
8239     var->type= SHOW_LONGLONG;
8240     var->value= buff;
8241     *((longlong *)buff)= active_mi->received_heartbeats;
8242   }
8243   else
8244     var->type= SHOW_UNDEF;
8245   return 0;
8246 }
8247 
show_slave_last_heartbeat(THD * thd,SHOW_VAR * var,char * buff)8248 static int show_slave_last_heartbeat(THD *thd, SHOW_VAR *var, char *buff)
8249 {
8250   MYSQL_TIME received_heartbeat_time;
8251   if (active_mi)
8252   {
8253     var->type= SHOW_CHAR;
8254     var->value= buff;
8255     if (active_mi->last_heartbeat == 0)
8256       buff[0]='\0';
8257     else
8258     {
8259       thd->variables.time_zone->gmt_sec_to_TIME(&received_heartbeat_time,
8260         active_mi->last_heartbeat);
8261       my_datetime_to_str(&received_heartbeat_time, buff, 0);
8262     }
8263   }
8264   else
8265     var->type= SHOW_UNDEF;
8266   return 0;
8267 }
8268 
show_heartbeat_period(THD * thd,SHOW_VAR * var,char * buff)8269 static int show_heartbeat_period(THD *thd, SHOW_VAR *var, char *buff)
8270 {
8271   DEBUG_SYNC(thd, "dsync_show_heartbeat_period");
8272   if (active_mi)
8273   {
8274     var->type= SHOW_CHAR;
8275     var->value= buff;
8276     sprintf(buff, "%.3f", active_mi->heartbeat_period);
8277   }
8278   else
8279     var->type= SHOW_UNDEF;
8280   return 0;
8281 }
8282 
8283 #ifndef DBUG_OFF
show_slave_rows_last_search_algorithm_used(THD * thd,SHOW_VAR * var,char * buff)8284 static int show_slave_rows_last_search_algorithm_used(THD *thd, SHOW_VAR *var, char *buff)
8285 {
8286   uint res= slave_rows_last_search_algorithm_used;
8287   const char* s= ((res == Rows_log_event::ROW_LOOKUP_TABLE_SCAN) ? "TABLE_SCAN" :
8288                   ((res == Rows_log_event::ROW_LOOKUP_HASH_SCAN) ? "HASH_SCAN" :
8289                    "INDEX_SCAN"));
8290 
8291   var->type= SHOW_CHAR;
8292   var->value= buff;
8293   sprintf(buff, "%s", s);
8294 
8295   return 0;
8296 }
8297 #endif
8298 
8299 #endif /* HAVE_REPLICATION */
8300 
show_open_tables(THD * thd,SHOW_VAR * var,char * buff)8301 static int show_open_tables(THD *thd, SHOW_VAR *var, char *buff)
8302 {
8303   var->type= SHOW_LONG;
8304   var->value= buff;
8305   *((long *)buff)= (long)table_cache_manager.cached_tables();
8306   return 0;
8307 }
8308 
show_prepared_stmt_count(THD * thd,SHOW_VAR * var,char * buff)8309 static int show_prepared_stmt_count(THD *thd, SHOW_VAR *var, char *buff)
8310 {
8311   var->type= SHOW_LONG;
8312   var->value= buff;
8313   mysql_mutex_lock(&LOCK_prepared_stmt_count);
8314   *((long *)buff)= (long)prepared_stmt_count;
8315   mysql_mutex_unlock(&LOCK_prepared_stmt_count);
8316   return 0;
8317 }
8318 
show_table_definitions(THD * thd,SHOW_VAR * var,char * buff)8319 static int show_table_definitions(THD *thd, SHOW_VAR *var, char *buff)
8320 {
8321   var->type= SHOW_LONG;
8322   var->value= buff;
8323   *((long *)buff)= (long)cached_table_definitions();
8324   return 0;
8325 }
8326 
8327 #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
8328 /* Functions relying on CTX */
show_ssl_ctx_sess_accept(THD * thd,SHOW_VAR * var,char * buff)8329 static int show_ssl_ctx_sess_accept(THD *thd, SHOW_VAR *var, char *buff)
8330 {
8331   var->type= SHOW_LONG;
8332   var->value= buff;
8333   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
8334                      SSL_CTX_sess_accept(ssl_acceptor_fd->ssl_context));
8335   return 0;
8336 }
8337 
show_ssl_ctx_sess_accept_good(THD * thd,SHOW_VAR * var,char * buff)8338 static int show_ssl_ctx_sess_accept_good(THD *thd, SHOW_VAR *var, char *buff)
8339 {
8340   var->type= SHOW_LONG;
8341   var->value= buff;
8342   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
8343                      SSL_CTX_sess_accept_good(ssl_acceptor_fd->ssl_context));
8344   return 0;
8345 }
8346 
show_ssl_ctx_sess_connect_good(THD * thd,SHOW_VAR * var,char * buff)8347 static int show_ssl_ctx_sess_connect_good(THD *thd, SHOW_VAR *var, char *buff)
8348 {
8349   var->type= SHOW_LONG;
8350   var->value= buff;
8351   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
8352                      SSL_CTX_sess_connect_good(ssl_acceptor_fd->ssl_context));
8353   return 0;
8354 }
8355 
show_ssl_ctx_sess_accept_renegotiate(THD * thd,SHOW_VAR * var,char * buff)8356 static int show_ssl_ctx_sess_accept_renegotiate(THD *thd, SHOW_VAR *var, char *buff)
8357 {
8358   var->type= SHOW_LONG;
8359   var->value= buff;
8360   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
8361                      SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context));
8362   return 0;
8363 }
8364 
show_ssl_ctx_sess_connect_renegotiate(THD * thd,SHOW_VAR * var,char * buff)8365 static int show_ssl_ctx_sess_connect_renegotiate(THD *thd, SHOW_VAR *var, char *buff)
8366 {
8367   var->type= SHOW_LONG;
8368   var->value= buff;
8369   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
8370                      SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd->ssl_context));
8371   return 0;
8372 }
8373 
show_ssl_ctx_sess_cb_hits(THD * thd,SHOW_VAR * var,char * buff)8374 static int show_ssl_ctx_sess_cb_hits(THD *thd, SHOW_VAR *var, char *buff)
8375 {
8376   var->type= SHOW_LONG;
8377   var->value= buff;
8378   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
8379                      SSL_CTX_sess_cb_hits(ssl_acceptor_fd->ssl_context));
8380   return 0;
8381 }
8382 
show_ssl_ctx_sess_hits(THD * thd,SHOW_VAR * var,char * buff)8383 static int show_ssl_ctx_sess_hits(THD *thd, SHOW_VAR *var, char *buff)
8384 {
8385   var->type= SHOW_LONG;
8386   var->value= buff;
8387   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
8388                      SSL_CTX_sess_hits(ssl_acceptor_fd->ssl_context));
8389   return 0;
8390 }
8391 
show_ssl_ctx_sess_cache_full(THD * thd,SHOW_VAR * var,char * buff)8392 static int show_ssl_ctx_sess_cache_full(THD *thd, SHOW_VAR *var, char *buff)
8393 {
8394   var->type= SHOW_LONG;
8395   var->value= buff;
8396   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
8397                      SSL_CTX_sess_cache_full(ssl_acceptor_fd->ssl_context));
8398   return 0;
8399 }
8400 
show_ssl_ctx_sess_misses(THD * thd,SHOW_VAR * var,char * buff)8401 static int show_ssl_ctx_sess_misses(THD *thd, SHOW_VAR *var, char *buff)
8402 {
8403   var->type= SHOW_LONG;
8404   var->value= buff;
8405   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
8406                      SSL_CTX_sess_misses(ssl_acceptor_fd->ssl_context));
8407   return 0;
8408 }
8409 
show_ssl_ctx_sess_timeouts(THD * thd,SHOW_VAR * var,char * buff)8410 static int show_ssl_ctx_sess_timeouts(THD *thd, SHOW_VAR *var, char *buff)
8411 {
8412   var->type= SHOW_LONG;
8413   var->value= buff;
8414   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
8415                      SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context));
8416   return 0;
8417 }
8418 
show_ssl_ctx_sess_number(THD * thd,SHOW_VAR * var,char * buff)8419 static int show_ssl_ctx_sess_number(THD *thd, SHOW_VAR *var, char *buff)
8420 {
8421   var->type= SHOW_LONG;
8422   var->value= buff;
8423   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
8424                      SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context));
8425   return 0;
8426 }
8427 
show_ssl_ctx_sess_connect(THD * thd,SHOW_VAR * var,char * buff)8428 static int show_ssl_ctx_sess_connect(THD *thd, SHOW_VAR *var, char *buff)
8429 {
8430   var->type= SHOW_LONG;
8431   var->value= buff;
8432   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
8433                      SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context));
8434   return 0;
8435 }
8436 
show_ssl_ctx_sess_get_cache_size(THD * thd,SHOW_VAR * var,char * buff)8437 static int show_ssl_ctx_sess_get_cache_size(THD *thd, SHOW_VAR *var, char *buff)
8438 {
8439   var->type= SHOW_LONG;
8440   var->value= buff;
8441   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
8442                      SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context));
8443   return 0;
8444 }
8445 
show_ssl_ctx_get_verify_mode(THD * thd,SHOW_VAR * var,char * buff)8446 static int show_ssl_ctx_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff)
8447 {
8448   var->type= SHOW_LONG;
8449   var->value= buff;
8450   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
8451                      SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context));
8452   return 0;
8453 }
8454 
show_ssl_ctx_get_verify_depth(THD * thd,SHOW_VAR * var,char * buff)8455 static int show_ssl_ctx_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff)
8456 {
8457   var->type= SHOW_LONG;
8458   var->value= buff;
8459   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
8460                      SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context));
8461   return 0;
8462 }
8463 
show_ssl_ctx_get_session_cache_mode(THD * thd,SHOW_VAR * var,char * buff)8464 static int show_ssl_ctx_get_session_cache_mode(THD *thd, SHOW_VAR *var, char *buff)
8465 {
8466   var->type= SHOW_CHAR;
8467   if (!ssl_acceptor_fd)
8468     var->value= const_cast<char*>("NONE");
8469   else
8470     switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context))
8471     {
8472     case SSL_SESS_CACHE_OFF:
8473       var->value= const_cast<char*>("OFF"); break;
8474     case SSL_SESS_CACHE_CLIENT:
8475       var->value= const_cast<char*>("CLIENT"); break;
8476     case SSL_SESS_CACHE_SERVER:
8477       var->value= const_cast<char*>("SERVER"); break;
8478     case SSL_SESS_CACHE_BOTH:
8479       var->value= const_cast<char*>("BOTH"); break;
8480     case SSL_SESS_CACHE_NO_AUTO_CLEAR:
8481       var->value= const_cast<char*>("NO_AUTO_CLEAR"); break;
8482     case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP:
8483       var->value= const_cast<char*>("NO_INTERNAL_LOOKUP"); break;
8484     default:
8485       var->value= const_cast<char*>("Unknown"); break;
8486     }
8487   return 0;
8488 }
8489 
8490 /*
8491    Functions relying on SSL
8492    Note: In the show_ssl_* functions, we need to check if we have a
8493          valid vio-object since this isn't always true, specifically
8494          when session_status or global_status is requested from
8495          inside an Event.
8496  */
show_ssl_get_version(THD * thd,SHOW_VAR * var,char * buff)8497 static int show_ssl_get_version(THD *thd, SHOW_VAR *var, char *buff)
8498 {
8499   var->type= SHOW_CHAR;
8500   if( thd->vio_ok() && thd->net.vio->ssl_arg )
8501     var->value= const_cast<char*>(SSL_get_version((SSL*) thd->net.vio->ssl_arg));
8502   else
8503     var->value= (char *)"";
8504   return 0;
8505 }
8506 
show_ssl_session_reused(THD * thd,SHOW_VAR * var,char * buff)8507 static int show_ssl_session_reused(THD *thd, SHOW_VAR *var, char *buff)
8508 {
8509   var->type= SHOW_LONG;
8510   var->value= buff;
8511   if( thd->vio_ok() && thd->net.vio->ssl_arg )
8512     *((long *)buff)= (long)SSL_session_reused((SSL*) thd->net.vio->ssl_arg);
8513   else
8514     *((long *)buff)= 0;
8515   return 0;
8516 }
8517 
show_ssl_get_default_timeout(THD * thd,SHOW_VAR * var,char * buff)8518 static int show_ssl_get_default_timeout(THD *thd, SHOW_VAR *var, char *buff)
8519 {
8520   var->type= SHOW_LONG;
8521   var->value= buff;
8522   if( thd->vio_ok() && thd->net.vio->ssl_arg )
8523     *((long *)buff)= (long)SSL_get_default_timeout((SSL*)thd->net.vio->ssl_arg);
8524   else
8525     *((long *)buff)= 0;
8526   return 0;
8527 }
8528 
show_ssl_get_verify_mode(THD * thd,SHOW_VAR * var,char * buff)8529 static int show_ssl_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff)
8530 {
8531   var->type= SHOW_LONG;
8532   var->value= buff;
8533   if( thd->net.vio && thd->net.vio->ssl_arg )
8534     *((long *)buff)= (long)SSL_get_verify_mode((SSL*)thd->net.vio->ssl_arg);
8535   else
8536     *((long *)buff)= 0;
8537   return 0;
8538 }
8539 
show_ssl_get_verify_depth(THD * thd,SHOW_VAR * var,char * buff)8540 static int show_ssl_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff)
8541 {
8542   var->type= SHOW_LONG;
8543   var->value= buff;
8544   if( thd->vio_ok() && thd->net.vio->ssl_arg )
8545     *((long *)buff)= (long)SSL_get_verify_depth((SSL*)thd->net.vio->ssl_arg);
8546   else
8547     *((long *)buff)= 0;
8548   return 0;
8549 }
8550 
show_ssl_get_cipher(THD * thd,SHOW_VAR * var,char * buff)8551 static int show_ssl_get_cipher(THD *thd, SHOW_VAR *var, char *buff)
8552 {
8553   var->type= SHOW_CHAR;
8554   if( thd->vio_ok() && thd->net.vio->ssl_arg )
8555     var->value= const_cast<char*>(SSL_get_cipher((SSL*) thd->net.vio->ssl_arg));
8556   else
8557     var->value= (char *)"";
8558   return 0;
8559 }
8560 
show_ssl_get_cipher_list(THD * thd,SHOW_VAR * var,char * buff)8561 static int show_ssl_get_cipher_list(THD *thd, SHOW_VAR *var, char *buff)
8562 {
8563   var->type= SHOW_CHAR;
8564   var->value= buff;
8565   if (thd->vio_ok() && thd->net.vio->ssl_arg)
8566   {
8567     int i;
8568     const char *p;
8569     char *end= buff + SHOW_VAR_FUNC_BUFF_SIZE;
8570     for (i=0; (p= SSL_get_cipher_list((SSL*) thd->net.vio->ssl_arg,i)) &&
8571                buff < end; i++)
8572     {
8573       buff= strnmov(buff, p, end-buff-1);
8574       *buff++= ':';
8575     }
8576     if (i)
8577       buff--;
8578   }
8579   *buff=0;
8580   return 0;
8581 }
8582 
8583 
8584 static char *
my_asn1_time_to_string(ASN1_TIME * time,char * buf,size_t len)8585 my_asn1_time_to_string(ASN1_TIME *time, char *buf, size_t len)
8586 {
8587   int n_read;
8588   char *res= NULL;
8589   BIO *bio= BIO_new(BIO_s_mem());
8590 
8591   if (bio == NULL)
8592     return NULL;
8593 
8594   if (!ASN1_TIME_print(bio, time))
8595     goto end;
8596 
8597   n_read= BIO_read(bio, buf, (int) (len - 1));
8598 
8599   if (n_read > 0)
8600   {
8601     buf[n_read]= 0;
8602     res= buf;
8603   }
8604 
8605 end:
8606   BIO_free(bio);
8607   return res;
8608 }
8609 
8610 
8611 /**
8612   Handler function for the 'ssl_get_server_not_before' variable
8613 
8614   @param      thd  the mysql thread structure
8615   @param      var  the data for the variable
8616   @param[out] buf  the string to put the value of the variable into
8617 
8618   @return          status
8619   @retval     0    success
8620 */
8621 
8622 static int
show_ssl_get_server_not_before(THD * thd,SHOW_VAR * var,char * buff)8623 show_ssl_get_server_not_before(THD *thd, SHOW_VAR *var, char *buff)
8624 {
8625   var->type= SHOW_CHAR;
8626   if(thd->vio_ok() && thd->net.vio->ssl_arg)
8627   {
8628     SSL *ssl= (SSL*) thd->net.vio->ssl_arg;
8629     X509 *cert= SSL_get_certificate(ssl);
8630     ASN1_TIME *not_before= X509_get_notBefore(cert);
8631 
8632     var->value= my_asn1_time_to_string(not_before, buff,
8633                                        SHOW_VAR_FUNC_BUFF_SIZE);
8634     if (!var->value)
8635       return 1;
8636     var->value= buff;
8637   }
8638   else
8639     var->value= empty_c_string;
8640   return 0;
8641 }
8642 
8643 
8644 /**
8645   Handler function for the 'ssl_get_server_not_after' variable
8646 
8647   @param      thd  the mysql thread structure
8648   @param      var  the data for the variable
8649   @param[out] buf  the string to put the value of the variable into
8650 
8651   @return          status
8652   @retval     0    success
8653 */
8654 
8655 static int
show_ssl_get_server_not_after(THD * thd,SHOW_VAR * var,char * buff)8656 show_ssl_get_server_not_after(THD *thd, SHOW_VAR *var, char *buff)
8657 {
8658   var->type= SHOW_CHAR;
8659   if(thd->vio_ok() && thd->net.vio->ssl_arg)
8660   {
8661     SSL *ssl= (SSL*) thd->net.vio->ssl_arg;
8662     X509 *cert= SSL_get_certificate(ssl);
8663     ASN1_TIME *not_after= X509_get_notAfter(cert);
8664 
8665     var->value= my_asn1_time_to_string(not_after, buff,
8666                                        SHOW_VAR_FUNC_BUFF_SIZE);
8667     if (!var->value)
8668       return 1;
8669   }
8670   else
8671     var->value= empty_c_string;
8672   return 0;
8673 }
8674 
8675 #endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
8676 
8677 
8678 /*
8679   Variables shown by SHOW STATUS in alphabetical order
8680 */
8681 
8682 SHOW_VAR status_vars[]= {
8683   {"Aborted_clients",          (char*) &aborted_threads,        SHOW_LONG},
8684   {"Aborted_connects",         (char*) &aborted_connects,       SHOW_LONG},
8685   {"Binlog_cache_disk_use",    (char*) &binlog_cache_disk_use,  SHOW_LONG},
8686   {"Binlog_cache_use",         (char*) &binlog_cache_use,       SHOW_LONG},
8687   {"Binlog_stmt_cache_disk_use",(char*) &binlog_stmt_cache_disk_use,  SHOW_LONG},
8688   {"Binlog_stmt_cache_use",    (char*) &binlog_stmt_cache_use,       SHOW_LONG},
8689   {"Bytes_received",           (char*) offsetof(STATUS_VAR, bytes_received), SHOW_LONGLONG_STATUS},
8690   {"Bytes_sent",               (char*) offsetof(STATUS_VAR, bytes_sent), SHOW_LONGLONG_STATUS},
8691   {"Com",                      (char*) com_status_vars, SHOW_ARRAY},
8692   {"Compression",              (char*) &show_net_compression, SHOW_FUNC},
8693   {"Connections",              (char*) &thread_id,              SHOW_LONG_NOFLUSH},
8694   {"Connection_errors_accept", (char*) &connection_errors_accept, SHOW_LONG},
8695   {"Connection_errors_internal", (char*) &connection_errors_internal, SHOW_LONG},
8696   {"Connection_errors_max_connections", (char*) &connection_errors_max_connection, SHOW_LONG},
8697   {"Connection_errors_peer_address", (char*) &connection_errors_peer_addr, SHOW_LONG},
8698   {"Connection_errors_select", (char*) &connection_errors_select, SHOW_LONG},
8699   {"Connection_errors_tcpwrap", (char*) &connection_errors_tcpwrap, SHOW_LONG},
8700   {"Created_tmp_disk_tables",  (char*) offsetof(STATUS_VAR, created_tmp_disk_tables), SHOW_LONGLONG_STATUS},
8701   {"Created_tmp_files",        (char*) &my_tmp_file_created, SHOW_LONG},
8702   {"Created_tmp_tables",       (char*) offsetof(STATUS_VAR, created_tmp_tables), SHOW_LONGLONG_STATUS},
8703   {"Delayed_errors",           (char*) &delayed_insert_errors,  SHOW_LONG},
8704   {"Delayed_insert_threads",   (char*) &delayed_insert_threads, SHOW_LONG_NOFLUSH},
8705   {"Delayed_writes",           (char*) &delayed_insert_writes,  SHOW_LONG},
8706   {"Flush_commands",           (char*) &refresh_version,        SHOW_LONG_NOFLUSH},
8707   {"Handler_commit",           (char*) offsetof(STATUS_VAR, ha_commit_count), SHOW_LONGLONG_STATUS},
8708   {"Handler_delete",           (char*) offsetof(STATUS_VAR, ha_delete_count), SHOW_LONGLONG_STATUS},
8709   {"Handler_discover",         (char*) offsetof(STATUS_VAR, ha_discover_count), SHOW_LONGLONG_STATUS},
8710   {"Handler_external_lock",    (char*) offsetof(STATUS_VAR, ha_external_lock_count), SHOW_LONGLONG_STATUS},
8711   {"Handler_mrr_init",         (char*) offsetof(STATUS_VAR, ha_multi_range_read_init_count),  SHOW_LONGLONG_STATUS},
8712   {"Handler_prepare",          (char*) offsetof(STATUS_VAR, ha_prepare_count),  SHOW_LONGLONG_STATUS},
8713   {"Handler_read_first",       (char*) offsetof(STATUS_VAR, ha_read_first_count), SHOW_LONGLONG_STATUS},
8714   {"Handler_read_key",         (char*) offsetof(STATUS_VAR, ha_read_key_count), SHOW_LONGLONG_STATUS},
8715   {"Handler_read_last",        (char*) offsetof(STATUS_VAR, ha_read_last_count), SHOW_LONGLONG_STATUS},
8716   {"Handler_read_next",        (char*) offsetof(STATUS_VAR, ha_read_next_count), SHOW_LONGLONG_STATUS},
8717   {"Handler_read_prev",        (char*) offsetof(STATUS_VAR, ha_read_prev_count), SHOW_LONGLONG_STATUS},
8718   {"Handler_read_rnd",         (char*) offsetof(STATUS_VAR, ha_read_rnd_count), SHOW_LONGLONG_STATUS},
8719   {"Handler_read_rnd_next",    (char*) offsetof(STATUS_VAR, ha_read_rnd_next_count), SHOW_LONGLONG_STATUS},
8720   {"Handler_rollback",         (char*) offsetof(STATUS_VAR, ha_rollback_count), SHOW_LONGLONG_STATUS},
8721   {"Handler_savepoint",        (char*) offsetof(STATUS_VAR, ha_savepoint_count), SHOW_LONGLONG_STATUS},
8722   {"Handler_savepoint_rollback",(char*) offsetof(STATUS_VAR, ha_savepoint_rollback_count), SHOW_LONGLONG_STATUS},
8723   {"Handler_update",           (char*) offsetof(STATUS_VAR, ha_update_count), SHOW_LONGLONG_STATUS},
8724   {"Handler_write",            (char*) offsetof(STATUS_VAR, ha_write_count), SHOW_LONGLONG_STATUS},
8725   {"Key_blocks_not_flushed",   (char*) offsetof(KEY_CACHE, global_blocks_changed), SHOW_KEY_CACHE_LONG},
8726   {"Key_blocks_unused",        (char*) offsetof(KEY_CACHE, blocks_unused), SHOW_KEY_CACHE_LONG},
8727   {"Key_blocks_used",          (char*) offsetof(KEY_CACHE, blocks_used), SHOW_KEY_CACHE_LONG},
8728   {"Key_read_requests",        (char*) offsetof(KEY_CACHE, global_cache_r_requests), SHOW_KEY_CACHE_LONGLONG},
8729   {"Key_reads",                (char*) offsetof(KEY_CACHE, global_cache_read), SHOW_KEY_CACHE_LONGLONG},
8730   {"Key_write_requests",       (char*) offsetof(KEY_CACHE, global_cache_w_requests), SHOW_KEY_CACHE_LONGLONG},
8731   {"Key_writes",               (char*) offsetof(KEY_CACHE, global_cache_write), SHOW_KEY_CACHE_LONGLONG},
8732   {"Last_query_cost",          (char*) offsetof(STATUS_VAR, last_query_cost), SHOW_DOUBLE_STATUS},
8733   {"Last_query_partial_plans", (char*) offsetof(STATUS_VAR, last_query_partial_plans), SHOW_LONGLONG_STATUS},
8734   {"Max_used_connections",     (char*) &max_used_connections,  SHOW_LONG},
8735   {"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use,    SHOW_LONG_NOFLUSH},
8736   {"Open_files",               (char*) &my_file_opened,         SHOW_LONG_NOFLUSH},
8737   {"Open_streams",             (char*) &my_stream_opened,       SHOW_LONG_NOFLUSH},
8738   {"Open_table_definitions",   (char*) &show_table_definitions, SHOW_FUNC},
8739   {"Open_tables",              (char*) &show_open_tables,       SHOW_FUNC},
8740   {"Opened_files",             (char*) &my_file_total_opened, SHOW_LONG_NOFLUSH},
8741   {"Opened_tables",            (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONGLONG_STATUS},
8742   {"Opened_table_definitions", (char*) offsetof(STATUS_VAR, opened_shares), SHOW_LONGLONG_STATUS},
8743   {"Prepared_stmt_count",      (char*) &show_prepared_stmt_count, SHOW_FUNC},
8744 #ifdef HAVE_QUERY_CACHE
8745   {"Qcache_free_blocks",       (char*) &query_cache.free_memory_blocks, SHOW_LONG_NOFLUSH},
8746   {"Qcache_free_memory",       (char*) &query_cache.free_memory, SHOW_LONG_NOFLUSH},
8747   {"Qcache_hits",              (char*) &query_cache.hits,       SHOW_LONG},
8748   {"Qcache_inserts",           (char*) &query_cache.inserts,    SHOW_LONG},
8749   {"Qcache_lowmem_prunes",     (char*) &query_cache.lowmem_prunes, SHOW_LONG},
8750   {"Qcache_not_cached",        (char*) &query_cache.refused,    SHOW_LONG},
8751   {"Qcache_queries_in_cache",  (char*) &query_cache.queries_in_cache, SHOW_LONG_NOFLUSH},
8752   {"Qcache_total_blocks",      (char*) &query_cache.total_blocks, SHOW_LONG_NOFLUSH},
8753 #endif /*HAVE_QUERY_CACHE*/
8754   {"Queries",                  (char*) &show_queries,            SHOW_FUNC},
8755   {"Questions",                (char*) offsetof(STATUS_VAR, questions), SHOW_LONGLONG_STATUS},
8756   {"Select_full_join",         (char*) offsetof(STATUS_VAR, select_full_join_count), SHOW_LONGLONG_STATUS},
8757   {"Select_full_range_join",   (char*) offsetof(STATUS_VAR, select_full_range_join_count), SHOW_LONGLONG_STATUS},
8758   {"Select_range",             (char*) offsetof(STATUS_VAR, select_range_count), SHOW_LONGLONG_STATUS},
8759   {"Select_range_check",       (char*) offsetof(STATUS_VAR, select_range_check_count), SHOW_LONGLONG_STATUS},
8760   {"Select_scan",	       (char*) offsetof(STATUS_VAR, select_scan_count), SHOW_LONGLONG_STATUS},
8761   {"Slave_open_temp_tables",   (char*) &slave_open_temp_tables, SHOW_INT},
8762 #ifdef HAVE_REPLICATION
8763   {"Slave_retried_transactions",(char*) &show_slave_retried_trans, SHOW_FUNC},
8764   {"Slave_heartbeat_period",   (char*) &show_heartbeat_period, SHOW_FUNC},
8765   {"Slave_received_heartbeats",(char*) &show_slave_received_heartbeats, SHOW_FUNC},
8766   {"Slave_last_heartbeat",     (char*) &show_slave_last_heartbeat, SHOW_FUNC},
8767 #ifndef DBUG_OFF
8768   {"Slave_rows_last_search_algorithm_used",(char*) &show_slave_rows_last_search_algorithm_used, SHOW_FUNC},
8769 #endif
8770   {"Slave_running",            (char*) &show_slave_running,     SHOW_FUNC},
8771 #endif
8772   {"Slow_launch_threads",      (char*) &slow_launch_threads,    SHOW_LONG},
8773   {"Slow_queries",             (char*) offsetof(STATUS_VAR, long_query_count), SHOW_LONGLONG_STATUS},
8774   {"Sort_merge_passes",        (char*) offsetof(STATUS_VAR, filesort_merge_passes), SHOW_LONGLONG_STATUS},
8775   {"Sort_range",               (char*) offsetof(STATUS_VAR, filesort_range_count), SHOW_LONGLONG_STATUS},
8776   {"Sort_rows",                (char*) offsetof(STATUS_VAR, filesort_rows), SHOW_LONGLONG_STATUS},
8777   {"Sort_scan",                (char*) offsetof(STATUS_VAR, filesort_scan_count), SHOW_LONGLONG_STATUS},
8778 #ifdef HAVE_OPENSSL
8779 #ifndef EMBEDDED_LIBRARY
8780   {"Ssl_accept_renegotiates",  (char*) &show_ssl_ctx_sess_accept_renegotiate, SHOW_FUNC},
8781   {"Ssl_accepts",              (char*) &show_ssl_ctx_sess_accept, SHOW_FUNC},
8782   {"Ssl_callback_cache_hits",  (char*) &show_ssl_ctx_sess_cb_hits, SHOW_FUNC},
8783   {"Ssl_cipher",               (char*) &show_ssl_get_cipher, SHOW_FUNC},
8784   {"Ssl_cipher_list",          (char*) &show_ssl_get_cipher_list, SHOW_FUNC},
8785   {"Ssl_client_connects",      (char*) &show_ssl_ctx_sess_connect, SHOW_FUNC},
8786   {"Ssl_connect_renegotiates", (char*) &show_ssl_ctx_sess_connect_renegotiate, SHOW_FUNC},
8787   {"Ssl_ctx_verify_depth",     (char*) &show_ssl_ctx_get_verify_depth, SHOW_FUNC},
8788   {"Ssl_ctx_verify_mode",      (char*) &show_ssl_ctx_get_verify_mode, SHOW_FUNC},
8789   {"Ssl_default_timeout",      (char*) &show_ssl_get_default_timeout, SHOW_FUNC},
8790   {"Ssl_finished_accepts",     (char*) &show_ssl_ctx_sess_accept_good, SHOW_FUNC},
8791   {"Ssl_finished_connects",    (char*) &show_ssl_ctx_sess_connect_good, SHOW_FUNC},
8792   {"Ssl_session_cache_hits",   (char*) &show_ssl_ctx_sess_hits, SHOW_FUNC},
8793   {"Ssl_session_cache_misses", (char*) &show_ssl_ctx_sess_misses, SHOW_FUNC},
8794   {"Ssl_session_cache_mode",   (char*) &show_ssl_ctx_get_session_cache_mode, SHOW_FUNC},
8795   {"Ssl_session_cache_overflows", (char*) &show_ssl_ctx_sess_cache_full, SHOW_FUNC},
8796   {"Ssl_session_cache_size",   (char*) &show_ssl_ctx_sess_get_cache_size, SHOW_FUNC},
8797   {"Ssl_session_cache_timeouts", (char*) &show_ssl_ctx_sess_timeouts, SHOW_FUNC},
8798   {"Ssl_sessions_reused",      (char*) &show_ssl_session_reused, SHOW_FUNC},
8799   {"Ssl_used_session_cache_entries",(char*) &show_ssl_ctx_sess_number, SHOW_FUNC},
8800   {"Ssl_verify_depth",         (char*) &show_ssl_get_verify_depth, SHOW_FUNC},
8801   {"Ssl_verify_mode",          (char*) &show_ssl_get_verify_mode, SHOW_FUNC},
8802   {"Ssl_version",              (char*) &show_ssl_get_version, SHOW_FUNC},
8803   {"Ssl_server_not_before",    (char*) &show_ssl_get_server_not_before,
8804     SHOW_FUNC},
8805   {"Ssl_server_not_after",     (char*) &show_ssl_get_server_not_after,
8806     SHOW_FUNC},
8807   {"Rsa_public_key",           (char*) &show_rsa_public_key, SHOW_FUNC},
8808 #endif
8809 #endif /* HAVE_OPENSSL */
8810   {"Table_locks_immediate",    (char*) &locks_immediate,        SHOW_LONG},
8811   {"Table_locks_waited",       (char*) &locks_waited,           SHOW_LONG},
8812   {"Table_open_cache_hits",    (char*) offsetof(STATUS_VAR, table_open_cache_hits), SHOW_LONGLONG_STATUS},
8813   {"Table_open_cache_misses",  (char*) offsetof(STATUS_VAR, table_open_cache_misses), SHOW_LONGLONG_STATUS},
8814   {"Table_open_cache_overflows",(char*) offsetof(STATUS_VAR, table_open_cache_overflows), SHOW_LONGLONG_STATUS},
8815 #ifdef HAVE_MMAP
8816   {"Tc_log_max_pages_used",    (char*) &tc_log_max_pages_used,  SHOW_LONG},
8817   {"Tc_log_page_size",         (char*) &tc_log_page_size,       SHOW_LONG},
8818   {"Tc_log_page_waits",        (char*) &tc_log_page_waits,      SHOW_LONG},
8819 #endif
8820   {"Threads_cached",           (char*) &blocked_pthread_count,    SHOW_LONG_NOFLUSH},
8821   {"Threads_connected",        (char*) &connection_count,       SHOW_INT},
8822   {"Threads_created",        (char*) &thread_created,   SHOW_LONG_NOFLUSH},
8823   {"Threads_running",          (char*) &num_thread_running,     SHOW_INT},
8824   {"Uptime",                   (char*) &show_starttime,         SHOW_FUNC},
8825 #ifdef ENABLED_PROFILING
8826   {"Uptime_since_flush_status",(char*) &show_flushstatustime,   SHOW_FUNC},
8827 #endif
8828 #ifdef WITH_WSREP
8829   {"wsrep_connected",          (char*) &wsrep_connected,         SHOW_BOOL},
8830   {"wsrep_ready",              (char*) &wsrep_show_ready,        SHOW_FUNC},
8831   {"wsrep_cluster_state_uuid", (char*) &wsrep_cluster_state_uuid,SHOW_CHAR_PTR},
8832   {"wsrep_cluster_conf_id",    (char*) &wsrep_cluster_conf_id,   SHOW_LONGLONG},
8833   {"wsrep_cluster_status",     (char*) &wsrep_cluster_status,    SHOW_CHAR_PTR},
8834   {"wsrep_cluster_size",       (char*) &wsrep_cluster_size,      SHOW_LONG_NOFLUSH},
8835   {"wsrep_local_index",        (char*) &wsrep_local_index,       SHOW_LONG_NOFLUSH},
8836   {"wsrep_local_bf_aborts",    (char*) &wsrep_show_bf_aborts,    SHOW_FUNC},
8837   {"wsrep_provider_name",      (char*) &wsrep_provider_name,     SHOW_CHAR_PTR},
8838   {"wsrep_provider_version",   (char*) &wsrep_provider_version,  SHOW_CHAR_PTR},
8839   {"wsrep_provider_vendor",    (char*) &wsrep_provider_vendor,   SHOW_CHAR_PTR},
8840   {"wsrep",                    (char*) &wsrep_show_status,       SHOW_FUNC},
8841 #endif
8842   {NullS, NullS, SHOW_LONG}
8843 };
8844 
add_terminator(vector<my_option> * options)8845 void add_terminator(vector<my_option> *options)
8846 {
8847   my_option empty_element=
8848     {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0};
8849   options->push_back(empty_element);
8850 }
8851 
8852 #ifndef EMBEDDED_LIBRARY
print_version(void)8853 static void print_version(void)
8854 {
8855   set_server_version();
8856 
8857   printf("%s  Ver %s for %s on %s (%s)\n",my_progname,
8858    server_version,SYSTEM_TYPE,MACHINE_TYPE, MYSQL_COMPILATION_COMMENT);
8859 }
8860 
8861 /** Compares two options' names, treats - and _ the same */
operator <(const my_option & a,const my_option & b)8862 static bool operator<(const my_option &a, const my_option &b)
8863 {
8864   const char *sa= a.name;
8865   const char *sb= b.name;
8866   for (; *sa || *sb; sa++, sb++)
8867   {
8868     if (*sa < *sb)
8869     {
8870       if (*sa == '-' && *sb == '_')
8871         continue;
8872       else
8873         return true;
8874     }
8875     if (*sa > *sb)
8876     {
8877       if (*sa == '_' && *sb == '-')
8878         continue;
8879       else
8880         return false;
8881     }
8882   }
8883   DBUG_ASSERT(a.name == b.name);
8884   return false;
8885 }
8886 
print_help()8887 static void print_help()
8888 {
8889   MEM_ROOT mem_root;
8890   init_alloc_root(&mem_root, 4096, 4096);
8891 
8892   all_options.pop_back();
8893   sys_var_add_options(&all_options, sys_var::PARSE_EARLY);
8894   for (my_option *opt= my_long_early_options;
8895        opt->name != NULL;
8896        opt++)
8897   {
8898     all_options.push_back(*opt);
8899   }
8900   add_plugin_options(&all_options, &mem_root);
8901   std::sort(all_options.begin(), all_options.end(), std::less<my_option>());
8902   add_terminator(&all_options);
8903 
8904   my_print_help(&all_options[0]);
8905   my_print_variables(&all_options[0]);
8906 
8907   free_root(&mem_root, MYF(0));
8908   vector<my_option>().swap(all_options);  // Deletes the vector contents.
8909 }
8910 
usage(void)8911 static void usage(void)
8912 {
8913   DBUG_ENTER("usage");
8914   if (!(default_charset_info= get_charset_by_csname(default_character_set_name,
8915                      MY_CS_PRIMARY,
8916                MYF(MY_WME))))
8917     exit(1);
8918   if (!default_collation_name)
8919     default_collation_name= (char*) default_charset_info->name;
8920   print_version();
8921   puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
8922   puts("Starts the MySQL database server.\n");
8923   printf("Usage: %s [OPTIONS]\n", my_progname);
8924   if (!opt_verbose)
8925     puts("\nFor more help options (several pages), use mysqld --verbose --help.");
8926   else
8927   {
8928 #ifdef __WIN__
8929   puts("NT and Win32 specific options:\n\
8930   --install                     Install the default service (NT).\n\
8931   --install-manual              Install the default service started manually (NT).\n\
8932   --install service_name        Install an optional service (NT).\n\
8933   --install-manual service_name Install an optional service started manually (NT).\n\
8934   --remove                      Remove the default service from the service list (NT).\n\
8935   --remove service_name         Remove the service_name from the service list (NT).\n\
8936   --enable-named-pipe           Only to be used for the default server (NT).\n\
8937   --standalone                  Dummy option to start as a standalone server (NT).\
8938 ");
8939   puts("");
8940 #endif
8941   print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
8942   puts("");
8943   set_ports();
8944 
8945   /* Print out all the options including plugin supplied options */
8946   print_help();
8947 
8948   if (! plugins_are_initialized)
8949   {
8950     puts("\n\
8951 Plugins have parameters that are not reflected in this list\n\
8952 because execution stopped before plugins were initialized.");
8953   }
8954 
8955   puts("\n\
8956 To see what values a running MySQL server is using, type\n\
8957 'mysqladmin variables' instead of 'mysqld --verbose --help'.");
8958   }
8959   DBUG_VOID_RETURN;
8960 }
8961 #endif /*!EMBEDDED_LIBRARY*/
8962 
8963 /**
8964   Initialize MySQL global variables to default values.
8965 
8966   @note
8967     The reason to set a lot of global variables to zero is to allow one to
8968     restart the embedded server with a clean environment
8969     It's also needed on some exotic platforms where global variables are
8970     not set to 0 when a program starts.
8971 
8972     We don't need to set variables refered to in my_long_options
8973     as these are initialized by my_getopt.
8974 */
8975 
mysql_init_variables(void)8976 static int mysql_init_variables(void)
8977 {
8978   /* Things reset to zero */
8979   opt_skip_slave_start= opt_reckless_slave = 0;
8980   mysql_home[0]= pidfile_name[0]= log_error_file[0]= 0;
8981   myisam_test_invalid_symlink= test_if_data_home_dir;
8982   opt_log= opt_slow_log= 0;
8983   opt_bin_log= 0;
8984   opt_disable_networking= opt_skip_show_db=0;
8985   opt_skip_name_resolve= 0;
8986   opt_ignore_builtin_innodb= 0;
8987   opt_logname= opt_update_logname= opt_binlog_index_name= opt_slow_logname= 0;
8988   opt_tc_log_file= (char *)"tc.log";      // no hostname in tc_log file name !
8989   opt_secure_auth= 0;
8990   opt_myisam_log= 0;
8991   mqh_used= 0;
8992   kill_in_progress= 0;
8993   cleanup_done= 0;
8994   server_id_supplied= 0;
8995   test_flags= select_errors= dropping_tables= ha_open_options=0;
8996   global_thread_count= num_thread_running= kill_blocked_pthreads_flag= wake_pthread=0;
8997   slave_open_temp_tables= 0;
8998   blocked_pthread_count= 0;
8999   opt_endinfo= using_udf_functions= 0;
9000   opt_using_transactions= 0;
9001   abort_loop= select_thread_in_use= signal_thread_in_use= 0;
9002   ready_to_exit= shutdown_in_progress= grant_option= 0;
9003   aborted_threads= aborted_connects= 0;
9004   delayed_insert_threads= delayed_insert_writes= delayed_rows_in_use= 0;
9005   delayed_insert_errors= thread_created= 0;
9006   specialflag= 0;
9007   binlog_cache_use=  binlog_cache_disk_use= 0;
9008   max_used_connections= slow_launch_threads = 0;
9009   mysqld_user= mysqld_chroot= opt_init_file= opt_bin_logname = 0;
9010   prepared_stmt_count= 0;
9011   mysqld_unix_port= opt_mysql_tmpdir= my_bind_addr_str= NullS;
9012   memset(&mysql_tmpdir_list, 0, sizeof(mysql_tmpdir_list));
9013   memset(&global_status_var, 0, sizeof(global_status_var));
9014   opt_large_pages= 0;
9015   opt_super_large_pages= 0;
9016 #if defined(ENABLED_DEBUG_SYNC)
9017   opt_debug_sync_timeout= 0;
9018 #endif /* defined(ENABLED_DEBUG_SYNC) */
9019   key_map_full.set_all();
9020   server_uuid[0]= 0;
9021 
9022   /* Character sets */
9023   system_charset_info= &my_charset_utf8_general_ci;
9024   files_charset_info= &my_charset_utf8_general_ci;
9025   national_charset_info= &my_charset_utf8_general_ci;
9026   table_alias_charset= &my_charset_bin;
9027   character_set_filesystem= &my_charset_bin;
9028 
9029   opt_specialflag= SPECIAL_ENGLISH;
9030   unix_sock= MYSQL_INVALID_SOCKET;
9031   ip_sock= MYSQL_INVALID_SOCKET;
9032   mysql_home_ptr= mysql_home;
9033   pidfile_name_ptr= pidfile_name;
9034   log_error_file_ptr= log_error_file;
9035   lc_messages_dir_ptr= lc_messages_dir;
9036   protocol_version= PROTOCOL_VERSION;
9037   what_to_log= ~ (1L << (uint) COM_TIME);
9038   refresh_version= 1L;  /* Increments on each reload */
9039   global_query_id= thread_id= 1L;
9040   my_atomic_rwlock_init(&opt_binlog_max_flush_queue_time_lock);
9041   my_atomic_rwlock_init(&global_query_id_lock);
9042   my_atomic_rwlock_init(&thread_running_lock);
9043   strmov(server_version, MYSQL_SERVER_VERSION);
9044   global_thread_list= new std::set<THD*>;
9045   waiting_thd_list= new std::list<THD*>;
9046   key_caches.empty();
9047   if (!(dflt_key_cache= get_or_create_key_cache(default_key_cache_base.str,
9048                                                 default_key_cache_base.length)))
9049   {
9050     sql_print_error("Cannot allocate the keycache");
9051     return 1;
9052   }
9053   /* set key_cache_hash.default_value = dflt_key_cache */
9054   multi_keycache_init();
9055 
9056   /* Set directory paths */
9057   mysql_real_data_home_len=
9058     strmake(mysql_real_data_home, get_relative_path(MYSQL_DATADIR),
9059             sizeof(mysql_real_data_home)-1) - mysql_real_data_home;
9060   /* Replication parameters */
9061   master_info_file= (char*) "master.info",
9062     relay_log_info_file= (char*) "relay-log.info";
9063   report_user= report_password = report_host= 0;  /* TO BE DELETED */
9064   opt_relay_logname= opt_relaylog_index_name= 0;
9065   log_bin_basename= NULL;
9066   log_bin_index= NULL;
9067 
9068   /* Handler variables */
9069   total_ha= 0;
9070   total_ha_2pc= 0;
9071   /* Variables in libraries */
9072   charsets_dir= 0;
9073   default_character_set_name= (char*) MYSQL_DEFAULT_CHARSET_NAME;
9074   default_collation_name= compiled_default_collation_name;
9075   character_set_filesystem_name= (char*) "binary";
9076   lc_messages= (char*) "en_US";
9077   lc_time_names_name= (char*) "en_US";
9078 
9079   /* Variables that depends on compile options */
9080 #ifndef DBUG_OFF
9081   default_dbug_option=IF_WIN("d:t:i:O,\\mysqld.trace",
9082            "d:t:i:o,/tmp/mysqld.trace");
9083 #endif
9084   opt_error_log= IF_WIN(1,0);
9085 #ifdef ENABLED_PROFILING
9086     have_profiling = SHOW_OPTION_YES;
9087 #else
9088     have_profiling = SHOW_OPTION_NO;
9089 #endif
9090 
9091 #ifdef HAVE_OPENSSL
9092   have_ssl=SHOW_OPTION_YES;
9093 #else
9094   have_ssl=SHOW_OPTION_NO;
9095 #endif
9096 #ifdef HAVE_BROKEN_REALPATH
9097   have_symlink=SHOW_OPTION_NO;
9098 #else
9099   have_symlink=SHOW_OPTION_YES;
9100 #endif
9101 #ifdef HAVE_DLOPEN
9102   have_dlopen=SHOW_OPTION_YES;
9103 #else
9104   have_dlopen=SHOW_OPTION_NO;
9105 #endif
9106 #ifdef HAVE_QUERY_CACHE
9107   have_query_cache=SHOW_OPTION_YES;
9108 #else
9109   have_query_cache=SHOW_OPTION_NO;
9110 #endif
9111 #ifdef HAVE_SPATIAL
9112   have_geometry=SHOW_OPTION_YES;
9113 #else
9114   have_geometry=SHOW_OPTION_NO;
9115 #endif
9116 #ifdef HAVE_RTREE_KEYS
9117   have_rtree_keys=SHOW_OPTION_YES;
9118 #else
9119   have_rtree_keys=SHOW_OPTION_NO;
9120 #endif
9121 #ifdef HAVE_CRYPT
9122   have_crypt=SHOW_OPTION_YES;
9123 #else
9124   have_crypt=SHOW_OPTION_NO;
9125 #endif
9126 #ifdef HAVE_COMPRESS
9127   have_compress= SHOW_OPTION_YES;
9128 #else
9129   have_compress= SHOW_OPTION_NO;
9130 #endif
9131 #ifdef HAVE_LIBWRAP
9132   libwrapName= NullS;
9133 #endif
9134 #ifdef HAVE_OPENSSL
9135   des_key_file = 0;
9136 #ifndef EMBEDDED_LIBRARY
9137   ssl_acceptor_fd= 0;
9138 #endif /* ! EMBEDDED_LIBRARY */
9139 #endif /* HAVE_OPENSSL */
9140 #ifdef HAVE_SMEM
9141   shared_memory_base_name= default_shared_memory_base_name;
9142 #endif
9143 
9144 #if defined(__WIN__)
9145   /* Allow Win32 users to move MySQL anywhere */
9146   {
9147     char prg_dev[LIBLEN];
9148     char executing_path_name[LIBLEN];
9149     if (!test_if_hard_path(my_progname))
9150     {
9151       // we don't want to use GetModuleFileName inside of my_path since
9152       // my_path is a generic path dereferencing function and here we care
9153       // only about the executing binary.
9154       GetModuleFileName(NULL, executing_path_name, sizeof(executing_path_name));
9155       my_path(prg_dev, executing_path_name, NULL);
9156     }
9157     else
9158       my_path(prg_dev, my_progname, "mysql/bin");
9159     strcat(prg_dev,"/../");     // Remove 'bin' to get base dir
9160     cleanup_dirname(mysql_home,prg_dev);
9161   }
9162 #else
9163   const char *tmpenv;
9164   if (!(tmpenv = getenv("MY_BASEDIR_VERSION")))
9165     tmpenv = DEFAULT_MYSQL_HOME;
9166   (void) strmake(mysql_home, tmpenv, sizeof(mysql_home)-1);
9167 #endif
9168 #ifdef WITH_WSREP
9169   if (wsrep_init_vars())
9170     return 1;
9171 #endif
9172   return 0;
9173 }
9174 
9175 my_bool
mysqld_get_one_option(int optid,const struct my_option * opt MY_ATTRIBUTE ((unused)),char * argument)9176 mysqld_get_one_option(int optid,
9177                       const struct my_option *opt MY_ATTRIBUTE((unused)),
9178                       char *argument)
9179 {
9180   switch(optid) {
9181   case '#':
9182 #ifndef DBUG_OFF
9183     DBUG_SET_INITIAL(argument ? argument : default_dbug_option);
9184 #endif
9185     opt_endinfo=1;        /* unireg: memory allocation */
9186     break;
9187   case 'a':
9188     global_system_variables.sql_mode= MODE_ANSI;
9189     global_system_variables.tx_isolation= ISO_SERIALIZABLE;
9190     break;
9191   case 'b':
9192     strmake(mysql_home,argument,sizeof(mysql_home)-1);
9193     mysql_home_ptr= mysql_home;
9194     break;
9195   case 'C':
9196     if (default_collation_name == compiled_default_collation_name)
9197       default_collation_name= 0;
9198     break;
9199   case 'h':
9200     strmake(mysql_real_data_home,argument, sizeof(mysql_real_data_home)-1);
9201     /* Correct pointer set by my_getopt (for embedded library) */
9202     mysql_real_data_home_ptr= mysql_real_data_home;
9203     break;
9204   case 'u':
9205     if (!mysqld_user || !strcmp(mysqld_user, argument))
9206       mysqld_user= argument;
9207     else
9208       sql_print_warning("Ignoring user change to '%s' because the user was set to '%s' earlier on the command line\n", argument, mysqld_user);
9209     break;
9210   case 'L':
9211     WARN_DEPRECATED(NULL, "--language/-l", "'--lc-messages-dir'");
9212     /* Note:  fall-through */
9213   case OPT_LC_MESSAGES_DIRECTORY:
9214     strmake(lc_messages_dir, argument, sizeof(lc_messages_dir)-1);
9215     lc_messages_dir_ptr= lc_messages_dir;
9216     break;
9217   case OPT_BINLOG_FORMAT:
9218     binlog_format_used= true;
9219     break;
9220   case OPT_BINLOGGING_IMPOSSIBLE_MODE:
9221     WARN_DEPRECATED(NULL, "--binlogging_impossible_mode",
9222                     "'--binlog_error_action'");
9223     break;
9224   case OPT_SIMPLIFIED_BINLOG_GTID_RECOVERY:
9225     WARN_DEPRECATED(NULL, "--simplified_binlog_gtid_recovery",
9226                     "'--binlog_gtid_simple_recovery'");
9227     break;
9228 #include <sslopt-case.h>
9229 #ifndef EMBEDDED_LIBRARY
9230   case 'V':
9231     print_version();
9232     exit(0);
9233 #endif /*EMBEDDED_LIBRARY*/
9234   case 'W':
9235     if (!argument)
9236       log_warnings++;
9237     else if (argument == disabled_my_option)
9238       log_warnings= 0L;
9239     else
9240       log_warnings= atoi(argument);
9241     break;
9242   case 'T':
9243     test_flags= argument ? (uint) atoi(argument) : 0;
9244     opt_endinfo=1;
9245     break;
9246   case OPT_THREAD_CONCURRENCY:
9247     WARN_DEPRECATED_NO_REPLACEMENT(NULL, "THREAD_CONCURRENCY");
9248     break;
9249   case (int) OPT_ISAM_LOG:
9250     opt_myisam_log=1;
9251     break;
9252   case (int) OPT_BIN_LOG:
9253     opt_bin_log= MY_TEST(argument != disabled_my_option);
9254     break;
9255 #ifdef HAVE_REPLICATION
9256   case (int)OPT_REPLICATE_IGNORE_DB:
9257   {
9258     rpl_filter->add_ignore_db(argument);
9259     break;
9260   }
9261   case (int)OPT_REPLICATE_DO_DB:
9262   {
9263     rpl_filter->add_do_db(argument);
9264     break;
9265   }
9266   case (int)OPT_REPLICATE_REWRITE_DB:
9267   {
9268     char* key = argument,*p, *val;
9269 
9270     if (!(p= strstr(argument, "->")))
9271     {
9272       sql_print_error("Bad syntax in replicate-rewrite-db - missing '->'!\n");
9273       return 1;
9274     }
9275     val= p + 2;
9276     while(p > argument && my_isspace(mysqld_charset, p[-1]))
9277       p--;
9278     *p= 0;
9279     if (!*key)
9280     {
9281       sql_print_error("Bad syntax in replicate-rewrite-db - empty FROM db!\n");
9282       return 1;
9283     }
9284     while (*val && my_isspace(mysqld_charset, *val))
9285       val++;
9286     if (!*val)
9287     {
9288       sql_print_error("Bad syntax in replicate-rewrite-db - empty TO db!\n");
9289       return 1;
9290     }
9291 
9292     rpl_filter->add_db_rewrite(key, val);
9293     break;
9294   }
9295 
9296   case (int)OPT_BINLOG_IGNORE_DB:
9297   {
9298     binlog_filter->add_ignore_db(argument);
9299     break;
9300   }
9301   case (int)OPT_BINLOG_DO_DB:
9302   {
9303     binlog_filter->add_do_db(argument);
9304     break;
9305   }
9306   case (int)OPT_REPLICATE_DO_TABLE:
9307   {
9308     if (rpl_filter->add_do_table_array(argument))
9309     {
9310       sql_print_error("Could not add do table rule '%s'!\n", argument);
9311       return 1;
9312     }
9313     break;
9314   }
9315   case (int)OPT_REPLICATE_WILD_DO_TABLE:
9316   {
9317     if (rpl_filter->add_wild_do_table(argument))
9318     {
9319       sql_print_error("Could not add do table rule '%s'!\n", argument);
9320       return 1;
9321     }
9322     break;
9323   }
9324   case (int)OPT_REPLICATE_WILD_IGNORE_TABLE:
9325   {
9326     if (rpl_filter->add_wild_ignore_table(argument))
9327     {
9328       sql_print_error("Could not add ignore table rule '%s'!\n", argument);
9329       return 1;
9330     }
9331     break;
9332   }
9333   case (int)OPT_REPLICATE_IGNORE_TABLE:
9334   {
9335     if (rpl_filter->add_ignore_table_array(argument))
9336     {
9337       sql_print_error("Could not add ignore table rule '%s'!\n", argument);
9338       return 1;
9339     }
9340     break;
9341   }
9342 #endif /* HAVE_REPLICATION */
9343   case (int) OPT_MASTER_RETRY_COUNT:
9344     WARN_DEPRECATED(NULL, "--master-retry-count", "'CHANGE MASTER TO master_retry_count = <num>'");
9345     break;
9346   case (int) OPT_SKIP_NEW:
9347     opt_specialflag|= SPECIAL_NO_NEW_FUNC;
9348     delay_key_write_options= DELAY_KEY_WRITE_NONE;
9349     myisam_concurrent_insert=0;
9350     myisam_recover_options= HA_RECOVER_OFF;
9351     sp_automatic_privileges=0;
9352     my_use_symdir=0;
9353     ha_open_options&= ~(HA_OPEN_ABORT_IF_CRASHED | HA_OPEN_DELAY_KEY_WRITE);
9354 #ifdef HAVE_QUERY_CACHE
9355     query_cache_size=0;
9356 #endif
9357     break;
9358   case (int) OPT_SKIP_HOST_CACHE:
9359     opt_specialflag|= SPECIAL_NO_HOST_CACHE;
9360     break;
9361   case (int) OPT_SKIP_RESOLVE:
9362     opt_skip_name_resolve= 1;
9363     opt_specialflag|=SPECIAL_NO_RESOLVE;
9364     break;
9365   case (int) OPT_WANT_CORE:
9366     test_flags |= TEST_CORE_ON_SIGNAL;
9367     break;
9368   case (int) OPT_SKIP_STACK_TRACE:
9369     test_flags|=TEST_NO_STACKTRACE;
9370     break;
9371   case OPT_CONSOLE:
9372     if (opt_console)
9373       opt_error_log= 0;     // Force logs to stdout
9374     break;
9375   case OPT_BOOTSTRAP:
9376     opt_bootstrap=1;
9377     break;
9378   case OPT_SERVER_ID:
9379     server_id_supplied = 1;
9380     break;
9381   case OPT_LOWER_CASE_TABLE_NAMES:
9382     lower_case_table_names_used= 1;
9383     break;
9384 #ifdef WITH_WSREP
9385   case OPT_WSREP_START_POSITION:
9386     wsrep_start_position_init (argument);
9387     break;
9388   case OPT_WSREP_SST_AUTH:
9389     wsrep_sst_auth_init (argument);
9390     break;
9391 #endif
9392 #if defined(ENABLED_DEBUG_SYNC)
9393   case OPT_DEBUG_SYNC_TIMEOUT:
9394     /*
9395       Debug Sync Facility. See debug_sync.cc.
9396       Default timeout for WAIT_FOR action.
9397       Default value is zero (facility disabled).
9398       If option is given without an argument, supply a non-zero value.
9399     */
9400     if (!argument)
9401     {
9402       /* purecov: begin tested */
9403       opt_debug_sync_timeout= DEBUG_SYNC_DEFAULT_WAIT_TIMEOUT;
9404       /* purecov: end */
9405     }
9406     break;
9407 #endif /* defined(ENABLED_DEBUG_SYNC) */
9408   case OPT_ENGINE_CONDITION_PUSHDOWN:
9409     /*
9410       The last of --engine-condition-pushdown and --optimizer_switch on
9411       command line wins (see get_options().
9412     */
9413     if (global_system_variables.engine_condition_pushdown)
9414       global_system_variables.optimizer_switch|=
9415         OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN;
9416     else
9417       global_system_variables.optimizer_switch&=
9418         ~OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN;
9419     break;
9420   case OPT_LOG_ERROR:
9421     /*
9422       "No --log-error" == "write errors to stderr",
9423       "--log-error without argument" == "write errors to a file".
9424     */
9425     if (argument == NULL) /* no argument */
9426       log_error_file_ptr= const_cast<char*>("");
9427     break;
9428 
9429   case OPT_IGNORE_DB_DIRECTORY:
9430     if (*argument == 0)
9431       ignore_db_dirs_reset();
9432     else
9433     {
9434       if (push_ignored_db_dir(argument))
9435       {
9436         sql_print_error("Can't start server: "
9437                         "cannot process --ignore-db-dir=%.*s",
9438                         FN_REFLEN, argument);
9439         return 1;
9440       }
9441     }
9442     break;
9443 
9444 
9445   case OPT_PLUGIN_LOAD:
9446     free_list(opt_plugin_load_list_ptr);
9447     /* fall through */
9448   case OPT_PLUGIN_LOAD_ADD:
9449     opt_plugin_load_list_ptr->push_back(new i_string(argument));
9450     break;
9451   case OPT_DEFAULT_AUTH:
9452     if (set_default_auth_plugin(argument, strlen(argument)))
9453     {
9454       sql_print_error("Can't start server: "
9455                       "Invalid value for --default-authentication-plugin");
9456       return 1;
9457     }
9458     break;
9459   case OPT_SECURE_AUTH:
9460     if (opt_secure_auth == 0)
9461       WARN_DEPRECATED(NULL, "pre-4.1 password hash", "post-4.1 password hash");
9462     break;
9463   case OPT_PFS_INSTRUMENT:
9464     {
9465 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
9466 #ifndef EMBEDDED_LIBRARY
9467 
9468       /*
9469         Parse instrument name and value from argument string. Handle leading
9470         and trailing spaces. Also handle single quotes.
9471 
9472         Acceptable:
9473           performance_schema_instrument = ' foo/%/bar/  =  ON  '
9474           performance_schema_instrument = '%=OFF'
9475         Not acceptable:
9476           performance_schema_instrument = '' foo/%/bar = ON ''
9477           performance_schema_instrument = '%='OFF''
9478       */
9479       char *name= argument,*p= NULL, *val= NULL;
9480       my_bool quote= false; /* true if quote detected */
9481       my_bool error= true;  /* false if no errors detected */
9482       const int PFS_BUFFER_SIZE= 128;
9483       char orig_argument[PFS_BUFFER_SIZE+1];
9484       orig_argument[0]= 0;
9485 
9486       if (!argument)
9487         goto pfs_error;
9488 
9489       /* Save original argument string for error reporting */
9490       strncpy(orig_argument, argument, PFS_BUFFER_SIZE);
9491 
9492       /* Split instrument name and value at the equal sign */
9493       if (!(p= strchr(argument, '=')))
9494         goto pfs_error;
9495 
9496       /* Get option value */
9497       val= p + 1;
9498       if (!*val)
9499         goto pfs_error;
9500 
9501       /* Trim leading spaces and quote from the instrument name */
9502       while (*name && (my_isspace(mysqld_charset, *name) || (*name == '\'')))
9503       {
9504         /* One quote allowed */
9505         if (*name == '\'')
9506         {
9507           if (!quote)
9508             quote= true;
9509           else
9510             goto pfs_error;
9511         }
9512         name++;
9513       }
9514 
9515       /* Trim trailing spaces from instrument name */
9516       while ((p > name) && my_isspace(mysqld_charset, p[-1]))
9517         p--;
9518       *p= 0;
9519 
9520       /* Remove trailing slash from instrument name */
9521       if (p > name && (p[-1] == '/'))
9522         p[-1]= 0;
9523 
9524       if (!*name)
9525         goto pfs_error;
9526 
9527       /* Trim leading spaces from option value */
9528       while (*val && my_isspace(mysqld_charset, *val))
9529         val++;
9530 
9531       /* Trim trailing spaces and matching quote from value */
9532       p= val + strlen(val);
9533       while (p > val && (my_isspace(mysqld_charset, p[-1]) || p[-1] == '\''))
9534       {
9535         /* One matching quote allowed */
9536         if (p[-1] == '\'')
9537         {
9538           if (quote)
9539             quote= false;
9540           else
9541             goto pfs_error;
9542         }
9543         p--;
9544       }
9545 
9546       *p= 0;
9547 
9548       if (!*val)
9549         goto pfs_error;
9550 
9551       /* Add instrument name and value to array of configuration options */
9552       if (add_pfs_instr_to_array(name, val))
9553         goto pfs_error;
9554 
9555       error= false;
9556 
9557 pfs_error:
9558       if (error)
9559       {
9560         my_getopt_error_reporter(WARNING_LEVEL,
9561                                  "Invalid instrument name or value for "
9562                                  "performance_schema_instrument '%s'",
9563                                  orig_argument);
9564         return 0;
9565       }
9566 #endif /* EMBEDDED_LIBRARY */
9567 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
9568       break;
9569     }
9570   case OPT_THREAD_CACHE_SIZE:
9571     thread_cache_size_specified= true;
9572     break;
9573   case OPT_HOST_CACHE_SIZE:
9574     host_cache_size_specified= true;
9575     break;
9576   case OPT_TABLE_DEFINITION_CACHE:
9577     table_definition_cache_specified= true;
9578     break;
9579   case OPT_AVOID_TEMPORAL_UPGRADE:
9580     WARN_DEPRECATED_NO_REPLACEMENT(NULL, "avoid_temporal_upgrade");
9581     break;
9582   case OPT_SHOW_OLD_TEMPORALS:
9583     WARN_DEPRECATED_NO_REPLACEMENT(NULL, "show_old_temporals");
9584     break;
9585     case OPT_NAMED_PIPE_FULL_ACCESS_GROUP:
9586 #if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
9587       if (!is_valid_named_pipe_full_access_group(argument))
9588       {
9589         sql_print_error("Invalid value for named_pipe_full_access_group.");
9590         return 1;
9591       }
9592 #endif  /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */
9593       break;
9594   }
9595   return 0;
9596 }
9597 
9598 
9599 /** Handle arguments for multiple key caches. */
9600 
9601 C_MODE_START
9602 
9603 static void*
mysql_getopt_value(const char * keyname,uint key_length,const struct my_option * option,int * error)9604 mysql_getopt_value(const char *keyname, uint key_length,
9605        const struct my_option *option, int *error)
9606 {
9607   if (error)
9608     *error= 0;
9609   switch (option->id) {
9610   case OPT_KEY_BUFFER_SIZE:
9611   case OPT_KEY_CACHE_BLOCK_SIZE:
9612   case OPT_KEY_CACHE_DIVISION_LIMIT:
9613   case OPT_KEY_CACHE_AGE_THRESHOLD:
9614   {
9615     KEY_CACHE *key_cache;
9616     if (!(key_cache= get_or_create_key_cache(keyname, key_length)))
9617     {
9618       if (error)
9619         *error= EXIT_OUT_OF_MEMORY;
9620       return 0;
9621     }
9622     switch (option->id) {
9623     case OPT_KEY_BUFFER_SIZE:
9624       return &key_cache->param_buff_size;
9625     case OPT_KEY_CACHE_BLOCK_SIZE:
9626       return &key_cache->param_block_size;
9627     case OPT_KEY_CACHE_DIVISION_LIMIT:
9628       return &key_cache->param_division_limit;
9629     case OPT_KEY_CACHE_AGE_THRESHOLD:
9630       return &key_cache->param_age_threshold;
9631     }
9632   }
9633   }
9634   return option->value;
9635 }
9636 
option_error_reporter(enum loglevel level,const char * format,...)9637 static void option_error_reporter(enum loglevel level, const char *format, ...)
9638 {
9639   va_list args;
9640   va_start(args, format);
9641 
9642   /* Don't print warnings for --loose options during bootstrap */
9643   if (level == ERROR_LEVEL || !opt_bootstrap ||
9644       log_warnings)
9645   {
9646     vprint_msg_to_log(level, format, args);
9647   }
9648   va_end(args);
9649 }
9650 
9651 C_MODE_END
9652 
9653 /**
9654   Get server options from the command line,
9655   and perform related server initializations.
9656   @param [in, out] argc_ptr       command line options (count)
9657   @param [in, out] argv_ptr       command line options (values)
9658   @return 0 on success
9659 
9660   @todo
9661   - FIXME add EXIT_TOO_MANY_ARGUMENTS to "mysys_err.h" and return that code?
9662 */
get_options(int * argc_ptr,char *** argv_ptr)9663 static int get_options(int *argc_ptr, char ***argv_ptr)
9664 {
9665   int ho_error;
9666 
9667   my_getopt_register_get_addr(mysql_getopt_value);
9668   my_getopt_error_reporter= option_error_reporter;
9669 
9670   /* prepare all_options array */
9671   all_options.reserve(array_elements(my_long_options));
9672   for (my_option *opt= my_long_options;
9673        opt < my_long_options + array_elements(my_long_options) - 1;
9674        opt++)
9675   {
9676     all_options.push_back(*opt);
9677   }
9678   sys_var_add_options(&all_options, sys_var::PARSE_NORMAL);
9679   add_terminator(&all_options);
9680 
9681   /* Skip unknown options so that they may be processed later by plugins */
9682   my_getopt_skip_unknown= TRUE;
9683 
9684   if ((ho_error= handle_options(argc_ptr, argv_ptr, &all_options[0],
9685                                 mysqld_get_one_option)))
9686     return ho_error;
9687 
9688   if (!opt_help)
9689     vector<my_option>().swap(all_options);  // Deletes the vector contents.
9690 
9691   /* Add back the program name handle_options removes */
9692   (*argc_ptr)++;
9693   (*argv_ptr)--;
9694 
9695   /*
9696     Options have been parsed. Now some of them need additional special
9697     handling, like custom value checking, checking of incompatibilites
9698     between options, setting of multiple variables, etc.
9699     Do them here.
9700   */
9701 
9702   if ((opt_log_slow_admin_statements || opt_log_queries_not_using_indexes ||
9703        opt_log_slow_slave_statements) &&
9704       !opt_slow_log)
9705     sql_print_warning("options --log-slow-admin-statements, "
9706                       "--log-queries-not-using-indexes and "
9707                       "--log-slow-slave-statements have no effect if "
9708                       "--slow-query-log is not set");
9709   if (global_system_variables.net_buffer_length >
9710       global_system_variables.max_allowed_packet)
9711   {
9712     sql_print_warning("net_buffer_length (%lu) is set to be larger "
9713                       "than max_allowed_packet (%lu). Please rectify.",
9714                       global_system_variables.net_buffer_length,
9715                       global_system_variables.max_allowed_packet);
9716   }
9717 
9718   /*
9719     TIMESTAMP columns get implicit DEFAULT values when
9720     --explicit_defaults_for_timestamp is not set.
9721     This behavior is deprecated now.
9722   */
9723   if (!opt_help && !global_system_variables.explicit_defaults_for_timestamp)
9724     sql_print_warning("TIMESTAMP with implicit DEFAULT value is deprecated. "
9725                       "Please use --explicit_defaults_for_timestamp server "
9726                       "option (see documentation for more details).");
9727 
9728 
9729   if (log_error_file_ptr != disabled_my_option)
9730     opt_error_log= 1;
9731   else
9732     log_error_file_ptr= const_cast<char*>("");
9733 
9734   opt_init_connect.length=strlen(opt_init_connect.str);
9735   opt_init_slave.length=strlen(opt_init_slave.str);
9736 
9737   if (global_system_variables.low_priority_updates)
9738     thr_upgraded_concurrent_insert_lock= TL_WRITE_LOW_PRIORITY;
9739 
9740   if (ft_boolean_check_syntax_string((uchar*) ft_boolean_syntax))
9741   {
9742     sql_print_error("Invalid ft-boolean-syntax string: %s\n",
9743                     ft_boolean_syntax);
9744     return 1;
9745   }
9746 
9747   if (opt_disable_networking)
9748     mysqld_port= 0;
9749 
9750   if (opt_skip_show_db)
9751     opt_specialflag|= SPECIAL_SKIP_SHOW_DB;
9752 
9753   if (myisam_flush)
9754     flush_time= 0;
9755 
9756 #ifdef HAVE_REPLICATION
9757   if (opt_slave_skip_errors)
9758     add_slave_skip_errors(opt_slave_skip_errors);
9759 #endif
9760 
9761   if (global_system_variables.max_join_size == HA_POS_ERROR)
9762     global_system_variables.option_bits|= OPTION_BIG_SELECTS;
9763   else
9764     global_system_variables.option_bits&= ~OPTION_BIG_SELECTS;
9765 
9766 #ifdef WITH_WSREP
9767   if (global_system_variables.wsrep_causal_reads) {
9768       WSREP_WARN("option --wsrep-causal-reads is deprecated");
9769       if (!(global_system_variables.wsrep_sync_wait &
9770             WSREP_SYNC_WAIT_BEFORE_READ)) {
9771           WSREP_WARN("--wsrep-causal-reads=ON takes precedence over --wsrep-sync-wait=%u. "
9772                      "WSREP_SYNC_WAIT_BEFORE_READ is on",
9773                      global_system_variables.wsrep_sync_wait);
9774           global_system_variables.wsrep_sync_wait |= WSREP_SYNC_WAIT_BEFORE_READ;
9775       } else {
9776           // they are turned on both.
9777       }
9778   } else {
9779       if (global_system_variables.wsrep_sync_wait &
9780           WSREP_SYNC_WAIT_BEFORE_READ) {
9781           WSREP_WARN("--wsrep-sync-wait=%u takes precedence over --wsrep-causal-reads=OFF. "
9782                      "WSREP_SYNC_WAIT_BEFORE_READ is on",
9783                      global_system_variables.wsrep_sync_wait);
9784           global_system_variables.wsrep_causal_reads = 1;
9785       } else {
9786           // they are turned off both.
9787       }
9788   }
9789 #endif // WITH_WSREP
9790 
9791   // Synchronize @@global.autocommit on --autocommit
9792   const ulonglong turn_bit_on= opt_autocommit ?
9793     OPTION_AUTOCOMMIT : OPTION_NOT_AUTOCOMMIT;
9794   global_system_variables.option_bits=
9795     (global_system_variables.option_bits &
9796      ~(OPTION_NOT_AUTOCOMMIT | OPTION_AUTOCOMMIT)) | turn_bit_on;
9797 
9798   global_system_variables.sql_mode=
9799     expand_sql_mode(global_system_variables.sql_mode);
9800 #if defined(HAVE_BROKEN_REALPATH)
9801   my_use_symdir=0;
9802   my_disable_symlinks=1;
9803   have_symlink=SHOW_OPTION_NO;
9804 #else
9805   if (!my_use_symdir)
9806   {
9807     my_disable_symlinks=1;
9808     have_symlink=SHOW_OPTION_DISABLED;
9809   }
9810 #endif
9811   if (opt_debugging)
9812   {
9813     /* Allow break with SIGINT, no core or stack trace */
9814     test_flags|= TEST_SIGINT | TEST_NO_STACKTRACE;
9815     test_flags&= ~TEST_CORE_ON_SIGNAL;
9816   }
9817   /* Set global MyISAM variables from delay_key_write_options */
9818   fix_delay_key_write(0, 0, OPT_GLOBAL);
9819 
9820 #ifndef EMBEDDED_LIBRARY
9821   if (mysqld_chroot)
9822     set_root(mysqld_chroot);
9823 #else
9824   thread_handling = SCHEDULER_NO_THREADS;
9825   max_allowed_packet= global_system_variables.max_allowed_packet;
9826   net_buffer_length= global_system_variables.net_buffer_length;
9827 #endif
9828   if (fix_paths())
9829     return 1;
9830 
9831   /*
9832     Set some global variables from the global_system_variables
9833     In most cases the global variables will not be used
9834   */
9835   my_disable_locking= myisam_single_user= MY_TEST(opt_external_locking == 0);
9836   my_default_record_cache_size=global_system_variables.read_buff_size;
9837 
9838   global_system_variables.long_query_time= (ulonglong)
9839     (global_system_variables.long_query_time_double * 1e6);
9840 
9841   if (opt_short_log_format)
9842     opt_specialflag|= SPECIAL_SHORT_LOG_FORMAT;
9843 
9844   if (init_global_datetime_format(MYSQL_TIMESTAMP_DATE,
9845                                   &global_date_format) ||
9846       init_global_datetime_format(MYSQL_TIMESTAMP_TIME,
9847                                   &global_time_format) ||
9848       init_global_datetime_format(MYSQL_TIMESTAMP_DATETIME,
9849                                   &global_datetime_format))
9850     return 1;
9851 
9852 #ifdef EMBEDDED_LIBRARY
9853   one_thread_scheduler();
9854 #else
9855   if (thread_handling <= SCHEDULER_ONE_THREAD_PER_CONNECTION)
9856     one_thread_per_connection_scheduler();
9857   else                  /* thread_handling == SCHEDULER_NO_THREADS) */
9858     one_thread_scheduler();
9859 #endif
9860 
9861   global_system_variables.engine_condition_pushdown=
9862     MY_TEST(global_system_variables.optimizer_switch &
9863             OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN);
9864 
9865   opt_readonly= read_only;
9866 
9867   return 0;
9868 }
9869 
9870 
9871 /*
9872   Create version name for running mysqld version
9873   We automaticly add suffixes -debug, -embedded and -log to the version
9874   name to make the version more descriptive.
9875   (MYSQL_SERVER_SUFFIX is set by the compilation environment)
9876 */
9877 
set_server_version(void)9878 static void set_server_version(void)
9879 {
9880   char *end= strxmov(server_version, MYSQL_SERVER_VERSION,
9881                      MYSQL_SERVER_SUFFIX_STR, NullS);
9882 #ifdef EMBEDDED_LIBRARY
9883   end= strmov(end, "-embedded");
9884 #endif
9885 #ifndef DBUG_OFF
9886   if (!strstr(MYSQL_SERVER_SUFFIX_STR, "-debug"))
9887     end= strmov(end, "-debug");
9888 #endif
9889   if (opt_log || opt_slow_log || opt_bin_log)
9890     strmov(end, "-log");                        // This may slow down system
9891 }
9892 
9893 
get_relative_path(const char * path)9894 static char *get_relative_path(const char *path)
9895 {
9896   if (test_if_hard_path(path) &&
9897       is_prefix(path,DEFAULT_MYSQL_HOME) &&
9898       strcmp(DEFAULT_MYSQL_HOME,FN_ROOTDIR))
9899   {
9900     path+=(uint) strlen(DEFAULT_MYSQL_HOME);
9901     while (*path == FN_LIBCHAR || *path == FN_LIBCHAR2)
9902       path++;
9903   }
9904   return (char*) path;
9905 }
9906 
9907 
9908 /**
9909   Fix filename and replace extension where 'dir' is relative to
9910   mysql_real_data_home.
9911   @return
9912     1 if len(path) > FN_REFLEN
9913 */
9914 
9915 bool
fn_format_relative_to_data_home(char * to,const char * name,const char * dir,const char * extension)9916 fn_format_relative_to_data_home(char * to, const char *name,
9917         const char *dir, const char *extension)
9918 {
9919   char tmp_path[FN_REFLEN];
9920   if (!test_if_hard_path(dir))
9921   {
9922     strxnmov(tmp_path,sizeof(tmp_path)-1, mysql_real_data_home,
9923        dir, NullS);
9924     dir=tmp_path;
9925   }
9926   return !fn_format(to, name, dir, extension,
9927         MY_APPEND_EXT | MY_UNPACK_FILENAME | MY_SAFE_PATH);
9928 }
9929 
9930 
9931 /**
9932   Test a file path to determine if the path is compatible with the secure file
9933   path restriction.
9934 
9935   @param path null terminated character string
9936 
9937   @return
9938     @retval TRUE The path is secure
9939     @retval FALSE The path isn't secure
9940 */
9941 
is_secure_file_path(char * path)9942 bool is_secure_file_path(char *path)
9943 {
9944   char buff1[FN_REFLEN], buff2[FN_REFLEN];
9945   size_t opt_secure_file_priv_len;
9946   /*
9947     All paths are secure if opt_secure_file_priv is 0
9948   */
9949   if (!opt_secure_file_priv[0])
9950     return TRUE;
9951 
9952   opt_secure_file_priv_len= strlen(opt_secure_file_priv);
9953 
9954   if (strlen(path) >= FN_REFLEN)
9955     return FALSE;
9956 
9957   if (!my_strcasecmp(system_charset_info, opt_secure_file_priv, "NULL"))
9958     return FALSE;
9959 
9960   if (my_realpath(buff1, path, 0))
9961   {
9962     /*
9963       The supplied file path might have been a file and not a directory.
9964     */
9965     int length= (int)dirname_length(path);
9966     if (length >= FN_REFLEN)
9967       return FALSE;
9968     memcpy(buff2, path, length);
9969     buff2[length]= '\0';
9970     if (length == 0 || my_realpath(buff1, buff2, 0))
9971       return FALSE;
9972   }
9973   convert_dirname(buff2, buff1, NullS);
9974   if (!lower_case_file_system)
9975   {
9976     if (strncmp(opt_secure_file_priv, buff2, opt_secure_file_priv_len))
9977       return FALSE;
9978   }
9979   else
9980   {
9981     if (files_charset_info->coll->strnncoll(files_charset_info,
9982                                             (uchar *) buff2, strlen(buff2),
9983                                             (uchar *) opt_secure_file_priv,
9984                                             opt_secure_file_priv_len,
9985                                             TRUE))
9986       return FALSE;
9987   }
9988   return TRUE;
9989 }
9990 
9991 
9992 /**
9993   Test a file path whether it is same as mysql data directory path.
9994 
9995   @param path null terminated character string
9996 
9997   @return
9998     @retval TRUE The path is different from mysql data directory.
9999     @retval FALSE The path is same as mysql data directory.
10000 */
is_mysql_datadir_path(const char * path)10001 bool is_mysql_datadir_path(const char *path)
10002 {
10003   if (path == NULL)
10004     return false;
10005 
10006   char mysql_data_dir[FN_REFLEN], path_dir[FN_REFLEN];
10007   convert_dirname(path_dir, path, NullS);
10008   convert_dirname(mysql_data_dir, mysql_unpacked_real_data_home, NullS);
10009   size_t mysql_data_home_len= dirname_length(mysql_data_dir);
10010   size_t path_len = dirname_length(path_dir);
10011 
10012   if (path_len < mysql_data_home_len)
10013     return true;
10014 
10015   if (!lower_case_file_system)
10016     return(memcmp(mysql_data_dir, path_dir, mysql_data_home_len));
10017 
10018   return(files_charset_info->coll->strnncoll(files_charset_info,
10019                                             (uchar *) path_dir, path_len,
10020                                             (uchar *) mysql_data_dir,
10021                                             mysql_data_home_len,
10022                                             TRUE));
10023 
10024 }
10025 
10026 /**
10027   check_secure_file_priv_path : Checks path specified through
10028   --secure-file-priv and raises warning in following cases:
10029   1. If path is empty string or NULL and mysqld is not running
10030      with --bootstrap mode.
10031   2. If path can access data directory
10032   3. If path points to a directory which is accessible by
10033      all OS users (non-Windows build only)
10034 
10035   It throws error in following cases:
10036 
10037   1. If path normalization fails
10038   2. If it can not get stats of the directory
10039 
10040   @params NONE
10041 
10042   Assumptions :
10043   1. Data directory path has been normalized
10044   2. opt_secure_file_priv has been normalized unless it is set
10045      to "NULL".
10046 
10047   @returns Status of validation
10048     @retval true : Validation is successful with/without warnings
10049     @retval false : Validation failed. Error is raised.
10050 */
10051 
check_secure_file_priv_path()10052 bool check_secure_file_priv_path()
10053 {
10054   char datadir_buffer[FN_REFLEN+1]={0};
10055   char plugindir_buffer[FN_REFLEN+1]={0};
10056   char whichdir[20]= {0};
10057   size_t opt_plugindir_len= 0;
10058   size_t opt_datadir_len= 0;
10059   size_t opt_secure_file_priv_len= 0;
10060   bool warn= false;
10061   bool case_insensitive_fs;
10062 #ifndef _WIN32
10063   MY_STAT dir_stat;
10064 #endif
10065 
10066   if (!opt_secure_file_priv[0])
10067   {
10068     if (opt_bootstrap)
10069     {
10070       /*
10071         Do not impose --secure-file-priv restriction
10072         in --bootstrap mode
10073       */
10074       sql_print_information("Ignoring --secure-file-priv value as server is "
10075                             "running with --bootstrap.");
10076     }
10077     else
10078     {
10079       sql_print_warning("Insecure configuration for --secure-file-priv: "
10080                         "Current value does not restrict location of generated "
10081                         "files. Consider setting it to a valid, "
10082                         "non-empty path.");
10083     }
10084     return true;
10085   }
10086 
10087   /*
10088     Setting --secure-file-priv to NULL would disable
10089     reading/writing from/to file
10090   */
10091   if(!my_strcasecmp(system_charset_info, opt_secure_file_priv, "NULL"))
10092   {
10093     sql_print_information("--secure-file-priv is set to NULL. "
10094                           "Operations related to importing and exporting "
10095                           "data are disabled");
10096     return true;
10097   }
10098 
10099   /*
10100     Check if --secure-file-priv can access data directory
10101   */
10102   opt_secure_file_priv_len= strlen(opt_secure_file_priv);
10103 
10104   /*
10105     Adds dir seperator at the end.
10106     This is required in subsequent comparison
10107   */
10108   convert_dirname(datadir_buffer, mysql_unpacked_real_data_home, NullS);
10109   opt_datadir_len= strlen(datadir_buffer);
10110 
10111   case_insensitive_fs=
10112     (test_if_case_insensitive(datadir_buffer) == 1);
10113 
10114   if (!case_insensitive_fs)
10115   {
10116     if (!strncmp(datadir_buffer, opt_secure_file_priv,
10117           opt_datadir_len < opt_secure_file_priv_len ?
10118           opt_datadir_len : opt_secure_file_priv_len))
10119     {
10120       warn= true;
10121       strcpy(whichdir, "Data directory");
10122     }
10123   }
10124   else
10125   {
10126     if (!files_charset_info->coll->strnncoll(files_charset_info,
10127           (uchar *) datadir_buffer,
10128           opt_datadir_len,
10129           (uchar *) opt_secure_file_priv,
10130           opt_secure_file_priv_len,
10131           TRUE))
10132     {
10133       warn= true;
10134       strcpy(whichdir, "Data directory");
10135     }
10136   }
10137 
10138   /*
10139     Don't bother comparing --secure-file-priv with --plugin-dir
10140     if we already have a match against --datadir or
10141     --plugin-dir is not pointing to a valid directory.
10142   */
10143   if (!warn && !my_realpath(plugindir_buffer, opt_plugin_dir, 0))
10144   {
10145     convert_dirname(plugindir_buffer, plugindir_buffer, NullS);
10146     opt_plugindir_len= strlen(plugindir_buffer);
10147 
10148     if (!case_insensitive_fs)
10149     {
10150       if (!strncmp(plugindir_buffer, opt_secure_file_priv,
10151           opt_plugindir_len < opt_secure_file_priv_len ?
10152           opt_plugindir_len : opt_secure_file_priv_len))
10153       {
10154         warn= true;
10155         strcpy(whichdir, "Plugin directory");
10156       }
10157     }
10158     else
10159     {
10160       if (!files_charset_info->coll->strnncoll(files_charset_info,
10161           (uchar *) plugindir_buffer,
10162           opt_plugindir_len,
10163           (uchar *) opt_secure_file_priv,
10164           opt_secure_file_priv_len,
10165           TRUE))
10166       {
10167         warn= true;
10168         strcpy(whichdir, "Plugin directory");
10169       }
10170     }
10171   }
10172 
10173 
10174   if (warn)
10175     sql_print_warning("Insecure configuration for --secure-file-priv: "
10176                       "%s is accessible through "
10177                       "--secure-file-priv. Consider choosing a different "
10178                       "directory.", whichdir);
10179 
10180 #ifndef _WIN32
10181   /*
10182      Check for --secure-file-priv directory's permission
10183   */
10184   if (!(my_stat(opt_secure_file_priv, &dir_stat, MYF(0))))
10185   {
10186     sql_print_error("Failed to get stat for directory pointed out "
10187                     "by --secure-file-priv");
10188     return false;
10189   }
10190 
10191   if (dir_stat.st_mode & S_IRWXO)
10192     sql_print_warning("Insecure configuration for --secure-file-priv: "
10193                       "Location is accessible to all OS users. "
10194                       "Consider choosing a different directory.");
10195 #endif
10196   return true;
10197 }
10198 
fix_paths(void)10199 static int fix_paths(void)
10200 {
10201   char buff[FN_REFLEN],*pos;
10202   bool secure_file_priv_nonempty= false;
10203   convert_dirname(mysql_home,mysql_home,NullS);
10204   /* Resolve symlinks to allow 'mysql_home' to be a relative symlink */
10205   my_realpath(mysql_home,mysql_home,MYF(0));
10206   /* Ensure that mysql_home ends in FN_LIBCHAR */
10207   pos=strend(mysql_home);
10208   if (pos[-1] != FN_LIBCHAR)
10209   {
10210     pos[0]= FN_LIBCHAR;
10211     pos[1]= 0;
10212   }
10213   convert_dirname(lc_messages_dir, lc_messages_dir, NullS);
10214   convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS);
10215   (void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir
10216   (void) my_load_path(mysql_real_data_home,mysql_real_data_home,mysql_home);
10217   (void) my_load_path(pidfile_name, pidfile_name_ptr, mysql_real_data_home);
10218 
10219   convert_dirname(opt_plugin_dir, opt_plugin_dir_ptr ? opt_plugin_dir_ptr :
10220                                   get_relative_path(PLUGINDIR), NullS);
10221   (void) my_load_path(opt_plugin_dir, opt_plugin_dir, mysql_home);
10222   opt_plugin_dir_ptr= opt_plugin_dir;
10223 
10224   my_realpath(mysql_unpacked_real_data_home, mysql_real_data_home, MYF(0));
10225   mysql_unpacked_real_data_home_len=
10226     (int) strlen(mysql_unpacked_real_data_home);
10227   if (mysql_unpacked_real_data_home[mysql_unpacked_real_data_home_len-1] == FN_LIBCHAR)
10228     --mysql_unpacked_real_data_home_len;
10229 
10230   char *sharedir=get_relative_path(SHAREDIR);
10231   if (test_if_hard_path(sharedir))
10232     strmake(buff,sharedir,sizeof(buff)-1);    /* purecov: tested */
10233   else
10234     strxnmov(buff,sizeof(buff)-1,mysql_home,sharedir,NullS);
10235   convert_dirname(buff,buff,NullS);
10236   (void) my_load_path(lc_messages_dir, lc_messages_dir, buff);
10237 
10238   /* If --character-sets-dir isn't given, use shared library dir */
10239   if (charsets_dir)
10240     strmake(mysql_charsets_dir, charsets_dir, sizeof(mysql_charsets_dir)-1);
10241   else
10242     strxnmov(mysql_charsets_dir, sizeof(mysql_charsets_dir)-1, buff,
10243        CHARSET_DIR, NullS);
10244   (void) my_load_path(mysql_charsets_dir, mysql_charsets_dir, buff);
10245   convert_dirname(mysql_charsets_dir, mysql_charsets_dir, NullS);
10246   charsets_dir=mysql_charsets_dir;
10247 
10248   if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir))
10249     return 1;
10250   if (!opt_mysql_tmpdir)
10251     opt_mysql_tmpdir= mysql_tmpdir;
10252 #ifdef HAVE_REPLICATION
10253   if (!slave_load_tmpdir)
10254     slave_load_tmpdir= mysql_tmpdir;
10255 #endif /* HAVE_REPLICATION */
10256   /*
10257     Convert the secure-file-priv option to system format, allowing
10258     a quick strcmp to check if read or write is in an allowed dir
10259   */
10260   if (opt_bootstrap)
10261     opt_secure_file_priv= EMPTY_STR.str;
10262   secure_file_priv_nonempty= opt_secure_file_priv[0] ? true : false;
10263 
10264   if (secure_file_priv_nonempty && strlen(opt_secure_file_priv) > FN_REFLEN)
10265   {
10266     sql_print_warning("Value for --secure-file-priv is longer than maximum "
10267                       "limit of %d", FN_REFLEN-1);
10268     return 1;
10269   }
10270 
10271   memset(buff, 0, sizeof(buff));
10272   if (secure_file_priv_nonempty &&
10273       my_strcasecmp(system_charset_info, opt_secure_file_priv, "NULL"))
10274   {
10275     int retval= my_realpath(buff, opt_secure_file_priv, MYF(MY_WME));
10276     if (!retval)
10277     {
10278       convert_dirname(secure_file_real_path, buff, NullS);
10279 #ifdef WIN32
10280       MY_DIR *dir= my_dir(secure_file_real_path, MYF(MY_DONT_SORT+MY_WME));
10281       if (!dir)
10282       {
10283         retval= 1;
10284       }
10285       else
10286       {
10287         my_dirend(dir);
10288       }
10289 #endif
10290     }
10291 
10292     if (retval)
10293     {
10294       char err_buffer[FN_REFLEN];
10295       my_snprintf(err_buffer, FN_REFLEN-1,
10296                   "Failed to access directory for --secure-file-priv."
10297                   " Please make sure that directory exists and is "
10298                   "accessible by MySQL Server. Supplied value : %s",
10299                   opt_secure_file_priv);
10300       err_buffer[FN_REFLEN-1]='\0';
10301       sql_print_error("%s", err_buffer);
10302       return 1;
10303     }
10304     opt_secure_file_priv= secure_file_real_path;
10305   }
10306 
10307   if (!check_secure_file_priv_path())
10308     return 1;
10309 
10310   return 0;
10311 }
10312 
10313 /**
10314   Check if file system used for databases is case insensitive.
10315 
10316   @param dir_name     Directory to test
10317 
10318   @retval
10319     -1  Don't know (Test failed)
10320   @retval
10321     0   File system is case sensitive
10322   @retval
10323     1   File system is case insensitive
10324 */
10325 
test_if_case_insensitive(const char * dir_name)10326 static int test_if_case_insensitive(const char *dir_name)
10327 {
10328   int result= 0;
10329   File file;
10330   char buff[FN_REFLEN], buff2[FN_REFLEN];
10331   MY_STAT stat_info;
10332   DBUG_ENTER("test_if_case_insensitive");
10333 
10334   fn_format(buff, glob_hostname, dir_name, ".lower-test",
10335       MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR);
10336   fn_format(buff2, glob_hostname, dir_name, ".LOWER-TEST",
10337       MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR);
10338   mysql_file_delete(key_file_casetest, buff2, MYF(0));
10339   if ((file= mysql_file_create(key_file_casetest,
10340                                buff, 0666, O_RDWR, MYF(0))) < 0)
10341   {
10342     sql_print_warning("Can't create test file %s", buff);
10343     DBUG_RETURN(-1);
10344   }
10345   mysql_file_close(file, MYF(0));
10346   if (mysql_file_stat(key_file_casetest, buff2, &stat_info, MYF(0)))
10347     result= 1;          // Can access file
10348   mysql_file_delete(key_file_casetest, buff, MYF(MY_WME));
10349   DBUG_PRINT("exit", ("result: %d", result));
10350   DBUG_RETURN(result);
10351 }
10352 
10353 
10354 #ifndef EMBEDDED_LIBRARY
10355 
10356 /**
10357   Create file to store pid number.
10358 */
create_pid_file()10359 static void create_pid_file()
10360 {
10361   File file;
10362   bool check_parent_path= 1, is_path_accessible= 1;
10363   char pid_filepath[FN_REFLEN], *pos= NULL;
10364   /* Copy pid file name to get pid file path */
10365   strcpy(pid_filepath, pidfile_name);
10366 
10367   /* Iterate through the entire path to check if even one of the sub-dirs
10368      is world-writable */
10369   while (check_parent_path && (pos= strrchr(pid_filepath, FN_LIBCHAR))
10370          && (pos != pid_filepath)) /* shouldn't check root */
10371   {
10372     *pos= '\0';  /* Trim the inner-most dir */
10373     switch (is_file_or_dir_world_writable(pid_filepath))
10374     {
10375       case -2:
10376         is_path_accessible= 0;
10377         break;
10378       case -1:
10379         sql_perror("Can't start server: can't check PID filepath");
10380         exit(1);
10381       case 1:
10382         sql_print_warning("Insecure configuration for --pid-file: Location "
10383                           "'%s' in the path is accessible to all OS users. "
10384                           "Consider choosing a different directory.",
10385                           pid_filepath);
10386         check_parent_path= 0;
10387         break;
10388       case 0:
10389         continue; /* Keep checking the parent dir */
10390     }
10391   }
10392   if(!is_path_accessible)
10393   {
10394     sql_print_warning("Few location(s) are inaccessible while checking PID filepath.");
10395   }
10396   if ((file= mysql_file_create(key_file_pid, pidfile_name, 0664,
10397                                O_WRONLY | O_TRUNC, MYF(MY_WME))) >= 0)
10398   {
10399     char buff[MAX_BIGINT_WIDTH + 1], *end;
10400     end= int10_to_str((long) getpid(), buff, 10);
10401     *end++= '\n';
10402     if (!mysql_file_write(file, (uchar*) buff, (uint) (end-buff),
10403                           MYF(MY_WME | MY_NABP)))
10404     {
10405       mysql_file_close(file, MYF(0));
10406       pid_file_created= true;
10407       return;
10408     }
10409     mysql_file_close(file, MYF(0));
10410   }
10411   sql_perror("Can't start server: can't create PID file");
10412   exit(1);
10413 }
10414 #endif /* EMBEDDED_LIBRARY */
10415 
10416 
10417 /**
10418   Remove the process' pid file.
10419 
10420   @param  flags  file operation flags
10421 */
10422 
delete_pid_file(myf flags)10423 static void delete_pid_file(myf flags)
10424 {
10425 #ifndef EMBEDDED_LIBRARY
10426   File file;
10427   if (opt_bootstrap ||
10428       !pid_file_created ||
10429       !(file= mysql_file_open(key_file_pid, pidfile_name,
10430                               O_RDONLY, flags)))
10431     return;
10432 
10433   /* Make sure that the pid file was created by the same process. */
10434   uchar buff[MAX_BIGINT_WIDTH + 1];
10435   size_t error= mysql_file_read(file, buff, sizeof(buff), flags);
10436   mysql_file_close(file, flags);
10437   buff[sizeof(buff) - 1]= '\0';
10438   if (error != MY_FILE_ERROR &&
10439       atol((char *) buff) == (long) getpid())
10440   {
10441     mysql_file_delete(key_file_pid, pidfile_name, flags);
10442     pid_file_created= false;
10443   }
10444 #endif /* EMBEDDED_LIBRARY */
10445   return;
10446 }
10447 
10448 
10449 /** Clear most status variables. */
refresh_status(THD * thd)10450 void refresh_status(THD *thd)
10451 {
10452   mysql_mutex_lock(&LOCK_status);
10453 
10454   /* Add thread's status variabes to global status */
10455   add_to_status(&global_status_var, &thd->status_var);
10456 
10457   /* Reset thread's status variables */
10458   memset(&thd->status_var, 0, sizeof(thd->status_var));
10459 
10460   /* Reset some global variables */
10461   reset_status_vars();
10462 #ifdef WITH_WSREP
10463   wsrep->stats_reset(wsrep);
10464 #endif /* WITH_WSREP */
10465 
10466   /* Reset the counters of all key caches (default and named). */
10467   process_key_caches(reset_key_cache_counters);
10468   flush_status_time= time((time_t*) 0);
10469   mysql_mutex_unlock(&LOCK_status);
10470 
10471   /*
10472     Set max_used_connections to the number of currently open
10473     connections.  Lock LOCK_thread_count out of LOCK_status to avoid
10474     deadlocks.  Status reset becomes not atomic, but status data is
10475     not exact anyway.
10476   */
10477   mysql_mutex_lock(&LOCK_thread_count);
10478   max_used_connections= get_thread_count() - delayed_insert_threads;
10479   mysql_mutex_unlock(&LOCK_thread_count);
10480 }
10481 
10482 
10483 /*****************************************************************************
10484   Instantiate variables for missing storage engines
10485   This section should go away soon
10486 *****************************************************************************/
10487 
10488 #ifdef HAVE_PSI_INTERFACE
10489 #ifdef HAVE_MMAP
10490 PSI_mutex_key key_PAGE_lock, key_LOCK_sync, key_LOCK_active, key_LOCK_pool;
10491 #endif /* HAVE_MMAP */
10492 
10493 #ifdef HAVE_OPENSSL
10494 PSI_mutex_key key_LOCK_des_key_file;
10495 #endif /* HAVE_OPENSSL */
10496 
10497 PSI_mutex_key key_BINLOG_LOCK_commit;
10498 PSI_mutex_key key_BINLOG_LOCK_commit_queue;
10499 PSI_mutex_key key_BINLOG_LOCK_done;
10500 PSI_mutex_key key_BINLOG_LOCK_flush_queue;
10501 PSI_mutex_key key_BINLOG_LOCK_index;
10502 PSI_mutex_key key_BINLOG_LOCK_log;
10503 PSI_mutex_key key_BINLOG_LOCK_sync;
10504 PSI_mutex_key key_BINLOG_LOCK_sync_queue;
10505 PSI_mutex_key key_BINLOG_LOCK_xids;
10506 PSI_mutex_key
10507   key_delayed_insert_mutex, key_hash_filo_lock, key_LOCK_active_mi,
10508   key_LOCK_connection_count, key_LOCK_crypt, key_LOCK_delayed_create,
10509   key_LOCK_delayed_insert, key_LOCK_delayed_status, key_LOCK_error_log,
10510   key_LOCK_gdl, key_LOCK_global_system_variables,
10511   key_LOCK_manager,
10512   key_LOCK_prepared_stmt_count,
10513   key_LOCK_sql_slave_skip_counter,
10514   key_LOCK_slave_net_timeout,
10515   key_LOCK_server_started, key_LOCK_status,
10516   key_LOCK_system_variables_hash, key_LOCK_table_share, key_LOCK_thd_data,
10517   key_LOCK_user_conn, key_LOCK_uuid_generator, key_LOG_LOCK_log,
10518   key_master_info_data_lock, key_master_info_run_lock,
10519   key_master_info_sleep_lock,
10520   key_mutex_slave_reporting_capability_err_lock, key_relay_log_info_data_lock,
10521   key_relay_log_info_sleep_lock,
10522   key_relay_log_info_log_space_lock, key_relay_log_info_run_lock,
10523   key_mutex_slave_parallel_pend_jobs, key_mutex_mts_temp_tables_lock,
10524   key_mutex_slave_parallel_worker_count,
10525   key_mutex_slave_parallel_worker,
10526   key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data,
10527   key_LOCK_error_messages, key_LOG_INFO_lock, key_LOCK_thread_count,
10528   key_LOCK_log_throttle_qni;
10529 #ifdef WITH_WSREP
10530 PSI_mutex_key key_LOCK_wsrep_rollback, key_LOCK_wsrep_thd,
10531   key_LOCK_wsrep_replaying, key_LOCK_wsrep_ready, key_LOCK_wsrep_sst,
10532   key_LOCK_wsrep_sst_thread, key_LOCK_wsrep_sst_init,
10533   key_LOCK_wsrep_slave_threads, key_LOCK_wsrep_desync;
10534 #endif
10535 PSI_mutex_key key_LOCK_thd_remove;
10536 PSI_mutex_key key_RELAYLOG_LOCK_commit;
10537 PSI_mutex_key key_RELAYLOG_LOCK_commit_queue;
10538 PSI_mutex_key key_RELAYLOG_LOCK_done;
10539 PSI_mutex_key key_RELAYLOG_LOCK_flush_queue;
10540 PSI_mutex_key key_RELAYLOG_LOCK_index;
10541 PSI_mutex_key key_RELAYLOG_LOCK_log;
10542 PSI_mutex_key key_RELAYLOG_LOCK_sync;
10543 PSI_mutex_key key_RELAYLOG_LOCK_sync_queue;
10544 PSI_mutex_key key_RELAYLOG_LOCK_xids;
10545 PSI_mutex_key key_LOCK_sql_rand;
10546 PSI_mutex_key key_gtid_ensure_index_mutex;
10547 PSI_mutex_key key_LOCK_thread_created;
10548 
10549 static PSI_mutex_info all_server_mutexes[]=
10550 {
10551 #ifdef HAVE_MMAP
10552   { &key_PAGE_lock, "PAGE::lock", 0},
10553   { &key_LOCK_sync, "TC_LOG_MMAP::LOCK_sync", 0},
10554   { &key_LOCK_active, "TC_LOG_MMAP::LOCK_active", 0},
10555   { &key_LOCK_pool, "TC_LOG_MMAP::LOCK_pool", 0},
10556 #endif /* HAVE_MMAP */
10557 
10558 #ifdef HAVE_OPENSSL
10559   { &key_LOCK_des_key_file, "LOCK_des_key_file", PSI_FLAG_GLOBAL},
10560 #endif /* HAVE_OPENSSL */
10561 
10562   { &key_BINLOG_LOCK_commit, "MYSQL_BIN_LOG::LOCK_commit", 0 },
10563   { &key_BINLOG_LOCK_commit_queue, "MYSQL_BIN_LOG::LOCK_commit_queue", 0 },
10564   { &key_BINLOG_LOCK_done, "MYSQL_BIN_LOG::LOCK_done", 0 },
10565   { &key_BINLOG_LOCK_flush_queue, "MYSQL_BIN_LOG::LOCK_flush_queue", 0 },
10566   { &key_BINLOG_LOCK_index, "MYSQL_BIN_LOG::LOCK_index", 0},
10567   { &key_BINLOG_LOCK_log, "MYSQL_BIN_LOG::LOCK_log", 0},
10568   { &key_BINLOG_LOCK_sync, "MYSQL_BIN_LOG::LOCK_sync", 0},
10569   { &key_BINLOG_LOCK_sync_queue, "MYSQL_BIN_LOG::LOCK_sync_queue", 0 },
10570   { &key_BINLOG_LOCK_xids, "MYSQL_BIN_LOG::LOCK_xids", 0 },
10571   { &key_RELAYLOG_LOCK_commit, "MYSQL_RELAY_LOG::LOCK_commit", 0},
10572   { &key_RELAYLOG_LOCK_commit_queue, "MYSQL_RELAY_LOG::LOCK_commit_queue", 0 },
10573   { &key_RELAYLOG_LOCK_done, "MYSQL_RELAY_LOG::LOCK_done", 0 },
10574   { &key_RELAYLOG_LOCK_flush_queue, "MYSQL_RELAY_LOG::LOCK_flush_queue", 0 },
10575   { &key_RELAYLOG_LOCK_index, "MYSQL_RELAY_LOG::LOCK_index", 0},
10576   { &key_RELAYLOG_LOCK_log, "MYSQL_RELAY_LOG::LOCK_log", 0},
10577   { &key_RELAYLOG_LOCK_sync, "MYSQL_RELAY_LOG::LOCK_sync", 0},
10578   { &key_RELAYLOG_LOCK_sync_queue, "MYSQL_RELAY_LOG::LOCK_sync_queue", 0 },
10579   { &key_RELAYLOG_LOCK_xids, "MYSQL_RELAY_LOG::LOCK_xids", 0},
10580   { &key_delayed_insert_mutex, "Delayed_insert::mutex", 0},
10581   { &key_hash_filo_lock, "hash_filo::lock", 0},
10582   { &key_LOCK_active_mi, "LOCK_active_mi", PSI_FLAG_GLOBAL},
10583   { &key_LOCK_connection_count, "LOCK_connection_count", PSI_FLAG_GLOBAL},
10584   { &key_LOCK_crypt, "LOCK_crypt", PSI_FLAG_GLOBAL},
10585   { &key_LOCK_delayed_create, "LOCK_delayed_create", PSI_FLAG_GLOBAL},
10586   { &key_LOCK_delayed_insert, "LOCK_delayed_insert", PSI_FLAG_GLOBAL},
10587   { &key_LOCK_delayed_status, "LOCK_delayed_status", PSI_FLAG_GLOBAL},
10588   { &key_LOCK_error_log, "LOCK_error_log", PSI_FLAG_GLOBAL},
10589   { &key_LOCK_gdl, "LOCK_gdl", PSI_FLAG_GLOBAL},
10590   { &key_LOCK_global_system_variables, "LOCK_global_system_variables", PSI_FLAG_GLOBAL},
10591   { &key_LOCK_manager, "LOCK_manager", PSI_FLAG_GLOBAL},
10592   { &key_LOCK_prepared_stmt_count, "LOCK_prepared_stmt_count", PSI_FLAG_GLOBAL},
10593   { &key_LOCK_sql_slave_skip_counter, "LOCK_sql_slave_skip_counter", PSI_FLAG_GLOBAL},
10594   { &key_LOCK_slave_net_timeout, "LOCK_slave_net_timeout", PSI_FLAG_GLOBAL},
10595   { &key_LOCK_server_started, "LOCK_server_started", PSI_FLAG_GLOBAL},
10596   { &key_LOCK_status, "LOCK_status", PSI_FLAG_GLOBAL},
10597   { &key_LOCK_system_variables_hash, "LOCK_system_variables_hash", PSI_FLAG_GLOBAL},
10598   { &key_LOCK_table_share, "LOCK_table_share", PSI_FLAG_GLOBAL},
10599   { &key_LOCK_thd_data, "THD::LOCK_thd_data", 0},
10600   { &key_LOCK_user_conn, "LOCK_user_conn", PSI_FLAG_GLOBAL},
10601   { &key_LOCK_uuid_generator, "LOCK_uuid_generator", PSI_FLAG_GLOBAL},
10602   { &key_LOCK_sql_rand, "LOCK_sql_rand", PSI_FLAG_GLOBAL},
10603   { &key_LOG_LOCK_log, "LOG::LOCK_log", 0},
10604   { &key_master_info_data_lock, "Master_info::data_lock", 0},
10605   { &key_master_info_run_lock, "Master_info::run_lock", 0},
10606   { &key_master_info_sleep_lock, "Master_info::sleep_lock", 0},
10607   { &key_mutex_slave_reporting_capability_err_lock, "Slave_reporting_capability::err_lock", 0},
10608   { &key_relay_log_info_data_lock, "Relay_log_info::data_lock", 0},
10609   { &key_relay_log_info_sleep_lock, "Relay_log_info::sleep_lock", 0},
10610   { &key_relay_log_info_log_space_lock, "Relay_log_info::log_space_lock", 0},
10611   { &key_relay_log_info_run_lock, "Relay_log_info::run_lock", 0},
10612   { &key_mutex_slave_parallel_pend_jobs, "Relay_log_info::pending_jobs_lock", 0},
10613   { &key_mutex_slave_parallel_worker_count, "Relay_log_info::exit_count_lock", 0},
10614   { &key_mutex_mts_temp_tables_lock, "Relay_log_info::temp_tables_lock", 0},
10615   { &key_mutex_slave_parallel_worker, "Worker_info::jobs_lock", 0},
10616   { &key_structure_guard_mutex, "Query_cache::structure_guard_mutex", 0},
10617   { &key_TABLE_SHARE_LOCK_ha_data, "TABLE_SHARE::LOCK_ha_data", 0},
10618   { &key_LOCK_error_messages, "LOCK_error_messages", PSI_FLAG_GLOBAL},
10619   { &key_LOG_INFO_lock, "LOG_INFO::lock", 0},
10620   { &key_LOCK_thread_count, "LOCK_thread_count", PSI_FLAG_GLOBAL},
10621 #ifdef WITH_WSREP
10622   { &key_LOCK_wsrep_ready, "LOCK_wsrep_ready", PSI_FLAG_GLOBAL},
10623   { &key_LOCK_wsrep_sst, "LOCK_wsrep_sst", PSI_FLAG_GLOBAL},
10624   { &key_LOCK_wsrep_sst_thread, "wsrep_sst_thread", 0},
10625   { &key_LOCK_wsrep_sst_init, "LOCK_wsrep_sst_init", PSI_FLAG_GLOBAL},
10626   { &key_LOCK_wsrep_sst, "LOCK_wsrep_sst", PSI_FLAG_GLOBAL},
10627   { &key_LOCK_wsrep_rollback, "LOCK_wsrep_rollback", PSI_FLAG_GLOBAL},
10628   { &key_LOCK_wsrep_thd, "THD::LOCK_wsrep_thd", 0},
10629   { &key_LOCK_wsrep_replaying, "LOCK_wsrep_replaying", PSI_FLAG_GLOBAL},
10630   { &key_LOCK_wsrep_slave_threads, "LOCK_wsrep_slave_threads", PSI_FLAG_GLOBAL},
10631   { &key_LOCK_wsrep_desync, "LOCK_wsrep_desync", PSI_FLAG_GLOBAL},
10632 #endif
10633   { &key_LOCK_thd_remove, "LOCK_thd_remove", PSI_FLAG_GLOBAL},
10634   { &key_LOCK_log_throttle_qni, "LOCK_log_throttle_qni", PSI_FLAG_GLOBAL},
10635   { &key_gtid_ensure_index_mutex, "Gtid_state", PSI_FLAG_GLOBAL},
10636   { &key_LOCK_thread_created, "LOCK_thread_created", PSI_FLAG_GLOBAL }
10637 };
10638 
10639 PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger,
10640   key_rwlock_LOCK_sys_init_connect, key_rwlock_LOCK_sys_init_slave,
10641   key_rwlock_LOCK_system_variables_hash, key_rwlock_query_cache_query_lock,
10642   key_rwlock_global_sid_lock;
10643 
10644 PSI_rwlock_key key_rwlock_Trans_delegate_lock;
10645 PSI_rwlock_key key_rwlock_Binlog_storage_delegate_lock;
10646 #ifdef HAVE_REPLICATION
10647 PSI_rwlock_key key_rwlock_Binlog_transmit_delegate_lock;
10648 PSI_rwlock_key key_rwlock_Binlog_relay_IO_delegate_lock;
10649 #endif
10650 
10651 static PSI_rwlock_info all_server_rwlocks[]=
10652 {
10653 #if defined (HAVE_OPENSSL)
10654   { &key_rwlock_openssl, "CRYPTO_dynlock_value::lock", 0},
10655 #endif
10656 #ifdef HAVE_REPLICATION
10657   { &key_rwlock_Binlog_transmit_delegate_lock, "Binlog_transmit_delegate::lock", PSI_FLAG_GLOBAL},
10658   { &key_rwlock_Binlog_relay_IO_delegate_lock, "Binlog_relay_IO_delegate::lock", PSI_FLAG_GLOBAL},
10659 #endif
10660   { &key_rwlock_LOCK_grant, "LOCK_grant", PSI_FLAG_GLOBAL},
10661   { &key_rwlock_LOCK_logger, "LOGGER::LOCK_logger", 0},
10662   { &key_rwlock_LOCK_sys_init_connect, "LOCK_sys_init_connect", PSI_FLAG_GLOBAL},
10663   { &key_rwlock_LOCK_sys_init_slave, "LOCK_sys_init_slave", PSI_FLAG_GLOBAL},
10664   { &key_rwlock_LOCK_system_variables_hash, "LOCK_system_variables_hash", PSI_FLAG_GLOBAL},
10665   { &key_rwlock_query_cache_query_lock, "Query_cache_query::lock", 0},
10666   { &key_rwlock_global_sid_lock, "gtid_commit_rollback", PSI_FLAG_GLOBAL},
10667   { &key_rwlock_Trans_delegate_lock, "Trans_delegate::lock", PSI_FLAG_GLOBAL},
10668   { &key_rwlock_Binlog_storage_delegate_lock, "Binlog_storage_delegate::lock", PSI_FLAG_GLOBAL},
10669 #if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
10670   { &key_rwlock_LOCK_named_pipe_full_access_group, "LOCK_named_pipe_full_access_group", PSI_FLAG_GLOBAL},
10671 #endif /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */
10672 };
10673 
10674 #ifdef HAVE_MMAP
10675 PSI_cond_key key_PAGE_cond, key_COND_active, key_COND_pool;
10676 #endif /* HAVE_MMAP */
10677 
10678 PSI_cond_key key_BINLOG_update_cond,
10679   key_COND_cache_status_changed, key_COND_manager,
10680   key_COND_server_started,
10681   key_delayed_insert_cond, key_delayed_insert_cond_client,
10682   key_item_func_sleep_cond, key_master_info_data_cond,
10683   key_master_info_start_cond, key_master_info_stop_cond,
10684   key_master_info_sleep_cond,
10685   key_relay_log_info_data_cond, key_relay_log_info_log_space_cond,
10686   key_relay_log_info_start_cond, key_relay_log_info_stop_cond,
10687   key_relay_log_info_sleep_cond, key_cond_slave_parallel_pend_jobs,
10688   key_cond_slave_parallel_worker,
10689   key_TABLE_SHARE_cond, key_user_level_lock_cond,
10690   key_COND_thread_count, key_COND_thread_cache, key_COND_flush_thread_cache,
10691   key_COND_connection_count;
10692 #ifdef WITH_WSREP
10693 PSI_cond_key key_COND_wsrep_rollback, key_COND_wsrep_thd,
10694   key_COND_wsrep_replaying, key_COND_wsrep_ready, key_COND_wsrep_sst,
10695   key_COND_wsrep_sst_init, key_COND_wsrep_sst_thread;
10696 
10697 #endif /* WITH_WSREP */
10698 PSI_cond_key key_RELAYLOG_update_cond;
10699 PSI_cond_key key_BINLOG_COND_done;
10700 PSI_cond_key key_RELAYLOG_COND_done;
10701 PSI_cond_key key_BINLOG_prep_xids_cond;
10702 PSI_cond_key key_RELAYLOG_prep_xids_cond;
10703 PSI_cond_key key_gtid_ensure_index_cond;
10704 
10705 static PSI_cond_info all_server_conds[]=
10706 {
10707 #if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
10708   { &key_COND_handler_count, "COND_handler_count", PSI_FLAG_GLOBAL},
10709 #endif /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */
10710 #ifdef HAVE_MMAP
10711   { &key_PAGE_cond, "PAGE::cond", 0},
10712   { &key_COND_active, "TC_LOG_MMAP::COND_active", 0},
10713   { &key_COND_pool, "TC_LOG_MMAP::COND_pool", 0},
10714 #endif /* HAVE_MMAP */
10715   { &key_BINLOG_COND_done, "MYSQL_BIN_LOG::COND_done", 0},
10716   { &key_BINLOG_update_cond, "MYSQL_BIN_LOG::update_cond", 0},
10717   { &key_BINLOG_prep_xids_cond, "MYSQL_BIN_LOG::prep_xids_cond", 0},
10718   { &key_RELAYLOG_COND_done, "MYSQL_RELAY_LOG::COND_done", 0},
10719   { &key_RELAYLOG_update_cond, "MYSQL_RELAY_LOG::update_cond", 0},
10720   { &key_RELAYLOG_prep_xids_cond, "MYSQL_RELAY_LOG::prep_xids_cond", 0},
10721   { &key_COND_cache_status_changed, "Query_cache::COND_cache_status_changed", 0},
10722   { &key_COND_manager, "COND_manager", PSI_FLAG_GLOBAL},
10723   { &key_COND_server_started, "COND_server_started", PSI_FLAG_GLOBAL},
10724   { &key_delayed_insert_cond, "Delayed_insert::cond", 0},
10725   { &key_delayed_insert_cond_client, "Delayed_insert::cond_client", 0},
10726   { &key_item_func_sleep_cond, "Item_func_sleep::cond", 0},
10727   { &key_master_info_data_cond, "Master_info::data_cond", 0},
10728   { &key_master_info_start_cond, "Master_info::start_cond", 0},
10729   { &key_master_info_stop_cond, "Master_info::stop_cond", 0},
10730   { &key_master_info_sleep_cond, "Master_info::sleep_cond", 0},
10731   { &key_relay_log_info_data_cond, "Relay_log_info::data_cond", 0},
10732   { &key_relay_log_info_log_space_cond, "Relay_log_info::log_space_cond", 0},
10733   { &key_relay_log_info_start_cond, "Relay_log_info::start_cond", 0},
10734   { &key_relay_log_info_stop_cond, "Relay_log_info::stop_cond", 0},
10735   { &key_relay_log_info_sleep_cond, "Relay_log_info::sleep_cond", 0},
10736   { &key_cond_slave_parallel_pend_jobs, "Relay_log_info::pending_jobs_cond", 0},
10737   { &key_cond_slave_parallel_worker, "Worker_info::jobs_cond", 0},
10738   { &key_TABLE_SHARE_cond, "TABLE_SHARE::cond", 0},
10739   { &key_user_level_lock_cond, "User_level_lock::cond", 0},
10740   { &key_COND_thread_count, "COND_thread_count", PSI_FLAG_GLOBAL},
10741   { &key_COND_thread_cache, "COND_thread_cache", PSI_FLAG_GLOBAL},
10742 #ifdef WITH_WSREP
10743   { &key_COND_wsrep_ready, "COND_wsrep_ready", PSI_FLAG_GLOBAL},
10744   { &key_COND_wsrep_sst, "COND_wsrep_sst", PSI_FLAG_GLOBAL},
10745   { &key_COND_wsrep_sst_init, "COND_wsrep_sst_init", PSI_FLAG_GLOBAL},
10746   { &key_COND_wsrep_sst_thread, "wsrep_sst_thread", 0},
10747   { &key_COND_wsrep_rollback, "COND_wsrep_rollback", PSI_FLAG_GLOBAL},
10748   { &key_COND_wsrep_thd, "THD::COND_wsrep_thd", 0},
10749   { &key_COND_wsrep_replaying, "COND_wsrep_replaying", PSI_FLAG_GLOBAL},
10750 #endif
10751   { &key_COND_flush_thread_cache, "COND_flush_thread_cache", PSI_FLAG_GLOBAL},
10752   { &key_gtid_ensure_index_cond, "Gtid_state", PSI_FLAG_GLOBAL},
10753   { &key_COND_connection_count, "COND_connection_count", PSI_FLAG_GLOBAL}
10754 };
10755 
10756 PSI_thread_key key_thread_bootstrap, key_thread_delayed_insert,
10757   key_thread_handle_manager, key_thread_main,
10758   key_thread_one_connection, key_thread_signal_hand;
10759 
10760 static PSI_thread_info all_server_threads[]=
10761 {
10762 #if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
10763   { &key_thread_handle_con_namedpipes, "con_named_pipes", PSI_FLAG_GLOBAL},
10764 #endif /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */
10765 
10766 #if defined(HAVE_SMEM) && !defined(EMBEDDED_LIBRARY)
10767   { &key_thread_handle_con_sharedmem, "con_shared_mem", PSI_FLAG_GLOBAL},
10768 #endif /* HAVE_SMEM && !EMBEDDED_LIBRARY */
10769 
10770 #if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
10771   { &key_thread_handle_con_sockets, "con_sockets", PSI_FLAG_GLOBAL},
10772 #endif /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */
10773 
10774 #ifdef __WIN__
10775   { &key_thread_handle_shutdown, "shutdown", PSI_FLAG_GLOBAL},
10776 #endif /* __WIN__ */
10777 
10778   { &key_thread_bootstrap, "bootstrap", PSI_FLAG_GLOBAL},
10779   { &key_thread_delayed_insert, "delayed_insert", 0},
10780   { &key_thread_handle_manager, "manager", PSI_FLAG_GLOBAL},
10781   { &key_thread_main, "main", PSI_FLAG_GLOBAL},
10782   { &key_thread_one_connection, "one_connection", 0},
10783   { &key_thread_signal_hand, "signal_handler", PSI_FLAG_GLOBAL}
10784 };
10785 
10786 #ifdef HAVE_MMAP
10787 PSI_file_key key_file_map;
10788 #endif /* HAVE_MMAP */
10789 
10790 PSI_file_key key_file_binlog, key_file_binlog_index, key_file_casetest,
10791   key_file_dbopt, key_file_des_key_file, key_file_ERRMSG, key_select_to_file,
10792   key_file_fileparser, key_file_frm, key_file_global_ddl_log, key_file_load,
10793   key_file_loadfile, key_file_log_event_data, key_file_log_event_info,
10794   key_file_master_info, key_file_misc, key_file_partition,
10795   key_file_pid, key_file_relay_log_info, key_file_send_file, key_file_tclog,
10796   key_file_trg, key_file_trn, key_file_init;
10797 PSI_file_key key_file_query_log, key_file_slow_log;
10798 PSI_file_key key_file_relaylog, key_file_relaylog_index;
10799 
10800 static PSI_file_info all_server_files[]=
10801 {
10802 #ifdef HAVE_MMAP
10803   { &key_file_map, "map", 0},
10804 #endif /* HAVE_MMAP */
10805   { &key_file_binlog, "binlog", 0},
10806   { &key_file_binlog_index, "binlog_index", 0},
10807   { &key_file_relaylog, "relaylog", 0},
10808   { &key_file_relaylog_index, "relaylog_index", 0},
10809   { &key_file_casetest, "casetest", 0},
10810   { &key_file_dbopt, "dbopt", 0},
10811   { &key_file_des_key_file, "des_key_file", 0},
10812   { &key_file_ERRMSG, "ERRMSG", 0},
10813   { &key_select_to_file, "select_to_file", 0},
10814   { &key_file_fileparser, "file_parser", 0},
10815   { &key_file_frm, "FRM", 0},
10816   { &key_file_global_ddl_log, "global_ddl_log", 0},
10817   { &key_file_load, "load", 0},
10818   { &key_file_loadfile, "LOAD_FILE", 0},
10819   { &key_file_log_event_data, "log_event_data", 0},
10820   { &key_file_log_event_info, "log_event_info", 0},
10821   { &key_file_master_info, "master_info", 0},
10822   { &key_file_misc, "misc", 0},
10823   { &key_file_partition, "partition", 0},
10824   { &key_file_pid, "pid", 0},
10825   { &key_file_query_log, "query_log", 0},
10826   { &key_file_relay_log_info, "relay_log_info", 0},
10827   { &key_file_send_file, "send_file", 0},
10828   { &key_file_slow_log, "slow_log", 0},
10829   { &key_file_tclog, "tclog", 0},
10830   { &key_file_trg, "trigger_name", 0},
10831   { &key_file_trn, "trigger", 0},
10832   { &key_file_init, "init", 0}
10833 };
10834 #endif /* HAVE_PSI_INTERFACE */
10835 
10836 PSI_stage_info stage_after_create= { 0, "After create", 0};
10837 PSI_stage_info stage_allocating_local_table= { 0, "allocating local table", 0};
10838 PSI_stage_info stage_alter_inplace_prepare= { 0, "preparing for alter table", 0};
10839 PSI_stage_info stage_alter_inplace= { 0, "altering table", 0};
10840 PSI_stage_info stage_alter_inplace_commit= { 0, "committing alter table to storage engine", 0};
10841 PSI_stage_info stage_changing_master= { 0, "Changing master", 0};
10842 PSI_stage_info stage_checking_master_version= { 0, "Checking master version", 0};
10843 PSI_stage_info stage_checking_permissions= { 0, "checking permissions", 0};
10844 PSI_stage_info stage_checking_privileges_on_cached_query= { 0, "checking privileges on cached query", 0};
10845 PSI_stage_info stage_checking_query_cache_for_query= { 0, "checking query cache for query", 0};
10846 PSI_stage_info stage_cleaning_up= { 0, "cleaning up", 0};
10847 PSI_stage_info stage_closing_tables= { 0, "closing tables", 0};
10848 PSI_stage_info stage_connecting_to_master= { 0, "Connecting to master", 0};
10849 PSI_stage_info stage_converting_heap_to_myisam= { 0, "converting HEAP to MyISAM", 0};
10850 PSI_stage_info stage_copying_to_group_table= { 0, "Copying to group table", 0};
10851 PSI_stage_info stage_copying_to_tmp_table= { 0, "Copying to tmp table", 0};
10852 PSI_stage_info stage_copy_to_tmp_table= { 0, "copy to tmp table", 0};
10853 PSI_stage_info stage_creating_delayed_handler= { 0, "Creating delayed handler", 0};
10854 PSI_stage_info stage_creating_sort_index= { 0, "Creating sort index", 0};
10855 PSI_stage_info stage_creating_table= { 0, "creating table", 0};
10856 PSI_stage_info stage_creating_tmp_table= { 0, "Creating tmp table", 0};
10857 PSI_stage_info stage_deleting_from_main_table= { 0, "deleting from main table", 0};
10858 PSI_stage_info stage_deleting_from_reference_tables= { 0, "deleting from reference tables", 0};
10859 PSI_stage_info stage_discard_or_import_tablespace= { 0, "discard_or_import_tablespace", 0};
10860 PSI_stage_info stage_end= { 0, "end", 0};
10861 PSI_stage_info stage_executing= { 0, "executing", 0};
10862 PSI_stage_info stage_execution_of_init_command= { 0, "Execution of init_command", 0};
10863 PSI_stage_info stage_explaining= { 0, "explaining", 0};
10864 PSI_stage_info stage_finished_reading_one_binlog_switching_to_next_binlog= { 0, "Finished reading one binlog; switching to next binlog", 0};
10865 PSI_stage_info stage_flushing_relay_log_and_master_info_repository= { 0, "Flushing relay log and master info repository.", 0};
10866 PSI_stage_info stage_flushing_relay_log_info_file= { 0, "Flushing relay-log info file.", 0};
10867 PSI_stage_info stage_freeing_items= { 0, "freeing items", 0};
10868 PSI_stage_info stage_fulltext_initialization= { 0, "FULLTEXT initialization", 0};
10869 PSI_stage_info stage_got_handler_lock= { 0, "got handler lock", 0};
10870 PSI_stage_info stage_got_old_table= { 0, "got old table", 0};
10871 PSI_stage_info stage_init= { 0, "init", 0};
10872 PSI_stage_info stage_insert= { 0, "insert", 0};
10873 PSI_stage_info stage_invalidating_query_cache_entries_table= { 0, "invalidating query cache entries (table)", 0};
10874 PSI_stage_info stage_invalidating_query_cache_entries_table_list= { 0, "invalidating query cache entries (table list)", 0};
10875 PSI_stage_info stage_killing_slave= { 0, "Killing slave", 0};
10876 PSI_stage_info stage_logging_slow_query= { 0, "logging slow query", 0};
10877 PSI_stage_info stage_making_temp_file_append_before_load_data= { 0, "Making temporary file (append) before replaying LOAD DATA INFILE.", 0};
10878 PSI_stage_info stage_making_temp_file_create_before_load_data= { 0, "Making temporary file (create) before replaying LOAD DATA INFILE.", 0};
10879 PSI_stage_info stage_manage_keys= { 0, "manage keys", 0};
10880 PSI_stage_info stage_master_has_sent_all_binlog_to_slave= { 0, "Master has sent all binlog to slave; waiting for binlog to be updated", 0};
10881 PSI_stage_info stage_opening_tables= { 0, "Opening tables", 0};
10882 PSI_stage_info stage_optimizing= { 0, "optimizing", 0};
10883 PSI_stage_info stage_preparing= { 0, "preparing", 0};
10884 PSI_stage_info stage_purging_old_relay_logs= { 0, "Purging old relay logs", 0};
10885 PSI_stage_info stage_query_end= { 0, "query end", 0};
10886 PSI_stage_info stage_queueing_master_event_to_the_relay_log= { 0, "Queueing master event to the relay log", 0};
10887 PSI_stage_info stage_reading_event_from_the_relay_log= { 0, "Reading event from the relay log", 0};
10888 PSI_stage_info stage_registering_slave_on_master= { 0, "Registering slave on master", 0};
10889 PSI_stage_info stage_removing_duplicates= { 0, "Removing duplicates", 0};
10890 PSI_stage_info stage_removing_tmp_table= { 0, "removing tmp table", 0};
10891 PSI_stage_info stage_rename= { 0, "rename", 0};
10892 PSI_stage_info stage_rename_result_table= { 0, "rename result table", 0};
10893 PSI_stage_info stage_requesting_binlog_dump= { 0, "Requesting binlog dump", 0};
10894 PSI_stage_info stage_reschedule= { 0, "reschedule", 0};
10895 PSI_stage_info stage_searching_rows_for_update= { 0, "Searching rows for update", 0};
10896 PSI_stage_info stage_sending_binlog_event_to_slave= { 0, "Sending binlog event to slave", 0};
10897 PSI_stage_info stage_sending_cached_result_to_client= { 0, "sending cached result to client", 0};
10898 PSI_stage_info stage_sending_data= { 0, "Sending data", 0};
10899 PSI_stage_info stage_setup= { 0, "setup", 0};
10900 PSI_stage_info stage_slave_has_read_all_relay_log= { 0, "Slave has read all relay log; waiting for the slave I/O thread to update it", 0};
10901 PSI_stage_info stage_sorting_for_group= { 0, "Sorting for group", 0};
10902 PSI_stage_info stage_sorting_for_order= { 0, "Sorting for order", 0};
10903 PSI_stage_info stage_sorting_result= { 0, "Sorting result", 0};
10904 PSI_stage_info stage_statistics= { 0, "statistics", 0};
10905 PSI_stage_info stage_sql_thd_waiting_until_delay= { 0, "Waiting until MASTER_DELAY seconds after master executed event", 0 };
10906 PSI_stage_info stage_storing_result_in_query_cache= { 0, "storing result in query cache", 0};
10907 PSI_stage_info stage_storing_row_into_queue= { 0, "storing row into queue", 0};
10908 PSI_stage_info stage_system_lock= { 0, "System lock", 0};
10909 PSI_stage_info stage_update= { 0, "update", 0};
10910 PSI_stage_info stage_updating= { 0, "updating", 0};
10911 PSI_stage_info stage_updating_main_table= { 0, "updating main table", 0};
10912 PSI_stage_info stage_updating_reference_tables= { 0, "updating reference tables", 0};
10913 PSI_stage_info stage_upgrading_lock= { 0, "upgrading lock", 0};
10914 PSI_stage_info stage_user_lock= { 0, "User lock", 0};
10915 PSI_stage_info stage_user_sleep= { 0, "User sleep", 0};
10916 PSI_stage_info stage_verifying_table= { 0, "verifying table", 0};
10917 PSI_stage_info stage_waiting_for_delay_list= { 0, "waiting for delay_list", 0};
10918 PSI_stage_info stage_waiting_for_gtid_to_be_written_to_binary_log= { 0, "waiting for GTID to be written to binary log", 0};
10919 PSI_stage_info stage_waiting_for_handler_insert= { 0, "waiting for handler insert", 0};
10920 PSI_stage_info stage_waiting_for_handler_lock= { 0, "waiting for handler lock", 0};
10921 PSI_stage_info stage_waiting_for_handler_open= { 0, "waiting for handler open", 0};
10922 PSI_stage_info stage_waiting_for_insert= { 0, "Waiting for INSERT", 0};
10923 PSI_stage_info stage_waiting_for_master_to_send_event= { 0, "Waiting for master to send event", 0};
10924 PSI_stage_info stage_waiting_for_master_update= { 0, "Waiting for master update", 0};
10925 PSI_stage_info stage_waiting_for_relay_log_space= { 0, "Waiting for the slave SQL thread to free enough relay log space", 0};
10926 PSI_stage_info stage_waiting_for_slave_mutex_on_exit= { 0, "Waiting for slave mutex on exit", 0};
10927 PSI_stage_info stage_waiting_for_slave_thread_to_start= { 0, "Waiting for slave thread to start", 0};
10928 PSI_stage_info stage_waiting_for_table_flush= { 0, "Waiting for table flush", 0};
10929 PSI_stage_info stage_waiting_for_query_cache_lock= { 0, "Waiting for query cache lock", 0};
10930 PSI_stage_info stage_waiting_for_the_next_event_in_relay_log= { 0, "Waiting for the next event in relay log", 0};
10931 PSI_stage_info stage_waiting_for_the_slave_thread_to_advance_position= { 0, "Waiting for the slave SQL thread to advance position", 0};
10932 PSI_stage_info stage_waiting_to_finalize_termination= { 0, "Waiting to finalize termination", 0};
10933 PSI_stage_info stage_waiting_to_get_readlock= { 0, "Waiting to get readlock", 0};
10934 PSI_stage_info stage_slave_waiting_workers_to_exit= { 0, "Waiting for workers to exit", 0};
10935 PSI_stage_info stage_slave_waiting_worker_to_release_partition= { 0, "Waiting for Slave Worker to release partition", 0};
10936 PSI_stage_info stage_slave_waiting_worker_to_free_events= { 0, "Waiting for Slave Workers to free pending events", 0};
10937 PSI_stage_info stage_slave_waiting_worker_queue= { 0, "Waiting for Slave Worker queue", 0};
10938 PSI_stage_info stage_slave_waiting_event_from_coordinator= { 0, "Waiting for an event from Coordinator", 0};
10939 
10940 #ifdef HAVE_PSI_INTERFACE
10941 
10942 PSI_stage_info *all_server_stages[]=
10943 {
10944   & stage_after_create,
10945   & stage_allocating_local_table,
10946   & stage_alter_inplace_prepare,
10947   & stage_alter_inplace,
10948   & stage_alter_inplace_commit,
10949   & stage_changing_master,
10950   & stage_checking_master_version,
10951   & stage_checking_permissions,
10952   & stage_checking_privileges_on_cached_query,
10953   & stage_checking_query_cache_for_query,
10954   & stage_cleaning_up,
10955   & stage_closing_tables,
10956   & stage_connecting_to_master,
10957   & stage_converting_heap_to_myisam,
10958   & stage_copying_to_group_table,
10959   & stage_copying_to_tmp_table,
10960   & stage_copy_to_tmp_table,
10961   & stage_creating_delayed_handler,
10962   & stage_creating_sort_index,
10963   & stage_creating_table,
10964   & stage_creating_tmp_table,
10965   & stage_deleting_from_main_table,
10966   & stage_deleting_from_reference_tables,
10967   & stage_discard_or_import_tablespace,
10968   & stage_end,
10969   & stage_executing,
10970   & stage_execution_of_init_command,
10971   & stage_explaining,
10972   & stage_finished_reading_one_binlog_switching_to_next_binlog,
10973   & stage_flushing_relay_log_and_master_info_repository,
10974   & stage_flushing_relay_log_info_file,
10975   & stage_freeing_items,
10976   & stage_fulltext_initialization,
10977   & stage_got_handler_lock,
10978   & stage_got_old_table,
10979   & stage_init,
10980   & stage_insert,
10981   & stage_invalidating_query_cache_entries_table,
10982   & stage_invalidating_query_cache_entries_table_list,
10983   & stage_killing_slave,
10984   & stage_logging_slow_query,
10985   & stage_making_temp_file_append_before_load_data,
10986   & stage_making_temp_file_create_before_load_data,
10987   & stage_manage_keys,
10988   & stage_master_has_sent_all_binlog_to_slave,
10989   & stage_opening_tables,
10990   & stage_optimizing,
10991   & stage_preparing,
10992   & stage_purging_old_relay_logs,
10993   & stage_query_end,
10994   & stage_queueing_master_event_to_the_relay_log,
10995   & stage_reading_event_from_the_relay_log,
10996   & stage_registering_slave_on_master,
10997   & stage_removing_duplicates,
10998   & stage_removing_tmp_table,
10999   & stage_rename,
11000   & stage_rename_result_table,
11001   & stage_requesting_binlog_dump,
11002   & stage_reschedule,
11003   & stage_searching_rows_for_update,
11004   & stage_sending_binlog_event_to_slave,
11005   & stage_sending_cached_result_to_client,
11006   & stage_sending_data,
11007   & stage_setup,
11008   & stage_slave_has_read_all_relay_log,
11009   & stage_sorting_for_group,
11010   & stage_sorting_for_order,
11011   & stage_sorting_result,
11012   & stage_sql_thd_waiting_until_delay,
11013   & stage_statistics,
11014   & stage_storing_result_in_query_cache,
11015   & stage_storing_row_into_queue,
11016   & stage_system_lock,
11017   & stage_update,
11018   & stage_updating,
11019   & stage_updating_main_table,
11020   & stage_updating_reference_tables,
11021   & stage_upgrading_lock,
11022   & stage_user_lock,
11023   & stage_user_sleep,
11024   & stage_verifying_table,
11025   & stage_waiting_for_delay_list,
11026   & stage_waiting_for_handler_insert,
11027   & stage_waiting_for_handler_lock,
11028   & stage_waiting_for_handler_open,
11029   & stage_waiting_for_insert,
11030   & stage_waiting_for_master_to_send_event,
11031   & stage_waiting_for_master_update,
11032   & stage_waiting_for_slave_mutex_on_exit,
11033   & stage_waiting_for_slave_thread_to_start,
11034   & stage_waiting_for_table_flush,
11035   & stage_waiting_for_query_cache_lock,
11036   & stage_waiting_for_the_next_event_in_relay_log,
11037   & stage_waiting_for_the_slave_thread_to_advance_position,
11038   & stage_waiting_to_finalize_termination,
11039   & stage_waiting_to_get_readlock
11040 };
11041 
11042 PSI_socket_key key_socket_tcpip, key_socket_unix, key_socket_client_connection;
11043 
11044 static PSI_socket_info all_server_sockets[]=
11045 {
11046   { &key_socket_tcpip, "server_tcpip_socket", PSI_FLAG_GLOBAL},
11047   { &key_socket_unix, "server_unix_socket", PSI_FLAG_GLOBAL},
11048   { &key_socket_client_connection, "client_connection", 0}
11049 };
11050 
11051 /**
11052   Initialise all the performance schema instrumentation points
11053   used by the server.
11054 */
init_server_psi_keys(void)11055 void init_server_psi_keys(void)
11056 {
11057   const char* category= "sql";
11058   int count;
11059 
11060   count= array_elements(all_server_mutexes);
11061   mysql_mutex_register(category, all_server_mutexes, count);
11062 
11063   count= array_elements(all_server_rwlocks);
11064   mysql_rwlock_register(category, all_server_rwlocks, count);
11065 
11066   count= array_elements(all_server_conds);
11067   mysql_cond_register(category, all_server_conds, count);
11068 
11069   count= array_elements(all_server_threads);
11070   mysql_thread_register(category, all_server_threads, count);
11071 
11072   count= array_elements(all_server_files);
11073   mysql_file_register(category, all_server_files, count);
11074 
11075   count= array_elements(all_server_stages);
11076   mysql_stage_register(category, all_server_stages, count);
11077 
11078   count= array_elements(all_server_sockets);
11079   mysql_socket_register(category, all_server_sockets, count);
11080 
11081 #ifdef HAVE_PSI_STATEMENT_INTERFACE
11082   init_sql_statement_info();
11083   count= array_elements(sql_statement_info);
11084   mysql_statement_register(category, sql_statement_info, count);
11085 
11086   category= "com";
11087   init_com_statement_info();
11088 
11089   /*
11090     Register [0 .. COM_QUERY - 1] as "statement/com/..."
11091   */
11092   count= (int) COM_QUERY;
11093   mysql_statement_register(category, com_statement_info, count);
11094 
11095   /*
11096     Register [COM_QUERY + 1 .. COM_END] as "statement/com/..."
11097   */
11098   count= (int) COM_END - (int) COM_QUERY;
11099   mysql_statement_register(category, & com_statement_info[(int) COM_QUERY + 1], count);
11100 
11101   category= "abstract";
11102   /*
11103     Register [COM_QUERY] as "statement/abstract/com_query"
11104   */
11105   mysql_statement_register(category, & com_statement_info[(int) COM_QUERY], 1);
11106 
11107   /*
11108     When a new packet is received,
11109     it is instrumented as "statement/abstract/new_packet".
11110     Based on the packet type found, it later mutates to the
11111     proper narrow type, for example
11112     "statement/abstract/query" or "statement/com/ping".
11113     In cases of "statement/abstract/query", SQL queries are given to
11114     the parser, which mutates the statement type to an even more
11115     narrow classification, for example "statement/sql/select".
11116   */
11117   stmt_info_new_packet.m_key= 0;
11118   stmt_info_new_packet.m_name= "new_packet";
11119   stmt_info_new_packet.m_flags= PSI_FLAG_MUTABLE;
11120   mysql_statement_register(category, &stmt_info_new_packet, 1);
11121 
11122   /*
11123     Statements processed from the relay log are initially instrumented as
11124     "statement/abstract/relay_log". The parser will mutate the statement type to
11125     a more specific classification, for example "statement/sql/insert".
11126   */
11127   stmt_info_rpl.m_key= 0;
11128   stmt_info_rpl.m_name= "relay_log";
11129   stmt_info_rpl.m_flags= PSI_FLAG_MUTABLE;
11130   mysql_statement_register(category, &stmt_info_rpl, 1);
11131 #endif
11132 }
11133 
11134 #endif /* HAVE_PSI_INTERFACE */
11135 
11136 #if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
11137 // update_named_pipe_full_access_group returns false on success, true on failure
update_named_pipe_full_access_group(const char * new_group_name)11138 bool update_named_pipe_full_access_group(const char *new_group_name)
11139 {
11140   SECURITY_ATTRIBUTES *p_new_sa= NULL;
11141   const char *perror= NULL;
11142   TCHAR last_error_msg[256];
11143 
11144   // Set up security attributes to provide full access to the owner
11145   // and minimal read/write access to others.
11146   if (my_security_attr_create(&p_new_sa, &perror, NAMED_PIPE_OWNER_PERMISSIONS,
11147                               NAMED_PIPE_EVERYONE_PERMISSIONS) != 0)
11148   {
11149     sql_print_error("my_security_attr_create: %s", perror);
11150     return true;
11151   }
11152   if (new_group_name && new_group_name[0] != '\0')
11153   {
11154     if (my_security_attr_add_rights_to_group(
11155             p_new_sa, new_group_name,
11156             NAMED_PIPE_FULL_ACCESS_GROUP_PERMISSIONS))
11157     {
11158       sql_print_error("my_security_attr_add_rights_to_group failed for group: %s",
11159                       new_group_name);
11160       return true;
11161     }
11162   }
11163 
11164   psaPipeSecurity= p_new_sa;
11165 
11166   // Set the DACL for the existing "listener" named pipe instance...
11167   if (hPipe != INVALID_HANDLE_VALUE)
11168   {
11169     PACL pdacl= NULL;
11170     BOOL dacl_present_in_descriptor= FALSE;
11171     BOOL dacl_defaulted= FALSE;
11172     if (!GetSecurityDescriptorDacl(p_new_sa->lpSecurityDescriptor,
11173                                    &dacl_present_in_descriptor, &pdacl,
11174                                    &dacl_defaulted) ||
11175         !dacl_present_in_descriptor)
11176     {
11177       DWORD last_error_num= GetLastError();
11178       FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
11179                     NULL, last_error_num,
11180                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), last_error_msg,
11181                     sizeof(last_error_msg) / sizeof(TCHAR), NULL);
11182       sql_print_error("GetSecurityDescriptorDacl failed: %s", last_error_msg);
11183       return true;
11184     }
11185     DWORD res =
11186         SetSecurityInfo(hPipe, SE_KERNEL_OBJECT,
11187                         DACL_SECURITY_INFORMATION, NULL, NULL, pdacl, NULL);
11188     if (res != ERROR_SUCCESS)
11189     {
11190       char num_buff[20];
11191       int10_to_str(res, num_buff, 10);
11192       sql_print_error("SetSecurityInfo failed to update DACL on named pipe: %s", num_buff);
11193       return true;
11194     }
11195   }
11196   return false;
11197 }
11198 
11199 #endif  /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */
11200