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, ¬_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