1 /* Copyright (c) 2000, 2017, 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 as published by
6    the Free Software Foundation; version 2 of the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA */
16 
17 #include "my_global.h"                          /* NO_EMBEDDED_ACCESS_CHECKS */
18 #include "sql_priv.h"
19 #include "unireg.h"
20 #include <signal.h>
21 #ifndef __WIN__
22 #include <netdb.h>        // getservbyname, servent
23 #endif
24 #include "sql_parse.h"    // test_if_data_home_dir
25 #include "sql_cache.h"    // query_cache, query_cache_*
26 #include "sql_locale.h"   // MY_LOCALES, my_locales, my_locale_by_name
27 #include "sql_show.h"     // free_status_vars, add_status_vars,
28                           // reset_status_vars
29 #include "strfunc.h"      // find_set_from_flags
30 #include "parse_file.h"   // File_parser_dummy_hook
31 #include "sql_db.h"       // my_dboptions_cache_free
32                           // my_dboptions_cache_init
33 #include "sql_table.h"    // release_ddl_log, execute_ddl_log_recovery
34 #include "sql_connect.h"  // free_max_user_conn, init_max_user_conn,
35                           // handle_one_connection
36 #include "sql_time.h"     // known_date_time_formats,
37                           // get_date_time_format_str,
38                           // date_time_format_make
39 #include "tztime.h"       // my_tz_free, my_tz_init, my_tz_SYSTEM
40 #include "hostname.h"     // hostname_cache_free, hostname_cache_init
41 #include "sql_acl.h"      // acl_free, grant_free, acl_init,
42                           // grant_init
43 #include "sql_base.h"     // table_def_free, table_def_init,
44                           // cached_open_tables,
45                           // cached_table_definitions
46 #include "sql_test.h"     // mysql_print_status
47 #include "item_create.h"  // item_create_cleanup, item_create_init
48 #include "sql_servers.h"  // servers_free, servers_init
49 #include "init.h"         // unireg_init
50 #include "derror.h"       // init_errmessage
51 #include "derror.h"       // init_errmessage
52 #include "des_key_file.h" // load_des_key_file
53 #include "sql_manager.h"  // stop_handle_manager, start_handle_manager
54 #include <m_ctype.h>
55 #include <my_dir.h>
56 #include <my_bit.h>
57 #include "slave.h"
58 #include "rpl_mi.h"
59 #include "sql_repl.h"
60 #include "rpl_filter.h"
61 #include "repl_failsafe.h"
62 #include <sql_common.h>
63 #include <my_stacktrace.h>
64 #include "mysqld_suffix.h"
65 #include "mysys_err.h"
66 #include "events.h"
67 #include "sql_audit.h"
68 #include "probes_mysql.h"
69 #include "scheduler.h"
70 #include "debug_sync.h"
71 #include "sql_callback.h"
72 
73 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
74 #include "../storage/perfschema/pfs_server.h"
75 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
76 
77 #include "keycaches.h"
78 #include "../storage/myisam/ha_myisam.h"
79 #include "set_var.h"
80 
81 #include "rpl_injector.h"
82 
83 #include "rpl_handler.h"
84 
85 #ifdef HAVE_SYS_PRCTL_H
86 #include <sys/prctl.h>
87 #endif
88 
89 #include <thr_alarm.h>
90 #include <ft_global.h>
91 #include <errmsg.h>
92 #include "sp_rcontext.h"
93 #include "sp_cache.h"
94 #include "sql_reload.h"  // reload_acl_and_cache
95 
96 #ifdef HAVE_POLL_H
97 #include <poll.h>
98 #endif
99 
100 #define mysqld_charset &my_charset_latin1
101 
102 /* We have HAVE_purify below as this speeds up the shutdown of MySQL */
103 
104 #if defined(HAVE_DEC_3_2_THREADS) || defined(SIGNALS_DONT_BREAK_READ) || defined(HAVE_purify) && defined(__linux__)
105 #define HAVE_CLOSE_SERVER_SOCK 1
106 #endif
107 
108 extern "C" {					// Because of SCO 3.2V4.2
109 #include <errno.h>
110 #include <sys/stat.h>
111 #ifndef __GNU_LIBRARY__
112 #define __GNU_LIBRARY__				// Skip warnings in getopt.h
113 #endif
114 #include <my_getopt.h>
115 #ifdef HAVE_SYSENT_H
116 #include <sysent.h>
117 #endif
118 #ifdef HAVE_PWD_H
119 #include <pwd.h>				// For getpwent
120 #endif
121 #ifdef HAVE_GRP_H
122 #include <grp.h>
123 #endif
124 #include <my_net.h>
125 
126 #if !defined(__WIN__)
127 #include <sys/resource.h>
128 #ifdef HAVE_SYS_UN_H
129 #include <sys/un.h>
130 #endif
131 #ifdef HAVE_SELECT_H
132 #include <select.h>
133 #endif
134 #ifdef HAVE_SYS_SELECT_H
135 #include <sys/select.h>
136 #endif
137 #include <sys/utsname.h>
138 #endif /* __WIN__ */
139 
140 #include <my_libwrap.h>
141 
142 #ifdef HAVE_SYS_MMAN_H
143 #include <sys/mman.h>
144 #endif
145 
146 #ifdef __WIN__
147 #include <crtdbg.h>
148 #endif
149 
150 #ifdef HAVE_SOLARIS_LARGE_PAGES
151 #include <sys/mman.h>
152 #if defined(__sun__) && defined(__GNUC__) && defined(__cplusplus) \
153     && defined(_XOPEN_SOURCE)
154 extern int getpagesizes(size_t *, int);
155 extern int getpagesizes2(size_t *, int);
156 extern int memcntl(caddr_t, size_t, int, caddr_t, int, int);
157 #endif /* __sun__ ... */
158 #endif /* HAVE_SOLARIS_LARGE_PAGES */
159 
160 #ifdef _AIX41
161 int initgroups(const char *,unsigned int);
162 #endif
163 
164 #if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H) && !defined(HAVE_FEDISABLEEXCEPT)
165 #include <ieeefp.h>
166 #ifdef HAVE_FP_EXCEPT				// Fix type conflict
167 typedef fp_except fp_except_t;
168 #endif
169 #endif /* __FreeBSD__ && HAVE_IEEEFP_H && !HAVE_FEDISABLEEXCEPT */
170 #ifdef HAVE_SYS_FPU_H
171 /* for IRIX to use set_fpc_csr() */
172 #include <sys/fpu.h>
173 #endif
174 #ifdef HAVE_FPU_CONTROL_H
175 #include <fpu_control.h>
176 #endif
177 #if defined(__i386__) && !defined(HAVE_FPU_CONTROL_H)
178 # define fpu_control_t unsigned int
179 # define _FPU_EXTENDED 0x300
180 # define _FPU_DOUBLE 0x200
181 # if defined(__GNUC__) || (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x590)
182 #  define _FPU_GETCW(cw) asm volatile ("fnstcw %0" : "=m" (*&cw))
183 #  define _FPU_SETCW(cw) asm volatile ("fldcw %0" : : "m" (*&cw))
184 # else
185 #  define _FPU_GETCW(cw) (cw= 0)
186 #  define _FPU_SETCW(cw)
187 # endif
188 #endif
189 
190 extern "C" my_bool reopen_fstreams(const char *filename,
191                                    FILE *outstream, FILE *errstream);
192 
setup_fpu()193 inline void setup_fpu()
194 {
195 #if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H) && !defined(HAVE_FEDISABLEEXCEPT)
196   /* We can't handle floating point exceptions with threads, so disable
197      this on freebsd
198      Don't fall for overflow, underflow,divide-by-zero or loss of precision.
199      fpsetmask() is deprecated in favor of fedisableexcept() in C99.
200   */
201 #if defined(FP_X_DNML)
202   fpsetmask(~(FP_X_INV | FP_X_DNML | FP_X_OFL | FP_X_UFL | FP_X_DZ |
203 	      FP_X_IMP));
204 #else
205   fpsetmask(~(FP_X_INV |             FP_X_OFL | FP_X_UFL | FP_X_DZ |
206               FP_X_IMP));
207 #endif /* FP_X_DNML */
208 #endif /* __FreeBSD__ && HAVE_IEEEFP_H && !HAVE_FEDISABLEEXCEPT */
209 
210 #ifdef HAVE_FEDISABLEEXCEPT
211   fedisableexcept(FE_ALL_EXCEPT);
212 #endif
213 
214 #ifdef HAVE_FESETROUND
215     /* Set FPU rounding mode to "round-to-nearest" */
216   fesetround(FE_TONEAREST);
217 #endif /* HAVE_FESETROUND */
218 
219   /*
220     x86 (32-bit) requires FPU precision to be explicitly set to 64 bit
221     (double precision) for portable results of floating point operations.
222     However, there is no need to do so if compiler is using SSE2 for floating
223     point, double values will be stored and processed in 64 bits anyway.
224   */
225 #if defined(__i386__) && !defined(__SSE2_MATH__)
226 #if defined(_WIN32)
227 #if !defined(_WIN64)
228   _control87(_PC_53, MCW_PC);
229 #endif /* !_WIN64 */
230 #else /* !_WIN32 */
231   fpu_control_t cw;
232   _FPU_GETCW(cw);
233   cw= (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE;
234   _FPU_SETCW(cw);
235 #endif /* _WIN32 && */
236 #endif /* __i386__ */
237 
238 #if defined(__sgi) && defined(HAVE_SYS_FPU_H)
239   /* Enable denormalized DOUBLE values support for IRIX */
240   union fpc_csr n;
241   n.fc_word = get_fpc_csr();
242   n.fc_struct.flush = 0;
243   set_fpc_csr(n.fc_word);
244 #endif
245 }
246 
247 } /* cplusplus */
248 
249 #define MYSQL_KILL_SIGNAL SIGTERM
250 
251 #include <my_pthread.h>			// For thr_setconcurency()
252 
253 #ifdef SOLARIS
254 extern "C" int gethostname(char *name, int namelen);
255 #endif
256 
257 extern "C" sig_handler handle_fatal_signal(int sig);
258 
259 #if defined(__linux__)
260 #define ENABLE_TEMP_POOL 1
261 #else
262 #define ENABLE_TEMP_POOL 0
263 #endif
264 
265 /* Constants */
266 
267 #include <welcome_copyright_notice.h> // ORACLE_WELCOME_COPYRIGHT_NOTICE
268 
269 const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"};
270 
271 static const char *tc_heuristic_recover_names[]=
272 {
273   "COMMIT", "ROLLBACK", NullS
274 };
275 static TYPELIB tc_heuristic_recover_typelib=
276 {
277   array_elements(tc_heuristic_recover_names)-1,"",
278   tc_heuristic_recover_names, NULL
279 };
280 
281 const char *first_keyword= "first", *binary_keyword= "BINARY";
282 const char *my_localhost= "localhost", *delayed_user= "DELAYED";
283 
284 bool opt_large_files= sizeof(my_off_t) > 4;
285 static my_bool opt_autocommit; ///< for --autocommit command-line option
286 
287 /*
288   Used with --help for detailed option
289 */
290 static my_bool opt_help= 0, opt_verbose= 0;
291 
292 arg_cmp_func Arg_comparator::comparator_matrix[5][2] =
293 {{&Arg_comparator::compare_string,     &Arg_comparator::compare_e_string},
294  {&Arg_comparator::compare_real,       &Arg_comparator::compare_e_real},
295  {&Arg_comparator::compare_int_signed, &Arg_comparator::compare_e_int},
296  {&Arg_comparator::compare_row,        &Arg_comparator::compare_e_row},
297  {&Arg_comparator::compare_decimal,    &Arg_comparator::compare_e_decimal}};
298 
299 /* static variables */
300 
301 #ifdef HAVE_PSI_INTERFACE
302 #if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
303 static PSI_thread_key key_thread_handle_con_namedpipes;
304 static PSI_cond_key key_COND_handler_count;
305 #endif /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */
306 
307 #if defined(HAVE_SMEM) && !defined(EMBEDDED_LIBRARY)
308 static PSI_thread_key key_thread_handle_con_sharedmem;
309 #endif /* HAVE_SMEM && !EMBEDDED_LIBRARY */
310 
311 #if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
312 static PSI_thread_key key_thread_handle_con_sockets;
313 #endif /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */
314 
315 #ifdef __WIN__
316 static PSI_thread_key key_thread_handle_shutdown;
317 #endif /* __WIN__ */
318 
319 #if defined (HAVE_OPENSSL) && !defined(HAVE_YASSL)
320 static PSI_rwlock_key key_rwlock_openssl;
321 #endif
322 #endif /* HAVE_PSI_INTERFACE */
323 
324 #ifdef HAVE_NPTL
325 volatile sig_atomic_t ld_assume_kernel_is_set= 0;
326 #endif
327 
328 /* the default log output is log tables */
329 static bool lower_case_table_names_used= 0;
330 static bool max_long_data_size_used= false;
331 static bool volatile select_thread_in_use, signal_thread_in_use;
332 /* See Bug#56666 and Bug#56760 */;
333 volatile bool ready_to_exit;
334 static my_bool opt_debugging= 0, opt_external_locking= 0, opt_console= 0;
335 static my_bool opt_short_log_format= 0;
336 static uint kill_cached_threads, wake_thread;
337 static ulong killed_threads;
338        ulong max_used_connections;
339 static volatile ulong cached_thread_count= 0;
340 static char *mysqld_user, *mysqld_chroot;
341 static char *default_character_set_name;
342 static char *character_set_filesystem_name;
343 static char *lc_messages;
344 static char *lc_time_names_name;
345 static char *my_bind_addr_str;
346 static char *default_collation_name;
347 char *default_storage_engine;
348 static char compiled_default_collation_name[]= MYSQL_DEFAULT_COLLATION_NAME;
349 static I_List<THD> thread_cache;
350 static bool binlog_format_used= false;
351 
352 LEX_STRING opt_init_connect, opt_init_slave;
353 
354 static mysql_cond_t COND_thread_cache, COND_flush_thread_cache;
355 
356 /* Global variables */
357 
358 bool opt_bin_log, opt_ignore_builtin_innodb= 0;
359 my_bool opt_log, opt_slow_log;
360 ulonglong log_output_options;
361 my_bool opt_log_queries_not_using_indexes= 0;
362 bool opt_error_log= IF_WIN(1,0);
363 bool opt_disable_networking=0, opt_skip_show_db=0;
364 bool opt_skip_name_resolve=0;
365 my_bool opt_character_set_client_handshake= 1;
366 bool server_id_supplied = 0;
367 bool opt_endinfo, using_udf_functions;
368 my_bool locked_in_memory;
369 bool opt_using_transactions;
370 bool volatile abort_loop;
371 bool volatile shutdown_in_progress;
372 #if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
373 ulong slow_start_timeout;
374 #endif
375 /*
376   True if the bootstrap thread is running. Protected by LOCK_thread_count,
377   just like thread_count.
378   Used in bootstrap() function to determine if the bootstrap thread
379   has completed. Note, that we can't use 'thread_count' instead,
380   since in 5.1, in presence of the Event Scheduler, there may be
381   event threads running in parallel, so it's impossible to know
382   what value of 'thread_count' is a sign of completion of the
383   bootstrap thread.
384 
385   At the same time, we can't start the event scheduler after
386   bootstrap either, since we want to be able to process event-related
387   SQL commands in the init file and in --bootstrap mode.
388 */
389 bool in_bootstrap= FALSE;
390 /**
391    @brief 'grant_option' is used to indicate if privileges needs
392    to be checked, in which case the lock, LOCK_grant, is used
393    to protect access to the grant table.
394    @note This flag is dropped in 5.1
395    @see grant_init()
396  */
397 bool volatile grant_option;
398 
399 my_bool opt_skip_slave_start = 0; ///< If set, slave is not autostarted
400 my_bool opt_reckless_slave = 0;
401 my_bool opt_enable_named_pipe= 0;
402 my_bool opt_local_infile, opt_slave_compressed_protocol;
403 my_bool opt_safe_user_create = 0;
404 my_bool opt_show_slave_auth_info;
405 my_bool opt_log_slave_updates= 0;
406 char *opt_slave_skip_errors;
407 
408 /**
409   compatibility option:
410     - index usage hints (USE INDEX without a FOR clause) behave as in 5.0
411 */
412 my_bool old_mode;
413 
414 /*
415   Legacy global handlerton. These will be removed (please do not add more).
416 */
417 handlerton *heap_hton;
418 handlerton *myisam_hton;
419 handlerton *partition_hton;
420 
421 my_bool read_only= 0, opt_readonly= 0;
422 my_bool use_temp_pool, relay_log_purge;
423 my_bool relay_log_recovery;
424 my_bool opt_sync_frm, opt_allow_suspicious_udfs;
425 my_bool opt_secure_auth= 0;
426 char* opt_secure_file_priv;
427 my_bool opt_log_slow_admin_statements= 0;
428 my_bool opt_log_slow_slave_statements= 0;
429 my_bool lower_case_file_system= 0;
430 my_bool opt_large_pages= 0;
431 my_bool opt_super_large_pages= 0;
432 my_bool opt_myisam_use_mmap= 0;
433 uint   opt_large_page_size= 0;
434 #if defined(ENABLED_DEBUG_SYNC)
435 MYSQL_PLUGIN_IMPORT uint    opt_debug_sync_timeout= 0;
436 #endif /* defined(ENABLED_DEBUG_SYNC) */
437 my_bool opt_old_style_user_limits= 0, trust_function_creators= 0;
438 /*
439   True if there is at least one per-hour limit for some user, so we should
440   check them before each query (and possibly reset counters when hour is
441   changed). False otherwise.
442 */
443 volatile bool mqh_used = 0;
444 my_bool opt_noacl;
445 my_bool sp_automatic_privileges= 1;
446 
447 ulong opt_binlog_rows_event_max_size;
448 const char *binlog_format_names[]= {"MIXED", "STATEMENT", "ROW", NullS};
449 #ifdef HAVE_INITGROUPS
450 volatile sig_atomic_t calling_initgroups= 0; /**< Used in SIGSEGV handler. */
451 #endif
452 uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options;
453 uint mysqld_port_timeout;
454 ulong delay_key_write_options;
455 uint protocol_version;
456 uint lower_case_table_names;
457 ulong tc_heuristic_recover= 0;
458 uint volatile thread_count;
459 int32 thread_running;
460 ulong thread_created;
461 ulong back_log, connect_timeout, concurrency, server_id;
462 ulong table_cache_size, table_def_size;
463 ulong what_to_log;
464 ulong slow_launch_time, slave_open_temp_tables;
465 ulong open_files_limit, max_binlog_size, max_relay_log_size;
466 ulong slave_trans_retries;
467 uint  slave_net_timeout;
468 ulong slave_exec_mode_options;
469 ulonglong slave_type_conversions_options;
470 ulong thread_cache_size=0;
471 ulong binlog_cache_size=0;
472 ulonglong  max_binlog_cache_size=0;
473 ulong slave_max_allowed_packet= 0;
474 ulong binlog_stmt_cache_size=0;
475 ulonglong  max_binlog_stmt_cache_size=0;
476 ulong query_cache_size=0;
477 ulong refresh_version;  /* Increments on each reload */
478 query_id_t global_query_id;
479 my_atomic_rwlock_t global_query_id_lock;
480 my_atomic_rwlock_t thread_running_lock;
481 ulong aborted_threads, aborted_connects;
482 ulong delayed_insert_timeout, delayed_insert_limit, delayed_queue_size;
483 ulong delayed_insert_threads, delayed_insert_writes, delayed_rows_in_use;
484 ulong delayed_insert_errors,flush_time;
485 ulong specialflag=0;
486 ulong binlog_cache_use= 0, binlog_cache_disk_use= 0;
487 ulong binlog_stmt_cache_use= 0, binlog_stmt_cache_disk_use= 0;
488 ulong max_connections, max_connect_errors;
489 /*
490   Maximum length of parameter value which can be set through
491   mysql_send_long_data() call.
492 */
493 ulong max_long_data_size;
494 /**
495   Limit of the total number of prepared statements in the server.
496   Is necessary to protect the server against out-of-memory attacks.
497 */
498 ulong max_prepared_stmt_count;
499 /**
500   Current total number of prepared statements in the server. This number
501   is exact, and therefore may not be equal to the difference between
502   `com_stmt_prepare' and `com_stmt_close' (global status variables), as
503   the latter ones account for all registered attempts to prepare
504   a statement (including unsuccessful ones).  Prepared statements are
505   currently connection-local: if the same SQL query text is prepared in
506   two different connections, this counts as two distinct prepared
507   statements.
508 */
509 ulong prepared_stmt_count=0;
510 ulong thread_id=1L,current_pid;
511 ulong slow_launch_threads = 0;
512 uint sync_binlog_period= 0, sync_relaylog_period= 0,
513      sync_relayloginfo_period= 0, sync_masterinfo_period= 0;
514 ulong expire_logs_days = 0;
515 ulong rpl_recovery_rank=0;
516 /**
517   Soft upper limit for number of sp_head objects that can be stored
518   in the sp_cache for one connection.
519 */
520 ulong stored_program_cache_size= 0;
521 
522 const double log_10[] = {
523   1e000, 1e001, 1e002, 1e003, 1e004, 1e005, 1e006, 1e007, 1e008, 1e009,
524   1e010, 1e011, 1e012, 1e013, 1e014, 1e015, 1e016, 1e017, 1e018, 1e019,
525   1e020, 1e021, 1e022, 1e023, 1e024, 1e025, 1e026, 1e027, 1e028, 1e029,
526   1e030, 1e031, 1e032, 1e033, 1e034, 1e035, 1e036, 1e037, 1e038, 1e039,
527   1e040, 1e041, 1e042, 1e043, 1e044, 1e045, 1e046, 1e047, 1e048, 1e049,
528   1e050, 1e051, 1e052, 1e053, 1e054, 1e055, 1e056, 1e057, 1e058, 1e059,
529   1e060, 1e061, 1e062, 1e063, 1e064, 1e065, 1e066, 1e067, 1e068, 1e069,
530   1e070, 1e071, 1e072, 1e073, 1e074, 1e075, 1e076, 1e077, 1e078, 1e079,
531   1e080, 1e081, 1e082, 1e083, 1e084, 1e085, 1e086, 1e087, 1e088, 1e089,
532   1e090, 1e091, 1e092, 1e093, 1e094, 1e095, 1e096, 1e097, 1e098, 1e099,
533   1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109,
534   1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119,
535   1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129,
536   1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139,
537   1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149,
538   1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159,
539   1e160, 1e161, 1e162, 1e163, 1e164, 1e165, 1e166, 1e167, 1e168, 1e169,
540   1e170, 1e171, 1e172, 1e173, 1e174, 1e175, 1e176, 1e177, 1e178, 1e179,
541   1e180, 1e181, 1e182, 1e183, 1e184, 1e185, 1e186, 1e187, 1e188, 1e189,
542   1e190, 1e191, 1e192, 1e193, 1e194, 1e195, 1e196, 1e197, 1e198, 1e199,
543   1e200, 1e201, 1e202, 1e203, 1e204, 1e205, 1e206, 1e207, 1e208, 1e209,
544   1e210, 1e211, 1e212, 1e213, 1e214, 1e215, 1e216, 1e217, 1e218, 1e219,
545   1e220, 1e221, 1e222, 1e223, 1e224, 1e225, 1e226, 1e227, 1e228, 1e229,
546   1e230, 1e231, 1e232, 1e233, 1e234, 1e235, 1e236, 1e237, 1e238, 1e239,
547   1e240, 1e241, 1e242, 1e243, 1e244, 1e245, 1e246, 1e247, 1e248, 1e249,
548   1e250, 1e251, 1e252, 1e253, 1e254, 1e255, 1e256, 1e257, 1e258, 1e259,
549   1e260, 1e261, 1e262, 1e263, 1e264, 1e265, 1e266, 1e267, 1e268, 1e269,
550   1e270, 1e271, 1e272, 1e273, 1e274, 1e275, 1e276, 1e277, 1e278, 1e279,
551   1e280, 1e281, 1e282, 1e283, 1e284, 1e285, 1e286, 1e287, 1e288, 1e289,
552   1e290, 1e291, 1e292, 1e293, 1e294, 1e295, 1e296, 1e297, 1e298, 1e299,
553   1e300, 1e301, 1e302, 1e303, 1e304, 1e305, 1e306, 1e307, 1e308
554 };
555 
556 time_t server_start_time, flush_status_time;
557 
558 char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30];
559 char default_logfile_name[FN_REFLEN];
560 char *default_tz_name;
561 char log_error_file[FN_REFLEN], glob_hostname[FN_REFLEN];
562 char mysql_real_data_home[FN_REFLEN],
563      lc_messages_dir[FN_REFLEN], reg_ext[FN_EXTLEN],
564      mysql_charsets_dir[FN_REFLEN],
565      *opt_init_file, *opt_tc_log_file;
566 char *lc_messages_dir_ptr, *log_error_file_ptr;
567 char mysql_unpacked_real_data_home[FN_REFLEN];
568 int mysql_unpacked_real_data_home_len;
569 uint mysql_real_data_home_len, mysql_data_home_len= 1;
570 uint reg_ext_length;
571 const key_map key_map_empty(0);
572 key_map key_map_full(0);                        // Will be initialized later
573 char secure_file_real_path[FN_REFLEN];
574 
575 DATE_TIME_FORMAT global_date_format, global_datetime_format, global_time_format;
576 Time_zone *default_tz;
577 
578 char *mysql_data_home= const_cast<char*>(".");
579 const char *mysql_real_data_home_ptr= mysql_real_data_home;
580 char server_version[SERVER_VERSION_LENGTH];
581 char *mysqld_unix_port, *opt_mysql_tmpdir;
582 ulong thread_handling;
583 
584 /** name of reference on left expression in rewritten IN subquery */
585 const char *in_left_expr_name= "<left expr>";
586 /** name of additional condition */
587 const char *in_additional_cond= "<IN COND>";
588 const char *in_having_cond= "<IN HAVING>";
589 
590 my_decimal decimal_zero;
591 /* classes for comparation parsing/processing */
592 Eq_creator eq_creator;
593 Ne_creator ne_creator;
594 Gt_creator gt_creator;
595 Lt_creator lt_creator;
596 Ge_creator ge_creator;
597 Le_creator le_creator;
598 
599 MYSQL_FILE *bootstrap_file;
600 int bootstrap_error;
601 
602 I_List<THD> threads;
603 Rpl_filter* rpl_filter;
604 Rpl_filter* binlog_filter;
605 
first_global_thread()606 THD *first_global_thread()
607 {
608   if (threads.is_empty())
609     return NULL;
610   return threads.head();
611 }
612 
next_global_thread(THD * thd)613 THD *next_global_thread(THD *thd)
614 {
615   if (threads.is_last(thd))
616     return NULL;
617   struct ilink *next= thd->next;
618   return static_cast<THD*>(next);
619 }
620 
621 struct system_variables global_system_variables;
622 struct system_variables max_system_variables;
623 struct system_status_var global_status_var;
624 
625 MY_TMPDIR mysql_tmpdir_list;
626 MY_BITMAP temp_pool;
627 
628 CHARSET_INFO *system_charset_info, *files_charset_info ;
629 CHARSET_INFO *national_charset_info, *table_alias_charset;
630 CHARSET_INFO *character_set_filesystem;
631 CHARSET_INFO *error_message_charset_info;
632 
633 MY_LOCALE *my_default_lc_messages;
634 MY_LOCALE *my_default_lc_time_names;
635 
636 SHOW_COMP_OPTION have_ssl, have_symlink, have_dlopen, have_query_cache;
637 SHOW_COMP_OPTION have_geometry, have_rtree_keys;
638 SHOW_COMP_OPTION have_crypt, have_compress;
639 SHOW_COMP_OPTION have_profiling;
640 
641 /* Thread specific variables */
642 
643 pthread_key(MEM_ROOT**,THR_MALLOC);
644 pthread_key(THD*, THR_THD);
645 mysql_mutex_t LOCK_thread_created;
646 mysql_mutex_t LOCK_thread_count, LOCK_thd_remove;
647 mysql_mutex_t
648   LOCK_status, LOCK_error_log, LOCK_uuid_generator,
649   LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
650   LOCK_crypt,
651   LOCK_global_system_variables,
652   LOCK_user_conn, LOCK_slave_list, LOCK_active_mi,
653   LOCK_connection_count, LOCK_error_messages;
654 /**
655   The below lock protects access to two global server variables:
656   max_prepared_stmt_count and prepared_stmt_count. These variables
657   set the limit and hold the current total number of prepared statements
658   in the server, respectively. As PREPARE/DEALLOCATE rate in a loaded
659   server may be fairly high, we need a dedicated lock.
660 */
661 mysql_mutex_t LOCK_prepared_stmt_count;
662 #ifdef HAVE_OPENSSL
663 mysql_mutex_t LOCK_des_key_file;
664 #endif
665 mysql_rwlock_t LOCK_grant, LOCK_sys_init_connect, LOCK_sys_init_slave;
666 mysql_rwlock_t LOCK_system_variables_hash;
667 mysql_cond_t COND_thread_count;
668 pthread_t signal_thread;
669 pthread_attr_t connection_attrib;
670 mysql_mutex_t LOCK_server_started;
671 mysql_cond_t COND_server_started;
672 
673 int mysqld_server_started= 0;
674 
675 File_parser_dummy_hook file_parser_dummy_hook;
676 
677 /* replication parameters, if master_host is not NULL, we are a slave */
678 uint report_port= 0;
679 ulong master_retry_count=0;
680 char *master_info_file;
681 char *relay_log_info_file, *report_user, *report_password, *report_host;
682 char *opt_relay_logname = 0, *opt_relaylog_index_name=0;
683 char *opt_logname, *opt_slow_logname, *opt_bin_logname;
684 
685 /* Static variables */
686 
687 static volatile sig_atomic_t kill_in_progress;
688 
689 
690 static my_bool opt_bootstrap, opt_myisam_log;
691 static int cleanup_done;
692 static ulong opt_specialflag;
693 static char *opt_update_logname, *opt_binlog_index_name;
694 char *mysql_home_ptr, *pidfile_name_ptr;
695 /** Initial command line arguments (count), after load_defaults().*/
696 static int defaults_argc;
697 /**
698   Initial command line arguments (arguments), after load_defaults().
699   This memory is allocated by @c load_defaults() and should be freed
700   using @c free_defaults().
701   Do not modify defaults_argc / defaults_argv,
702   use remaining_argc / remaining_argv instead to parse the command
703   line arguments in multiple steps.
704 */
705 static char **defaults_argv;
706 /** Remaining command line arguments (count), filtered by handle_options().*/
707 static int remaining_argc;
708 /** Remaining command line arguments (arguments), filtered by handle_options().*/
709 static char **remaining_argv;
710 
711 int orig_argc;
712 char **orig_argv;
713 
714 /*
715   Since buffered_option_error_reporter is only used currently
716   for parsing performance schema options, this code is not needed
717   when the performance schema is not compiled in.
718 */
719 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
720 /**
721   A log message for the error log, buffered in memory.
722   Log messages are temporarily buffered when generated before the error log
723   is initialized, and then printed once the error log is ready.
724 */
725 class Buffered_log : public Sql_alloc
726 {
727 public:
728   Buffered_log(enum loglevel level, const char *message);
729 
~Buffered_log()730   ~Buffered_log()
731   {}
732 
733   void print(void);
734 
735 private:
736   /** Log message level. */
737   enum loglevel m_level;
738   /** Log message text. */
739   String m_message;
740 };
741 
742 /**
743   Constructor.
744   @param level          the message log level
745   @param message        the message text
746 */
Buffered_log(enum loglevel level,const char * message)747 Buffered_log::Buffered_log(enum loglevel level, const char *message)
748   : m_level(level), m_message()
749 {
750   m_message.copy(message, strlen(message), &my_charset_latin1);
751 }
752 
753 /**
754   Print a buffered log to the real log file.
755 */
print()756 void Buffered_log::print()
757 {
758   /*
759     Since messages are buffered, they can be printed out
760     of order with other entries in the log.
761     Add "Buffered xxx" to the message text to prevent confusion.
762   */
763   switch(m_level)
764   {
765   case ERROR_LEVEL:
766     sql_print_error("Buffered error: %s\n", m_message.c_ptr_safe());
767     break;
768   case WARNING_LEVEL:
769     sql_print_warning("Buffered warning: %s\n", m_message.c_ptr_safe());
770     break;
771   case INFORMATION_LEVEL:
772     /*
773       Messages printed as "information" still end up in the mysqld *error* log,
774       but with a [Note] tag instead of an [ERROR] tag.
775       While this is probably fine for a human reading the log,
776       it is upsetting existing automated scripts used to parse logs,
777       because such scripts are likely to not already handle [Note] properly.
778       INFORMATION_LEVEL messages are simply silenced, on purpose,
779       to avoid un needed verbosity.
780     */
781     break;
782   }
783 }
784 
785 /**
786   Collection of all the buffered log messages.
787 */
788 class Buffered_logs
789 {
790 public:
Buffered_logs()791   Buffered_logs()
792   {}
793 
~Buffered_logs()794   ~Buffered_logs()
795   {}
796 
797   void init();
798   void cleanup();
799 
800   void buffer(enum loglevel m_level, const char *msg);
801   void print();
802 private:
803   /**
804     Memory root to use to store buffered logs.
805     This memory root lifespan is between init and cleanup.
806     Once the buffered logs are printed, they are not needed anymore,
807     and all the memory used is reclaimed.
808   */
809   MEM_ROOT m_root;
810   /** List of buffered log messages. */
811   List<Buffered_log> m_list;
812 };
813 
init()814 void Buffered_logs::init()
815 {
816   init_alloc_root(&m_root, 1024, 0);
817 }
818 
cleanup()819 void Buffered_logs::cleanup()
820 {
821   m_list.delete_elements();
822   free_root(&m_root, MYF(0));
823 }
824 
825 /**
826   Add a log message to the buffer.
827 */
buffer(enum loglevel level,const char * msg)828 void Buffered_logs::buffer(enum loglevel level, const char *msg)
829 {
830   /*
831     Do not let Sql_alloc::operator new(size_t) allocate memory,
832     there is no memory root associated with the main() thread.
833     Give explicitly the proper memory root to use to
834     Sql_alloc::operator new(size_t, MEM_ROOT *) instead.
835   */
836   Buffered_log *log= new (&m_root) Buffered_log(level, msg);
837   if (log)
838     m_list.push_back(log, &m_root);
839 }
840 
841 /**
842   Print buffered log messages.
843 */
print()844 void Buffered_logs::print()
845 {
846   Buffered_log *log;
847   List_iterator_fast<Buffered_log> it(m_list);
848   while ((log= it++))
849     log->print();
850 }
851 
852 /** Logs reported before a logger is available. */
853 static Buffered_logs buffered_logs;
854 
855 #ifndef EMBEDDED_LIBRARY
856 /**
857   Error reporter that buffer log messages.
858   @param level          log message level
859   @param format         log message format string
860 */
861 C_MODE_START
buffered_option_error_reporter(enum loglevel level,const char * format,...)862 static void buffered_option_error_reporter(enum loglevel level,
863                                            const char *format, ...)
864 {
865   va_list args;
866   char buffer[1024];
867 
868   va_start(args, format);
869   my_vsnprintf(buffer, sizeof(buffer), format, args);
870   va_end(args);
871   buffered_logs.buffer(level, buffer);
872 }
873 C_MODE_END
874 #endif /* !EMBEDDED_LIBRARY */
875 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
876 
877 static my_socket unix_sock,ip_sock;
878 struct rand_struct sql_rand; ///< used by sql_class.cc:THD::THD()
879 
880 #ifndef EMBEDDED_LIBRARY
881 struct passwd *user_info;
882 static pthread_t select_thread;
883 static uint thr_kill_signal;
884 #endif
885 
886 /* OS specific variables */
887 
888 #ifdef __WIN__
889 #undef	 getpid
890 #include <process.h>
891 
892 static mysql_cond_t COND_handler_count;
893 static uint handler_count;
894 static bool start_mode=0, use_opt_args;
895 static int opt_argc;
896 static char **opt_argv;
897 
898 #if !defined(EMBEDDED_LIBRARY)
899 static HANDLE hEventShutdown;
900 static char shutdown_event_name[40];
901 #include "nt_servc.h"
902 static	 NTService  Service;	      ///< Service object for WinNT
903 #endif /* EMBEDDED_LIBRARY */
904 #endif /* __WIN__ */
905 
906 #ifdef _WIN32
907 static char pipe_name[512];
908 static SECURITY_ATTRIBUTES saPipeSecurity;
909 static SECURITY_DESCRIPTOR sdPipeDescriptor;
910 static HANDLE hPipe = INVALID_HANDLE_VALUE;
911 #endif
912 
913 #ifndef EMBEDDED_LIBRARY
914 bool mysqld_embedded=0;
915 #else
916 bool mysqld_embedded=1;
917 #endif
918 
919 static my_bool plugins_are_initialized= FALSE;
920 
921 #ifndef DBUG_OFF
922 static const char* default_dbug_option;
923 #endif
924 #ifdef HAVE_LIBWRAP
925 const char *libwrapName= NULL;
926 int allow_severity = LOG_INFO;
927 int deny_severity = LOG_WARNING;
928 #endif
929 #ifdef HAVE_QUERY_CACHE
930 ulong query_cache_min_res_unit= QUERY_CACHE_MIN_RESULT_DATA_SIZE;
931 Query_cache query_cache;
932 #endif
933 #ifdef HAVE_SMEM
934 char *shared_memory_base_name= default_shared_memory_base_name;
935 my_bool opt_enable_shared_memory;
936 HANDLE smem_event_connect_request= 0;
937 #endif
938 
939 my_bool opt_use_ssl  = 0;
940 char *opt_ssl_ca= NULL, *opt_ssl_capath= NULL, *opt_ssl_cert= NULL,
941      *opt_ssl_cipher= NULL, *opt_ssl_key= NULL;
942 
943 #ifdef HAVE_OPENSSL
944 #include <openssl/crypto.h>
945 #ifndef HAVE_YASSL
946 typedef struct CRYPTO_dynlock_value
947 {
948   mysql_rwlock_t lock;
949 } openssl_lock_t;
950 
951 static openssl_lock_t *openssl_stdlocks;
952 static openssl_lock_t *openssl_dynlock_create(const char *, int);
953 static void openssl_dynlock_destroy(openssl_lock_t *, const char *, int);
954 static void openssl_lock_function(int, int, const char *, int);
955 static void openssl_lock(int, openssl_lock_t *, const char *, int);
956 static unsigned long openssl_id_function();
957 #endif
958 char *des_key_file;
959 #ifndef EMBEDDED_LIBRARY
960 struct st_VioSSLFd *ssl_acceptor_fd;
961 #endif
962 #endif /* HAVE_OPENSSL */
963 
964 /**
965   Number of currently active user connections. The variable is protected by
966   LOCK_connection_count.
967 */
968 uint connection_count= 0;
969 
970 /* Function declarations */
971 
972 pthread_handler_t signal_hand(void *arg);
973 static int mysql_init_variables(void);
974 static int get_options(int *argc_ptr, char ***argv_ptr);
975 static bool add_terminator(DYNAMIC_ARRAY *options);
976 extern "C" my_bool mysqld_get_one_option(int, const struct my_option *, char *);
977 static void set_server_version(void);
978 static int init_thread_environment();
979 static char *get_relative_path(const char *path);
980 static int fix_paths(void);
981 void handle_connections_sockets();
982 #ifdef _WIN32
983 pthread_handler_t handle_connections_sockets_thread(void *arg);
984 #endif
985 pthread_handler_t kill_server_thread(void *arg);
986 static void bootstrap(MYSQL_FILE *file);
987 static bool read_init_file(char *file_name);
988 #ifdef _WIN32
989 pthread_handler_t handle_connections_namedpipes(void *arg);
990 #endif
991 #ifdef HAVE_SMEM
992 pthread_handler_t handle_connections_shared_memory(void *arg);
993 #endif
994 pthread_handler_t handle_slave(void *arg);
995 static void clean_up(bool print_message);
996 static int test_if_case_insensitive(const char *dir_name);
997 
998 #ifndef EMBEDDED_LIBRARY
999 static bool pid_file_created= false;
1000 static void usage(void);
1001 static void start_signal_handler(void);
1002 static void close_server_sock();
1003 static void clean_up_mutexes(void);
1004 static void wait_for_signal_thread_to_end(void);
1005 static void create_pid_file();
1006 static void mysqld_exit(int exit_code) __attribute__((noreturn));
1007 #endif
1008 static void delete_pid_file(myf flags);
1009 static void end_ssl();
1010 
1011 
1012 #ifndef EMBEDDED_LIBRARY
1013 /****************************************************************************
1014 ** Code to end mysqld
1015 ****************************************************************************/
1016 
close_connections(void)1017 static void close_connections(void)
1018 {
1019 #ifdef EXTRA_DEBUG
1020   int count=0;
1021 #endif
1022   DBUG_ENTER("close_connections");
1023 
1024   /* Clear thread cache */
1025   kill_cached_threads++;
1026   flush_thread_cache();
1027 
1028   /* kill connection thread */
1029 #if !defined(__WIN__)
1030   DBUG_PRINT("quit", ("waiting for select thread: 0x%lx",
1031                       (ulong) select_thread));
1032   mysql_mutex_lock(&LOCK_thread_count);
1033 
1034   while (select_thread_in_use)
1035   {
1036     struct timespec abstime;
1037     int error;
1038     LINT_INIT(error);
1039     DBUG_PRINT("info",("Waiting for select thread"));
1040 
1041 #ifndef DONT_USE_THR_ALARM
1042     if (pthread_kill(select_thread, thr_client_alarm))
1043       break;					// allready dead
1044 #endif
1045     set_timespec(abstime, 2);
1046     for (uint tmp=0 ; tmp < 10 && select_thread_in_use; tmp++)
1047     {
1048       error= mysql_cond_timedwait(&COND_thread_count, &LOCK_thread_count,
1049                                   &abstime);
1050       if (error != EINTR)
1051 	break;
1052     }
1053 #ifdef EXTRA_DEBUG
1054     if (error != 0 && !count++)
1055       sql_print_error("Got error %d from mysql_cond_timedwait", error);
1056 #endif
1057     close_server_sock();
1058   }
1059   mysql_mutex_unlock(&LOCK_thread_count);
1060 #endif /* __WIN__ */
1061 
1062 
1063   /* Abort listening to new connections */
1064   DBUG_PRINT("quit",("Closing sockets"));
1065   if (!opt_disable_networking )
1066   {
1067     if (ip_sock != INVALID_SOCKET)
1068     {
1069       (void) mysql_socket_shutdown(ip_sock, SHUT_RDWR);
1070       (void) closesocket(ip_sock);
1071       ip_sock= INVALID_SOCKET;
1072     }
1073   }
1074 #ifdef _WIN32
1075   if (hPipe != INVALID_HANDLE_VALUE && opt_enable_named_pipe)
1076   {
1077     HANDLE temp;
1078     DBUG_PRINT("quit", ("Closing named pipes") );
1079 
1080     /* Create connection to the handle named pipe handler to break the loop */
1081     if ((temp = CreateFile(pipe_name,
1082 			   GENERIC_READ | GENERIC_WRITE,
1083 			   0,
1084 			   NULL,
1085 			   OPEN_EXISTING,
1086 			   0,
1087 			   NULL )) != INVALID_HANDLE_VALUE)
1088     {
1089       WaitNamedPipe(pipe_name, 1000);
1090       DWORD dwMode = PIPE_READMODE_BYTE | PIPE_WAIT;
1091       SetNamedPipeHandleState(temp, &dwMode, NULL, NULL);
1092       CancelIo(temp);
1093       DisconnectNamedPipe(temp);
1094       CloseHandle(temp);
1095     }
1096   }
1097 #endif
1098 #ifdef HAVE_SYS_UN_H
1099   if (unix_sock != INVALID_SOCKET)
1100   {
1101     (void) mysql_socket_shutdown(unix_sock, SHUT_RDWR);
1102     (void) closesocket(unix_sock);
1103     (void) unlink(mysqld_unix_port);
1104     unix_sock= INVALID_SOCKET;
1105   }
1106 #endif
1107   end_thr_alarm(0);			 // Abort old alarms.
1108 
1109   /*
1110     First signal all threads that it's time to die
1111     This will give the threads some time to gracefully abort their
1112     statements and inform their clients that the server is about to die.
1113   */
1114 
1115   THD *tmp;
1116   mysql_mutex_lock(&LOCK_thread_count); // For unlink from list
1117 
1118   I_List_iterator<THD> it(threads);
1119   while ((tmp=it++))
1120   {
1121     DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
1122 		       tmp->thread_id));
1123     /* We skip slave threads & scheduler on this first loop through. */
1124     if (tmp->slave_thread)
1125       continue;
1126 
1127     tmp->killed= THD::KILL_CONNECTION;
1128     MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (tmp));
1129     mysql_mutex_lock(&tmp->LOCK_thd_data);
1130     if (tmp->mysys_var)
1131     {
1132       tmp->mysys_var->abort=1;
1133       mysql_mutex_lock(&tmp->mysys_var->mutex);
1134       if (tmp->mysys_var->current_cond)
1135       {
1136         mysql_mutex_lock(tmp->mysys_var->current_mutex);
1137         mysql_cond_broadcast(tmp->mysys_var->current_cond);
1138         mysql_mutex_unlock(tmp->mysys_var->current_mutex);
1139       }
1140       mysql_mutex_unlock(&tmp->mysys_var->mutex);
1141     }
1142     mysql_mutex_unlock(&tmp->LOCK_thd_data);
1143   }
1144   mysql_mutex_unlock(&LOCK_thread_count); // For unlink from list
1145 
1146   Events::deinit();
1147   end_slave();
1148 
1149   if (thread_count)
1150     sleep(2);					// Give threads time to die
1151 
1152   /*
1153     Force remaining threads to die by closing the connection to the client
1154     This will ensure that threads that are waiting for a command from the
1155     client on a blocking read call are aborted.
1156   */
1157 
1158   for (;;)
1159   {
1160     DBUG_PRINT("quit",("Locking LOCK_thread_count"));
1161     mysql_mutex_lock(&LOCK_thread_count); // For unlink from list
1162     if (!(tmp=threads.get()))
1163     {
1164       DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
1165       mysql_mutex_unlock(&LOCK_thread_count);
1166       break;
1167     }
1168 #ifndef __bsdi__				// Bug in BSDI kernel
1169     if (tmp->vio_ok())
1170     {
1171       if (global_system_variables.log_warnings)
1172         sql_print_warning(ER_DEFAULT(ER_FORCING_CLOSE),my_progname,
1173                           tmp->thread_id,
1174                           (tmp->main_security_ctx.user ?
1175                            tmp->main_security_ctx.user : ""));
1176       close_connection(tmp);
1177     }
1178 #endif
1179     DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
1180     mysql_mutex_unlock(&LOCK_thread_count);
1181   }
1182   /* All threads has now been aborted */
1183   DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count));
1184   mysql_mutex_lock(&LOCK_thread_count);
1185   while (thread_count)
1186   {
1187     mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
1188     DBUG_PRINT("quit",("One thread died (count=%u)",thread_count));
1189   }
1190   mysql_mutex_unlock(&LOCK_thread_count);
1191 
1192   close_active_mi();
1193   DBUG_PRINT("quit",("close_connections thread"));
1194   DBUG_VOID_RETURN;
1195 }
1196 
1197 
close_server_sock()1198 static void close_server_sock()
1199 {
1200 #ifdef HAVE_CLOSE_SERVER_SOCK
1201   DBUG_ENTER("close_server_sock");
1202   my_socket tmp_sock;
1203   tmp_sock=ip_sock;
1204   if (tmp_sock != INVALID_SOCKET)
1205   {
1206     ip_sock=INVALID_SOCKET;
1207     DBUG_PRINT("info",("calling shutdown on TCP/IP socket"));
1208     (void) mysql_socket_shutdown(tmp_sock, SHUT_RDWR);
1209   }
1210   tmp_sock=unix_sock;
1211   if (tmp_sock != INVALID_SOCKET)
1212   {
1213     unix_sock=INVALID_SOCKET;
1214     DBUG_PRINT("info",("calling shutdown on unix socket"));
1215     (void) mysql_socket_shutdown(tmp_sock, SHUT_RDWR);
1216     (void) unlink(mysqld_unix_port);
1217   }
1218   DBUG_VOID_RETURN;
1219 #endif
1220 }
1221 
1222 #endif /*EMBEDDED_LIBRARY*/
1223 
1224 
kill_mysql(void)1225 void kill_mysql(void)
1226 {
1227   DBUG_ENTER("kill_mysql");
1228 
1229 #if defined(SIGNALS_DONT_BREAK_READ) && !defined(EMBEDDED_LIBRARY)
1230   abort_loop=1;					// Break connection loops
1231   close_server_sock();				// Force accept to wake up
1232 #endif
1233 
1234 #if defined(__WIN__)
1235 #if !defined(EMBEDDED_LIBRARY)
1236   {
1237     if (!SetEvent(hEventShutdown))
1238     {
1239       DBUG_PRINT("error",("Got error: %ld from SetEvent",GetLastError()));
1240     }
1241     /*
1242       or:
1243       HANDLE hEvent=OpenEvent(0, FALSE, "MySqlShutdown");
1244       SetEvent(hEventShutdown);
1245       CloseHandle(hEvent);
1246     */
1247   }
1248 #endif
1249 #elif defined(HAVE_PTHREAD_KILL)
1250   if (pthread_kill(signal_thread, MYSQL_KILL_SIGNAL))
1251   {
1252     DBUG_PRINT("error",("Got error %d from pthread_kill",errno)); /* purecov: inspected */
1253   }
1254 #elif !defined(SIGNALS_DONT_BREAK_READ)
1255   kill(current_pid, MYSQL_KILL_SIGNAL);
1256 #endif
1257   DBUG_PRINT("quit",("After pthread_kill"));
1258   shutdown_in_progress=1;			// Safety if kill didn't work
1259 #ifdef SIGNALS_DONT_BREAK_READ
1260   if (!kill_in_progress)
1261   {
1262     pthread_t tmp;
1263     int error;
1264     abort_loop=1;
1265     if ((error= mysql_thread_create(0, /* Not instrumented */
1266                                     &tmp, &connection_attrib,
1267                                     kill_server_thread, (void*) 0)))
1268       sql_print_error("Can't create thread to kill server (errno= %d).", error);
1269   }
1270 #endif
1271   DBUG_VOID_RETURN;
1272 }
1273 
1274 /**
1275   Force server down. Kill all connections and threads and exit.
1276 
1277   @param  sig_ptr       Signal number that caused kill_server to be called.
1278 
1279   @note
1280     A signal number of 0 mean that the function was not called
1281     from a signal handler and there is thus no signal to block
1282     or stop, we just want to kill the server.
1283 */
1284 
1285 #if !defined(__WIN__)
kill_server(void * sig_ptr)1286 static void *kill_server(void *sig_ptr)
1287 #define RETURN_FROM_KILL_SERVER return 0
1288 #else
1289 static void __cdecl kill_server(int sig_ptr)
1290 #define RETURN_FROM_KILL_SERVER return
1291 #endif
1292 {
1293   DBUG_ENTER("kill_server");
1294 #ifndef EMBEDDED_LIBRARY
1295   int sig=(int) (long) sig_ptr;			// This is passed a int
1296   // if there is a signal during the kill in progress, ignore the other
1297   if (kill_in_progress)				// Safety
1298   {
1299     DBUG_LEAVE;
1300     RETURN_FROM_KILL_SERVER;
1301   }
1302   kill_in_progress=TRUE;
1303   abort_loop=1;					// This should be set
1304   if (sig != 0) // 0 is not a valid signal number
1305     my_sigset(sig, SIG_IGN);                    /* purify inspected */
1306   if (sig == MYSQL_KILL_SIGNAL || sig == 0)
1307     sql_print_information(ER_DEFAULT(ER_NORMAL_SHUTDOWN),my_progname);
1308   else
1309     sql_print_error(ER_DEFAULT(ER_GOT_SIGNAL),my_progname,sig); /* purecov: inspected */
1310 
1311 #if defined(HAVE_SMEM) && defined(__WIN__)
1312   /*
1313    Send event to smem_event_connect_request for aborting
1314    */
1315   if (opt_enable_shared_memory)
1316   {
1317     if (!SetEvent(smem_event_connect_request))
1318     {
1319       DBUG_PRINT("error",
1320                  ("Got error: %ld from SetEvent of smem_event_connect_request",
1321                   GetLastError()));
1322     }
1323   }
1324 #endif
1325 
1326   close_connections();
1327   if (sig != MYSQL_KILL_SIGNAL &&
1328       sig != 0)
1329     unireg_abort(1);				/* purecov: inspected */
1330   else
1331     unireg_end();
1332 
1333   /* purecov: begin deadcode */
1334   DBUG_LEAVE;                                   // Must match DBUG_ENTER()
1335   my_thread_end();
1336   pthread_exit(0);
1337   /* purecov: end */
1338 
1339   RETURN_FROM_KILL_SERVER;                      // Avoid compiler warnings
1340 
1341 #else /* EMBEDDED_LIBRARY*/
1342 
1343   DBUG_LEAVE;
1344   RETURN_FROM_KILL_SERVER;
1345 
1346 #endif /* EMBEDDED_LIBRARY */
1347 }
1348 
1349 
1350 #if defined(USE_ONE_SIGNAL_HAND)
kill_server_thread(void * arg)1351 pthread_handler_t kill_server_thread(void *arg __attribute__((unused)))
1352 {
1353   my_thread_init();				// Initialize new thread
1354   kill_server(0);
1355   /* purecov: begin deadcode */
1356   my_thread_end();
1357   pthread_exit(0);
1358   return 0;
1359   /* purecov: end */
1360 }
1361 #endif
1362 
1363 
print_signal_warning(int sig)1364 extern "C" sig_handler print_signal_warning(int sig)
1365 {
1366   if (global_system_variables.log_warnings)
1367     sql_print_warning("Got signal %d from thread %ld", sig,my_thread_id());
1368 #ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY
1369   my_sigset(sig,print_signal_warning);		/* int. thread system calls */
1370 #endif
1371 #if !defined(__WIN__)
1372   if (sig == SIGALRM)
1373     alarm(2);					/* reschedule alarm */
1374 #endif
1375 }
1376 
1377 #ifndef EMBEDDED_LIBRARY
1378 
init_error_log_mutex()1379 static void init_error_log_mutex()
1380 {
1381   mysql_mutex_init(key_LOCK_error_log, &LOCK_error_log, MY_MUTEX_INIT_FAST);
1382 }
1383 
1384 
clean_up_error_log_mutex()1385 static void clean_up_error_log_mutex()
1386 {
1387   mysql_mutex_destroy(&LOCK_error_log);
1388 }
1389 
1390 
1391 /**
1392   cleanup all memory and end program nicely.
1393 
1394     If SIGNALS_DONT_BREAK_READ is defined, this function is called
1395     by the main thread. To get MySQL to shut down nicely in this case
1396     (Mac OS X) we have to call exit() instead if pthread_exit().
1397 
1398   @note
1399     This function never returns.
1400 */
unireg_end(void)1401 void unireg_end(void)
1402 {
1403   clean_up(1);
1404   my_thread_end();
1405 #if defined(SIGNALS_DONT_BREAK_READ)
1406   exit(0);
1407 #else
1408   pthread_exit(0);				// Exit is in main thread
1409 #endif
1410 }
1411 
1412 
unireg_abort(int exit_code)1413 extern "C" void unireg_abort(int exit_code)
1414 {
1415   DBUG_ENTER("unireg_abort");
1416 
1417   if (opt_help)
1418     usage();
1419   if (exit_code)
1420     sql_print_error("Aborting\n");
1421   clean_up(!opt_help && (exit_code || !opt_bootstrap)); /* purecov: inspected */
1422   DBUG_PRINT("quit",("done with cleanup in unireg_abort"));
1423   mysqld_exit(exit_code);
1424 }
1425 
mysqld_exit(int exit_code)1426 static void mysqld_exit(int exit_code)
1427 {
1428   /*
1429     Important note: we wait for the signal thread to end,
1430     but if a kill -15 signal was sent, the signal thread did
1431     spawn the kill_server_thread thread, which is running concurrently.
1432   */
1433   wait_for_signal_thread_to_end();
1434   mysql_audit_finalize();
1435   clean_up_mutexes();
1436   clean_up_error_log_mutex();
1437 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
1438   /*
1439     Bug#56666 needs to be fixed before calling:
1440     shutdown_performance_schema();
1441   */
1442 #endif
1443   my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
1444   exit(exit_code); /* purecov: inspected */
1445 }
1446 
1447 #endif /* !EMBEDDED_LIBRARY */
1448 
clean_up(bool print_message)1449 void clean_up(bool print_message)
1450 {
1451   DBUG_PRINT("exit",("clean_up"));
1452   if (cleanup_done++)
1453     return; /* purecov: inspected */
1454 
1455   stop_handle_manager();
1456   release_ddl_log();
1457 
1458   /*
1459     make sure that handlers finish up
1460     what they have that is dependent on the binlog
1461   */
1462   ha_binlog_end(current_thd);
1463 
1464   logger.cleanup_base();
1465 
1466   injector::free_instance();
1467   mysql_bin_log.cleanup();
1468 
1469 #ifdef HAVE_REPLICATION
1470   if (use_slave_mask)
1471     bitmap_free(&slave_error_mask);
1472 #endif
1473   my_tz_free();
1474   my_dboptions_cache_free();
1475 #ifndef NO_EMBEDDED_ACCESS_CHECKS
1476   servers_free(1);
1477   acl_free(1);
1478   grant_free();
1479 #endif
1480   query_cache_destroy();
1481   hostname_cache_free();
1482   item_user_lock_free();
1483   lex_free();				/* Free some memory */
1484   item_create_cleanup();
1485   if (!opt_noacl)
1486   {
1487 #ifdef HAVE_DLOPEN
1488     udf_free();
1489 #endif
1490   }
1491   table_def_start_shutdown();
1492   plugin_shutdown();
1493   ha_end();
1494   if (tc_log)
1495     tc_log->close();
1496   delegates_destroy();
1497   xid_cache_free();
1498   table_def_free();
1499   mdl_destroy();
1500   key_caches.delete_elements((void (*)(const char*, uchar*)) free_key_cache);
1501   multi_keycache_free();
1502   free_status_vars();
1503   end_thr_alarm(1);			/* Free allocated memory */
1504   my_free_open_file_info();
1505   if (defaults_argv)
1506     free_defaults(defaults_argv);
1507   free_tmpdir(&mysql_tmpdir_list);
1508   my_free(opt_bin_logname);
1509   bitmap_free(&temp_pool);
1510   free_max_user_conn();
1511 #ifdef HAVE_REPLICATION
1512   end_slave_list();
1513 #endif
1514   delete binlog_filter;
1515   delete rpl_filter;
1516   end_ssl();
1517   vio_end();
1518   my_regex_end();
1519 #if defined(ENABLED_DEBUG_SYNC)
1520   /* End the debug sync facility. See debug_sync.cc. */
1521   debug_sync_end();
1522 #endif /* defined(ENABLED_DEBUG_SYNC) */
1523 
1524   delete_pid_file(MYF(0));
1525 
1526   if (print_message && my_default_lc_messages && server_start_time)
1527     sql_print_information(ER_DEFAULT(ER_SHUTDOWN_COMPLETE),my_progname);
1528   cleanup_errmsgs();
1529   MYSQL_CALLBACK(thread_scheduler, end, ());
1530   mysql_client_plugin_deinit();
1531   finish_client_errs();
1532   (void) my_error_unregister(ER_ERROR_FIRST, ER_ERROR_LAST); // finish server errs
1533   DBUG_PRINT("quit", ("Error messages freed"));
1534   /* Tell main we are ready */
1535   logger.cleanup_end();
1536   my_atomic_rwlock_destroy(&global_query_id_lock);
1537   my_atomic_rwlock_destroy(&thread_running_lock);
1538   free_charsets();
1539   mysql_mutex_lock(&LOCK_thread_count);
1540   DBUG_PRINT("quit", ("got thread count lock"));
1541   ready_to_exit=1;
1542   /* do the broadcast inside the lock to ensure that my_end() is not called */
1543   mysql_cond_broadcast(&COND_thread_count);
1544   mysql_mutex_unlock(&LOCK_thread_count);
1545   sys_var_end();
1546 
1547   /*
1548     The following lines may never be executed as the main thread may have
1549     killed us
1550   */
1551   DBUG_PRINT("quit", ("done with cleanup"));
1552 } /* clean_up */
1553 
1554 
1555 #ifndef EMBEDDED_LIBRARY
1556 
1557 /**
1558   This is mainly needed when running with purify, but it's still nice to
1559   know that all child threads have died when mysqld exits.
1560 */
wait_for_signal_thread_to_end()1561 static void wait_for_signal_thread_to_end()
1562 {
1563   uint i;
1564   /*
1565     Wait up to 10 seconds for signal thread to die. We use this mainly to
1566     avoid getting warnings that my_thread_end has not been called
1567   */
1568   for (i= 0 ; i < 100 && signal_thread_in_use; i++)
1569   {
1570     if (pthread_kill(signal_thread, MYSQL_KILL_SIGNAL) != ESRCH)
1571       break;
1572     my_sleep(100);				// Give it time to die
1573   }
1574 }
1575 
1576 
clean_up_mutexes()1577 static void clean_up_mutexes()
1578 {
1579   mysql_rwlock_destroy(&LOCK_grant);
1580   mysql_mutex_destroy(&LOCK_thread_count);
1581   mysql_mutex_destroy(&LOCK_thread_created);
1582   mysql_mutex_destroy(&LOCK_status);
1583   mysql_mutex_destroy(&LOCK_delayed_insert);
1584   mysql_mutex_destroy(&LOCK_delayed_status);
1585   mysql_mutex_destroy(&LOCK_delayed_create);
1586   mysql_mutex_destroy(&LOCK_manager);
1587   mysql_mutex_destroy(&LOCK_crypt);
1588   mysql_mutex_destroy(&LOCK_user_conn);
1589   mysql_mutex_destroy(&LOCK_connection_count);
1590 #ifdef HAVE_OPENSSL
1591   mysql_mutex_destroy(&LOCK_des_key_file);
1592 #ifndef HAVE_YASSL
1593   for (int i= 0; i < CRYPTO_num_locks(); ++i)
1594     mysql_rwlock_destroy(&openssl_stdlocks[i].lock);
1595   OPENSSL_free(openssl_stdlocks);
1596 #endif
1597 #endif
1598 #ifdef HAVE_REPLICATION
1599   mysql_mutex_destroy(&LOCK_rpl_status);
1600   mysql_cond_destroy(&COND_rpl_status);
1601 #endif
1602   mysql_mutex_destroy(&LOCK_active_mi);
1603   mysql_rwlock_destroy(&LOCK_sys_init_connect);
1604   mysql_rwlock_destroy(&LOCK_sys_init_slave);
1605   mysql_mutex_destroy(&LOCK_global_system_variables);
1606   mysql_rwlock_destroy(&LOCK_system_variables_hash);
1607   mysql_mutex_destroy(&LOCK_uuid_generator);
1608   mysql_mutex_destroy(&LOCK_prepared_stmt_count);
1609   mysql_mutex_destroy(&LOCK_error_messages);
1610   mysql_cond_destroy(&COND_thread_count);
1611   mysql_mutex_destroy(&LOCK_thd_remove);
1612   mysql_cond_destroy(&COND_thread_cache);
1613   mysql_cond_destroy(&COND_flush_thread_cache);
1614   mysql_cond_destroy(&COND_manager);
1615 }
1616 #endif /*EMBEDDED_LIBRARY*/
1617 
1618 
1619 /****************************************************************************
1620 ** Init IP and UNIX socket
1621 ****************************************************************************/
1622 
1623 #ifndef EMBEDDED_LIBRARY
set_ports()1624 static void set_ports()
1625 {
1626   char	*env;
1627   if (!mysqld_port && !opt_disable_networking)
1628   {					// Get port if not from commandline
1629     mysqld_port= MYSQL_PORT;
1630 
1631     /*
1632       if builder specifically requested a default port, use that
1633       (even if it coincides with our factory default).
1634       only if they didn't do we check /etc/services (and, failing
1635       on that, fall back to the factory default of 3306).
1636       either default can be overridden by the environment variable
1637       MYSQL_TCP_PORT, which in turn can be overridden with command
1638       line options.
1639     */
1640 
1641 #if MYSQL_PORT_DEFAULT == 0
1642     struct  servent *serv_ptr;
1643     if ((serv_ptr= getservbyname("mysql", "tcp")))
1644       mysqld_port= ntohs((u_short) serv_ptr->s_port); /* purecov: inspected */
1645 #endif
1646     if ((env = getenv("MYSQL_TCP_PORT")))
1647       mysqld_port= (uint) atoi(env);		/* purecov: inspected */
1648   }
1649   if (!mysqld_unix_port)
1650   {
1651 #ifdef __WIN__
1652     mysqld_unix_port= (char*) MYSQL_NAMEDPIPE;
1653 #else
1654     mysqld_unix_port= (char*) MYSQL_UNIX_ADDR;
1655 #endif
1656     if ((env = getenv("MYSQL_UNIX_PORT")))
1657       mysqld_unix_port= env;			/* purecov: inspected */
1658   }
1659 }
1660 
1661 /* Change to run as another user if started with --user */
1662 
check_user(const char * user)1663 static struct passwd *check_user(const char *user)
1664 {
1665 #if !defined(__WIN__)
1666   struct passwd *tmp_user_info;
1667   uid_t user_id= geteuid();
1668 
1669   // Don't bother if we aren't superuser
1670   if (user_id)
1671   {
1672     if (user)
1673     {
1674       /* Don't give a warning, if real user is same as given with --user */
1675       /* purecov: begin tested */
1676       tmp_user_info= getpwnam(user);
1677       if ((!tmp_user_info || user_id != tmp_user_info->pw_uid) &&
1678 	  global_system_variables.log_warnings)
1679         sql_print_warning(
1680                     "One can only use the --user switch if running as root\n");
1681       /* purecov: end */
1682     }
1683     return NULL;
1684   }
1685   if (!user)
1686   {
1687     if (!opt_bootstrap && !opt_help)
1688     {
1689       sql_print_error("Fatal error: Please read \"Security\" section of the manual to find out how to run mysqld as root!\n");
1690       unireg_abort(1);
1691     }
1692     return NULL;
1693   }
1694   /* purecov: begin tested */
1695   if (!strcmp(user,"root"))
1696     return NULL;                        // Avoid problem with dynamic libraries
1697 
1698   if (!(tmp_user_info= getpwnam(user)))
1699   {
1700     // Allow a numeric uid to be used
1701     const char *pos;
1702     for (pos= user; my_isdigit(mysqld_charset,*pos); pos++) ;
1703     if (*pos)                                   // Not numeric id
1704       goto err;
1705     if (!(tmp_user_info= getpwuid(atoi(user))))
1706       goto err;
1707   }
1708   return tmp_user_info;
1709   /* purecov: end */
1710 
1711 err:
1712   sql_print_error("Fatal error: Can't change to run as user '%s' ;  Please check that the user exists!\n",user);
1713   unireg_abort(1);
1714 
1715 #ifdef PR_SET_DUMPABLE
1716   if (test_flags & TEST_CORE_ON_SIGNAL)
1717   {
1718     /* inform kernel that process is dumpable */
1719     (void) prctl(PR_SET_DUMPABLE, 1);
1720   }
1721 #endif
1722 
1723 #endif
1724   return NULL;
1725 }
1726 
set_user(const char * user,struct passwd * user_info_arg)1727 static void set_user(const char *user, struct passwd *user_info_arg)
1728 {
1729   /* purecov: begin tested */
1730 #if !defined(__WIN__)
1731   DBUG_ASSERT(user_info_arg != 0);
1732 #ifdef HAVE_INITGROUPS
1733   /*
1734     We can get a SIGSEGV when calling initgroups() on some systems when NSS
1735     is configured to use LDAP and the server is statically linked.  We set
1736     calling_initgroups as a flag to the SIGSEGV handler that is then used to
1737     output a specific message to help the user resolve this problem.
1738   */
1739   calling_initgroups= 1;
1740   initgroups((char*) user, user_info_arg->pw_gid);
1741   calling_initgroups= 0;
1742 #endif
1743   if (setgid(user_info_arg->pw_gid) == -1)
1744   {
1745     sql_perror("setgid");
1746     unireg_abort(1);
1747   }
1748   if (setuid(user_info_arg->pw_uid) == -1)
1749   {
1750     sql_perror("setuid");
1751     unireg_abort(1);
1752   }
1753 #endif
1754   /* purecov: end */
1755 }
1756 
1757 
set_effective_user(struct passwd * user_info_arg)1758 static void set_effective_user(struct passwd *user_info_arg)
1759 {
1760 #if !defined(__WIN__)
1761   DBUG_ASSERT(user_info_arg != 0);
1762   if (setregid((gid_t)-1, user_info_arg->pw_gid) == -1)
1763   {
1764     sql_perror("setregid");
1765     unireg_abort(1);
1766   }
1767   if (setreuid((uid_t)-1, user_info_arg->pw_uid) == -1)
1768   {
1769     sql_perror("setreuid");
1770     unireg_abort(1);
1771   }
1772 #endif
1773 }
1774 
1775 
1776 /** Change root user if started with @c --chroot . */
set_root(const char * path)1777 static void set_root(const char *path)
1778 {
1779 #if !defined(__WIN__)
1780   if (chroot(path) == -1)
1781   {
1782     sql_perror("chroot");
1783     unireg_abort(1);
1784   }
1785   my_setwd("/", MYF(0));
1786 #endif
1787 }
1788 
1789 
create_socket(const struct addrinfo * addrinfo_list,int addr_family,struct addrinfo ** use_addrinfo)1790 static my_socket create_socket(const struct addrinfo *addrinfo_list,
1791                                int addr_family,
1792                                struct addrinfo **use_addrinfo)
1793 {
1794   my_socket sock= INVALID_SOCKET;
1795 
1796   for (const struct addrinfo *cur_ai= addrinfo_list; cur_ai != NULL;
1797        cur_ai= cur_ai->ai_next)
1798   {
1799     if (cur_ai->ai_family != addr_family)
1800       continue;
1801 
1802     sock= socket(cur_ai->ai_family, cur_ai->ai_socktype, cur_ai->ai_protocol);
1803 
1804     char ip_addr[INET6_ADDRSTRLEN];
1805 
1806     if (vio_get_normalized_ip_string(cur_ai->ai_addr, cur_ai->ai_addrlen,
1807                                      ip_addr, sizeof (ip_addr)))
1808     {
1809       ip_addr[0]= 0;
1810     }
1811 
1812     if (sock == INVALID_SOCKET)
1813     {
1814       sql_print_error("Failed to create a socket for %s '%s': errno: %d.",
1815                       (addr_family == AF_INET) ? "IPv4" : "IPv6",
1816                       (const char *) ip_addr,
1817                       (int) socket_errno);
1818       continue;
1819     }
1820 
1821     sql_print_information("Server socket created on IP: '%s'.",
1822                           (const char *) ip_addr);
1823 
1824     *use_addrinfo= (struct addrinfo *)cur_ai;
1825     return sock;
1826   }
1827 
1828   return INVALID_SOCKET;
1829 }
1830 
1831 
network_init(void)1832 static void network_init(void)
1833 {
1834 #ifdef HAVE_SYS_UN_H
1835   struct sockaddr_un	UNIXaddr;
1836 #endif
1837   int	arg;
1838   int   ret;
1839   uint  waited;
1840   uint  this_wait;
1841   uint  retry;
1842   char port_buf[NI_MAXSERV];
1843   DBUG_ENTER("network_init");
1844   LINT_INIT(ret);
1845 
1846   if (MYSQL_CALLBACK_ELSE(thread_scheduler, init, (), 0))
1847     unireg_abort(1);			/* purecov: inspected */
1848 
1849   set_ports();
1850 
1851   if (report_port == 0)
1852   {
1853     report_port= mysqld_port;
1854   }
1855 
1856 #ifndef DBUG_OFF
1857   if (!opt_disable_networking)
1858     DBUG_ASSERT(report_port != 0);
1859 #endif
1860 
1861   if (mysqld_port != 0 && !opt_disable_networking && !opt_bootstrap)
1862   {
1863     struct addrinfo *ai, *a;
1864     struct addrinfo hints;
1865     const char *bind_address= my_bind_addr_str;
1866 
1867     if (!bind_address)
1868       bind_address= "0.0.0.0";
1869 
1870     sql_print_information("Server hostname (bind-address): '%s'; port: %d",
1871                           bind_address, mysqld_port);
1872 
1873     // Get list of IP-addresses associated with the server hostname.
1874     bzero(&hints, sizeof (hints));
1875     hints.ai_flags= AI_PASSIVE;
1876     hints.ai_socktype= SOCK_STREAM;
1877     hints.ai_family= AF_UNSPEC;
1878 
1879     my_snprintf(port_buf, NI_MAXSERV, "%d", mysqld_port);
1880     if (getaddrinfo(bind_address, port_buf, &hints, &ai))
1881     {
1882       sql_perror(ER_DEFAULT(ER_IPSOCK_ERROR));  /* purecov: tested */
1883       sql_print_error("Can't start server: cannot resolve hostname!");
1884       unireg_abort(1);				/* purecov: tested */
1885     }
1886 
1887     // Log all the IP-addresses.
1888     for (struct addrinfo *cur_ai= ai; cur_ai != NULL; cur_ai= cur_ai->ai_next)
1889     {
1890       char ip_addr[INET6_ADDRSTRLEN];
1891 
1892       if (vio_get_normalized_ip_string(cur_ai->ai_addr, cur_ai->ai_addrlen,
1893                                        ip_addr, sizeof (ip_addr)))
1894       {
1895         sql_print_error("Fails to print out IP-address.");
1896         continue;
1897       }
1898 
1899       sql_print_information("  - '%s' resolves to '%s';",
1900                             bind_address, ip_addr);
1901     }
1902 
1903     /*
1904       If the 'bind-address' option specifies the hostname, which resolves to
1905       multiple IP-address, use the following rule:
1906       - if there are IPv4-addresses, use the first IPv4-address
1907       returned by getaddrinfo();
1908       - if there are IPv6-addresses, use the first IPv6-address
1909       returned by getaddrinfo();
1910     */
1911 
1912     ip_sock= create_socket(ai, AF_INET, &a);
1913 
1914     if (ip_sock == INVALID_SOCKET)
1915       ip_sock= create_socket(ai, AF_INET6, &a);
1916 
1917     // Report user-error if we failed to create a socket.
1918     if (ip_sock == INVALID_SOCKET)
1919     {
1920       sql_perror(ER_DEFAULT(ER_IPSOCK_ERROR));  /* purecov: tested */
1921       unireg_abort(1);                          /* purecov: tested */
1922     }
1923 #ifndef __WIN__
1924     /*
1925       We should not use SO_REUSEADDR on windows as this would enable a
1926       user to open two mysqld servers with the same TCP/IP port.
1927     */
1928     arg= 1;
1929     (void) setsockopt(ip_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,sizeof(arg));
1930 #endif /* __WIN__ */
1931 
1932 #ifdef IPV6_V6ONLY
1933      /*
1934        For interoperability with older clients, IPv6 socket should
1935        listen on both IPv6 and IPv4 wildcard addresses.
1936        Turn off IPV6_V6ONLY option.
1937 
1938        NOTE: this will work starting from Windows Vista only.
1939        On Windows XP dual stack is not available, so it will not
1940        listen on the corresponding IPv4-address.
1941      */
1942     if (a->ai_family == AF_INET6)
1943     {
1944       arg= 0;
1945       (void) setsockopt(ip_sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
1946                 sizeof(arg));
1947     }
1948 #endif
1949     /*
1950       Sometimes the port is not released fast enough when stopping and
1951       restarting the server. This happens quite often with the test suite
1952       on busy Linux systems. Retry to bind the address at these intervals:
1953       Sleep intervals: 1, 2, 4,  6,  9, 13, 17, 22, ...
1954       Retry at second: 1, 3, 7, 13, 22, 35, 52, 74, ...
1955       Limit the sequence by mysqld_port_timeout (set --port-open-timeout=#).
1956     */
1957     for (waited= 0, retry= 1; ; retry++, waited+= this_wait)
1958     {
1959       if (((ret= bind(ip_sock, a->ai_addr, a->ai_addrlen)) >= 0 ) ||
1960           (socket_errno != SOCKET_EADDRINUSE) ||
1961           (waited >= mysqld_port_timeout))
1962         break;
1963       sql_print_information("Retrying bind on TCP/IP port %u", mysqld_port);
1964       this_wait= retry * retry / 3 + 1;
1965       sleep(this_wait);
1966     }
1967     freeaddrinfo(ai);
1968     if (ret < 0)
1969     {
1970       DBUG_PRINT("error",("Got error: %d from bind",socket_errno));
1971       sql_perror("Can't start server: Bind on TCP/IP port");
1972       sql_print_error("Do you already have another mysqld server running on port: %d ?",mysqld_port);
1973       unireg_abort(1);
1974     }
1975     if (listen(ip_sock,(int) back_log) < 0)
1976     {
1977       sql_perror("Can't start server: listen() on TCP/IP port");
1978       sql_print_error("listen() on TCP/IP failed with error %d",
1979 		      socket_errno);
1980       unireg_abort(1);
1981     }
1982   }
1983 
1984 #ifdef _WIN32
1985   /* create named pipe */
1986   if (Service.IsNT() && mysqld_unix_port[0] && !opt_bootstrap &&
1987       opt_enable_named_pipe)
1988   {
1989     strxnmov(pipe_name, sizeof(pipe_name)-1, "\\\\.\\pipe\\",
1990 	     mysqld_unix_port, NullS);
1991     bzero((char*) &saPipeSecurity, sizeof(saPipeSecurity));
1992     bzero((char*) &sdPipeDescriptor, sizeof(sdPipeDescriptor));
1993     if (!InitializeSecurityDescriptor(&sdPipeDescriptor,
1994 				      SECURITY_DESCRIPTOR_REVISION))
1995     {
1996       sql_perror("Can't start server : Initialize security descriptor");
1997       unireg_abort(1);
1998     }
1999     if (!SetSecurityDescriptorDacl(&sdPipeDescriptor, TRUE, NULL, FALSE))
2000     {
2001       sql_perror("Can't start server : Set security descriptor");
2002       unireg_abort(1);
2003     }
2004     saPipeSecurity.nLength = sizeof(SECURITY_ATTRIBUTES);
2005     saPipeSecurity.lpSecurityDescriptor = &sdPipeDescriptor;
2006     saPipeSecurity.bInheritHandle = FALSE;
2007     if ((hPipe= CreateNamedPipe(pipe_name,
2008 				PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED,
2009 				PIPE_TYPE_BYTE |
2010 				PIPE_READMODE_BYTE |
2011 				PIPE_WAIT,
2012 				PIPE_UNLIMITED_INSTANCES,
2013 				(int) global_system_variables.net_buffer_length,
2014 				(int) global_system_variables.net_buffer_length,
2015 				NMPWAIT_USE_DEFAULT_WAIT,
2016 				&saPipeSecurity)) == INVALID_HANDLE_VALUE)
2017       {
2018 	LPVOID lpMsgBuf;
2019 	int error=GetLastError();
2020 	FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
2021 		      FORMAT_MESSAGE_FROM_SYSTEM,
2022 		      NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
2023 		      (LPTSTR) &lpMsgBuf, 0, NULL );
2024 	sql_perror((char *)lpMsgBuf);
2025 	LocalFree(lpMsgBuf);
2026 	unireg_abort(1);
2027       }
2028   }
2029 #endif
2030 
2031 #if defined(HAVE_SYS_UN_H)
2032   /*
2033   ** Create the UNIX socket
2034   */
2035   if (mysqld_unix_port[0] && !opt_bootstrap)
2036   {
2037     DBUG_PRINT("general",("UNIX Socket is %s",mysqld_unix_port));
2038 
2039     if (strlen(mysqld_unix_port) > (sizeof(UNIXaddr.sun_path) - 1))
2040     {
2041       sql_print_error("The socket file path is too long (> %u): %s",
2042                       (uint) sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port);
2043       unireg_abort(1);
2044     }
2045     if ((unix_sock= socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
2046     {
2047       sql_perror("Can't start server : UNIX Socket "); /* purecov: inspected */
2048       unireg_abort(1);				/* purecov: inspected */
2049     }
2050     bzero((char*) &UNIXaddr, sizeof(UNIXaddr));
2051     UNIXaddr.sun_family = AF_UNIX;
2052     strmov(UNIXaddr.sun_path, mysqld_unix_port);
2053     (void) unlink(mysqld_unix_port);
2054     arg= 1;
2055     (void) setsockopt(unix_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,
2056 		      sizeof(arg));
2057     umask(0);
2058     if (bind(unix_sock, reinterpret_cast<struct sockaddr *>(&UNIXaddr),
2059 	     sizeof(UNIXaddr)) < 0)
2060     {
2061       sql_perror("Can't start server : Bind on unix socket"); /* purecov: tested */
2062       sql_print_error("Do you already have another mysqld server running on socket: %s ?",mysqld_unix_port);
2063       unireg_abort(1);					/* purecov: tested */
2064     }
2065     umask(((~my_umask) & 0666));
2066 #if defined(S_IFSOCK) && defined(SECURE_SOCKETS)
2067     (void) chmod(mysqld_unix_port,S_IFSOCK);	/* Fix solaris 2.6 bug */
2068 #endif
2069     if (listen(unix_sock,(int) back_log) < 0)
2070       sql_print_warning("listen() on Unix socket failed with error %d",
2071 		      socket_errno);
2072   }
2073 #endif
2074   DBUG_PRINT("info",("server started"));
2075   DBUG_VOID_RETURN;
2076 }
2077 
2078 #endif /*!EMBEDDED_LIBRARY*/
2079 
2080 
2081 #ifndef EMBEDDED_LIBRARY
2082 /**
2083   Close a connection.
2084 
2085   @param thd        Thread handle.
2086   @param sql_errno  The error code to send before disconnect.
2087 
2088   @note
2089     For the connection that is doing shutdown, this is called twice
2090 */
close_connection(THD * thd,uint sql_errno)2091 void close_connection(THD *thd, uint sql_errno)
2092 {
2093   DBUG_ENTER("close_connection");
2094 
2095   if (sql_errno)
2096     net_send_error(thd, sql_errno, ER_DEFAULT(sql_errno), NULL);
2097 
2098   thd->disconnect();
2099 
2100   MYSQL_CONNECTION_DONE((int) sql_errno, thd->thread_id);
2101 
2102   if (MYSQL_CONNECTION_DONE_ENABLED())
2103   {
2104     sleep(0); /* Workaround to avoid tailcall optimisation */
2105   }
2106   MYSQL_AUDIT_NOTIFY_CONNECTION_DISCONNECT(thd, sql_errno);
2107   DBUG_VOID_RETURN;
2108 }
2109 #endif /* EMBEDDED_LIBRARY */
2110 
2111 
2112 /** Called when a thread is aborted. */
2113 /* ARGSUSED */
end_thread_signal(int sig)2114 extern "C" sig_handler end_thread_signal(int sig __attribute__((unused)))
2115 {
2116   THD *thd=current_thd;
2117   DBUG_ENTER("end_thread_signal");
2118   if (thd && ! thd->bootstrap)
2119   {
2120     statistic_increment(killed_threads, &LOCK_status);
2121     MYSQL_CALLBACK(thread_scheduler, end_thread, (thd,0)); /* purecov: inspected */
2122   }
2123   DBUG_VOID_RETURN;				/* purecov: deadcode */
2124 }
2125 
2126 
2127 /*
2128   Cleanup THD object
2129 
2130   SYNOPSIS
2131     thd_cleanup()
2132     thd		 Thread handler
2133 */
2134 
thd_cleanup(THD * thd)2135 void thd_cleanup(THD *thd)
2136 {
2137   thd->cleanup();
2138 }
2139 
2140 /*
2141   Decrease number of connections
2142 
2143   SYNOPSIS
2144     dec_connection_count()
2145 */
2146 
dec_connection_count()2147 void dec_connection_count()
2148 {
2149   mysql_mutex_lock(&LOCK_connection_count);
2150   --connection_count;
2151   mysql_mutex_unlock(&LOCK_connection_count);
2152 }
2153 
2154 
2155 /*
2156   Delete the THD object and decrease number of threads
2157 
2158   SYNOPSIS
2159     delete_thd()
2160     thd		 Thread handler
2161 */
2162 
delete_thd(THD * thd)2163 void delete_thd(THD *thd)
2164 {
2165   mysql_mutex_assert_owner(&LOCK_thread_count);
2166   mysql_mutex_assert_owner(&LOCK_thd_remove);
2167   thread_count--;
2168   delete thd;
2169 }
2170 
2171 
2172 /*
2173   Unlink thd from global list of available connections and free thd
2174 
2175   SYNOPSIS
2176     unlink_thd()
2177     thd		 Thread handler
2178 
2179   NOTES
2180     LOCK_thread_count, LOCK_thd_remove are locked and left locked
2181 */
2182 
unlink_thd(THD * thd)2183 void unlink_thd(THD *thd)
2184 {
2185   DBUG_ENTER("unlink_thd");
2186   DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd));
2187 
2188   thd_cleanup(thd);
2189   dec_connection_count();
2190   mysql_mutex_lock(&LOCK_thd_remove);
2191   mysql_mutex_lock(&LOCK_thread_count);
2192   /*
2193     Used by binlog_reset_master.  It would be cleaner to use
2194     DEBUG_SYNC here, but that's not possible because the THD's debug
2195     sync feature has been shut down at this point.
2196   */
2197   DBUG_EXECUTE_IF("sleep_after_lock_thread_count_before_delete_thd", sleep(5););
2198   delete_thd(thd);
2199   DBUG_VOID_RETURN;
2200 }
2201 
2202 
2203 /*
2204   Store thread in cache for reuse by new connections
2205 
2206   SYNOPSIS
2207     cache_thread()
2208 
2209   NOTES
2210     LOCK_thread_count has to be locked
2211 
2212   RETURN
2213     0  Thread was not put in cache
2214     1  Thread is to be reused by new connection.
2215        (ie, caller should return, not abort with pthread_exit())
2216 */
2217 
2218 
cache_thread()2219 static bool cache_thread()
2220 {
2221   mysql_mutex_assert_owner(&LOCK_thread_count);
2222   if (cached_thread_count < thread_cache_size &&
2223       ! abort_loop && !kill_cached_threads)
2224   {
2225     /* Don't kill the thread, just put it in cache for reuse */
2226     DBUG_PRINT("info", ("Adding thread to cache"));
2227     cached_thread_count++;
2228 
2229 #ifdef HAVE_PSI_INTERFACE
2230     /*
2231       Delete the instrumentation for the job that just completed,
2232       before parking this pthread in the cache (blocked on COND_thread_cache).
2233     */
2234     if (likely(PSI_server != NULL))
2235       PSI_server->delete_current_thread();
2236 #endif
2237 
2238     while (!abort_loop && ! wake_thread && ! kill_cached_threads)
2239       mysql_cond_wait(&COND_thread_cache, &LOCK_thread_count);
2240     cached_thread_count--;
2241     if (kill_cached_threads)
2242       mysql_cond_signal(&COND_flush_thread_cache);
2243     if (wake_thread)
2244     {
2245       THD *thd;
2246       wake_thread--;
2247       thd= thread_cache.get();
2248       thd->thread_stack= (char*) &thd;          // For store_globals
2249       (void) thd->store_globals();
2250 
2251 #ifdef HAVE_PSI_INTERFACE
2252       /*
2253         Create new instrumentation for the new THD job,
2254         and attach it to this running pthread.
2255       */
2256       if (likely(PSI_server != NULL))
2257       {
2258         PSI_thread *psi= PSI_server->new_thread(key_thread_one_connection,
2259                                                 thd, thd->thread_id);
2260         if (likely(psi != NULL))
2261           PSI_server->set_thread(psi);
2262       }
2263 #endif
2264 
2265       /*
2266         THD::mysys_var::abort is associated with physical thread rather
2267         than with THD object. So we need to reset this flag before using
2268         this thread for handling of new THD object/connection.
2269       */
2270       thd->mysys_var->abort= 0;
2271       thd->thr_create_utime= thd->start_utime= my_micro_time();
2272       threads.append(thd);
2273       return(1);
2274     }
2275   }
2276   return(0);
2277 }
2278 
2279 
2280 /*
2281   End thread for the current connection
2282 
2283   SYNOPSIS
2284     one_thread_per_connection_end()
2285     thd		  Thread handler
2286     put_in_cache  Store thread in cache, if there is room in it
2287                   Normally this is true in all cases except when we got
2288                   out of resources initializing the current thread
2289 
2290   NOTES
2291     If thread is cached, we will wait until thread is scheduled to be
2292     reused and then we will return.
2293     If thread is not cached, we end the thread.
2294 
2295   RETURN
2296     0    Signal to handle_one_connection to reuse connection
2297 */
2298 
one_thread_per_connection_end(THD * thd,bool put_in_cache)2299 bool one_thread_per_connection_end(THD *thd, bool put_in_cache)
2300 {
2301   DBUG_ENTER("one_thread_per_connection_end");
2302   unlink_thd(thd);
2303   mysql_mutex_unlock(&LOCK_thd_remove);
2304   if (put_in_cache)
2305     put_in_cache= cache_thread();
2306   mysql_mutex_unlock(&LOCK_thread_count);
2307   if (put_in_cache)
2308     DBUG_RETURN(0);                             // Thread is reused
2309 
2310   /* It's safe to broadcast outside a lock (COND... is not deleted here) */
2311   DBUG_PRINT("signal", ("Broadcasting COND_thread_count"));
2312   DBUG_LEAVE;                                   // Must match DBUG_ENTER()
2313   my_thread_end();
2314   mysql_cond_broadcast(&COND_thread_count);
2315 
2316   pthread_exit(0);
2317   return 0;                                     // Avoid compiler warnings
2318 }
2319 
2320 
flush_thread_cache()2321 void flush_thread_cache()
2322 {
2323   mysql_mutex_lock(&LOCK_thread_count);
2324   kill_cached_threads++;
2325   while (cached_thread_count)
2326   {
2327     mysql_cond_broadcast(&COND_thread_cache);
2328     mysql_cond_wait(&COND_flush_thread_cache, &LOCK_thread_count);
2329   }
2330   kill_cached_threads--;
2331   mysql_mutex_unlock(&LOCK_thread_count);
2332 }
2333 
2334 
2335 #ifdef THREAD_SPECIFIC_SIGPIPE
2336 /**
2337   Aborts a thread nicely. Comes here on SIGPIPE.
2338 
2339   @todo
2340     One should have to fix that thr_alarm know about this thread too.
2341 */
abort_thread(int sig)2342 extern "C" sig_handler abort_thread(int sig __attribute__((unused)))
2343 {
2344   THD *thd=current_thd;
2345   DBUG_ENTER("abort_thread");
2346   if (thd)
2347     thd->killed= THD::KILL_CONNECTION;
2348   DBUG_VOID_RETURN;
2349 }
2350 #endif
2351 
2352 
2353 /******************************************************************************
2354   Setup a signal thread with handles all signals.
2355   Because Linux doesn't support schemas use a mutex to check that
2356   the signal thread is ready before continuing
2357 ******************************************************************************/
2358 
2359 #if defined(__WIN__)
2360 
2361 
2362 /*
2363   On Windows, we use native SetConsoleCtrlHandler for handle events like Ctrl-C
2364   with graceful shutdown.
2365   Also, we do not use signal(), but SetUnhandledExceptionFilter instead - as it
2366   provides possibility to pass the exception to just-in-time debugger, collect
2367   dumps and potentially also the exception and thread context used to output
2368   callstack.
2369 */
2370 
console_event_handler(DWORD type)2371 static BOOL WINAPI console_event_handler( DWORD type )
2372 {
2373   DBUG_ENTER("console_event_handler");
2374 #ifndef EMBEDDED_LIBRARY
2375   if(type == CTRL_C_EVENT)
2376   {
2377      /*
2378        Do not shutdown before startup is finished and shutdown
2379        thread is initialized. Otherwise there is a race condition
2380        between main thread doing initialization and CTRL-C thread doing
2381        cleanup, which can result into crash.
2382      */
2383 #ifndef EMBEDDED_LIBRARY
2384      if(hEventShutdown)
2385        kill_mysql();
2386      else
2387 #endif
2388        sql_print_warning("CTRL-C ignored during startup");
2389      DBUG_RETURN(TRUE);
2390   }
2391 #endif
2392   DBUG_RETURN(FALSE);
2393 }
2394 
2395 
2396 
2397 
2398 #ifdef DEBUG_UNHANDLED_EXCEPTION_FILTER
2399 #define DEBUGGER_ATTACH_TIMEOUT 120
2400 /*
2401   Wait for debugger to attach and break into debugger. If debugger is not attached,
2402   resume after timeout.
2403 */
wait_for_debugger(int timeout_sec)2404 static void wait_for_debugger(int timeout_sec)
2405 {
2406    if(!IsDebuggerPresent())
2407    {
2408      int i;
2409      printf("Waiting for debugger to attach, pid=%u\n",GetCurrentProcessId());
2410      fflush(stdout);
2411      for(i= 0; i < timeout_sec; i++)
2412      {
2413        Sleep(1000);
2414        if(IsDebuggerPresent())
2415        {
2416          /* Break into debugger */
2417          __debugbreak();
2418          return;
2419        }
2420      }
2421      printf("pid=%u, debugger not attached after %d seconds, resuming\n",GetCurrentProcessId(),
2422        timeout_sec);
2423      fflush(stdout);
2424    }
2425 }
2426 #endif /* DEBUG_UNHANDLED_EXCEPTION_FILTER */
2427 
my_unhandler_exception_filter(EXCEPTION_POINTERS * ex_pointers)2428 LONG WINAPI my_unhandler_exception_filter(EXCEPTION_POINTERS *ex_pointers)
2429 {
2430    static BOOL first_time= TRUE;
2431    if(!first_time)
2432    {
2433      /*
2434        This routine can be called twice, typically
2435        when detaching in JIT debugger.
2436        Return EXCEPTION_EXECUTE_HANDLER to terminate process.
2437      */
2438      return EXCEPTION_EXECUTE_HANDLER;
2439    }
2440    first_time= FALSE;
2441 #ifdef DEBUG_UNHANDLED_EXCEPTION_FILTER
2442    /*
2443     Unfortunately there is no clean way to debug unhandled exception filters,
2444     as debugger does not stop there(also documented in MSDN)
2445     To overcome, one could put a MessageBox, but this will not work in service.
2446     Better solution is to print error message and sleep some minutes
2447     until debugger is attached
2448   */
2449   wait_for_debugger(DEBUGGER_ATTACH_TIMEOUT);
2450 #endif /* DEBUG_UNHANDLED_EXCEPTION_FILTER */
2451   __try
2452   {
2453     my_set_exception_pointers(ex_pointers);
2454     handle_fatal_signal(ex_pointers->ExceptionRecord->ExceptionCode);
2455   }
2456   __except(EXCEPTION_EXECUTE_HANDLER)
2457   {
2458     DWORD written;
2459     const char msg[] = "Got exception in exception handler!\n";
2460     WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),msg, sizeof(msg)-1,
2461       &written,NULL);
2462   }
2463   /*
2464     Return EXCEPTION_CONTINUE_SEARCH to give JIT debugger
2465     (drwtsn32 or vsjitdebugger) possibility to attach,
2466     if JIT debugger is configured.
2467     Windows Error reporting might generate a dump here.
2468   */
2469   return EXCEPTION_CONTINUE_SEARCH;
2470 }
2471 
2472 
init_signals(void)2473 static void init_signals(void)
2474 {
2475   if(opt_console)
2476     SetConsoleCtrlHandler(console_event_handler,TRUE);
2477 
2478     /* Avoid MessageBox()es*/
2479   _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
2480   _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
2481   _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
2482   _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
2483   _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
2484   _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
2485 
2486    /*
2487      Do not use SEM_NOGPFAULTERRORBOX in the following SetErrorMode (),
2488      because it would prevent JIT debugger and Windows error reporting
2489      from working. We need WER or JIT-debugging, since our own unhandled
2490      exception filter is not guaranteed to work in all situation
2491      (like heap corruption or stack overflow)
2492    */
2493   SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS
2494                                | SEM_NOOPENFILEERRORBOX);
2495   SetUnhandledExceptionFilter(my_unhandler_exception_filter);
2496 }
2497 
2498 
start_signal_handler(void)2499 static void start_signal_handler(void)
2500 {
2501 #ifndef EMBEDDED_LIBRARY
2502   // Save vm id of this process
2503   if (!opt_bootstrap)
2504     create_pid_file();
2505 #endif /* EMBEDDED_LIBRARY */
2506 }
2507 
2508 
check_data_home(const char * path)2509 static void check_data_home(const char *path)
2510 {}
2511 
2512 #endif /* __WIN__ */
2513 
2514 
2515 #if BACKTRACE_DEMANGLE
2516 #include <cxxabi.h>
my_demangle(const char * mangled_name,int * status)2517 extern "C" char *my_demangle(const char *mangled_name, int *status)
2518 {
2519   return abi::__cxa_demangle(mangled_name, NULL, NULL, status);
2520 }
2521 #endif
2522 
2523 
2524 
2525 #if !defined(__WIN__)
2526 #ifndef SA_RESETHAND
2527 #define SA_RESETHAND 0
2528 #endif
2529 #ifndef SA_NODEFER
2530 #define SA_NODEFER 0
2531 #endif
2532 
2533 #ifndef EMBEDDED_LIBRARY
2534 
init_signals(void)2535 static void init_signals(void)
2536 {
2537   sigset_t set;
2538   struct sigaction sa;
2539   DBUG_ENTER("init_signals");
2540 
2541   my_sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called!
2542 
2543   if (!(test_flags & TEST_NO_STACKTRACE) || (test_flags & TEST_CORE_ON_SIGNAL))
2544   {
2545     sa.sa_flags = SA_RESETHAND | SA_NODEFER;
2546     sigemptyset(&sa.sa_mask);
2547     sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
2548 
2549 #ifdef HAVE_STACKTRACE
2550     my_init_stacktrace();
2551 #endif
2552 #if defined(__amiga__)
2553     sa.sa_handler=(void(*)())handle_fatal_signal;
2554 #else
2555     sa.sa_handler=handle_fatal_signal;
2556 #endif
2557     sigaction(SIGSEGV, &sa, NULL);
2558     sigaction(SIGABRT, &sa, NULL);
2559 #ifdef SIGBUS
2560     sigaction(SIGBUS, &sa, NULL);
2561 #endif
2562     sigaction(SIGILL, &sa, NULL);
2563     sigaction(SIGFPE, &sa, NULL);
2564   }
2565 
2566 #ifdef HAVE_GETRLIMIT
2567   if (test_flags & TEST_CORE_ON_SIGNAL)
2568   {
2569     /* Change limits so that we will get a core file */
2570     STRUCT_RLIMIT rl;
2571     rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
2572     if (setrlimit(RLIMIT_CORE, &rl) && global_system_variables.log_warnings)
2573       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");
2574   }
2575 #endif
2576   (void) sigemptyset(&set);
2577   my_sigset(SIGPIPE,SIG_IGN);
2578   sigaddset(&set,SIGPIPE);
2579 #ifndef IGNORE_SIGHUP_SIGQUIT
2580   sigaddset(&set,SIGQUIT);
2581   sigaddset(&set,SIGHUP);
2582 #endif
2583   sigaddset(&set,SIGTERM);
2584 
2585   /* Fix signals if blocked by parents (can happen on Mac OS X) */
2586   sigemptyset(&sa.sa_mask);
2587   sa.sa_flags = 0;
2588   sa.sa_handler = print_signal_warning;
2589   sigaction(SIGTERM, &sa, (struct sigaction*) 0);
2590   sa.sa_flags = 0;
2591   sa.sa_handler = print_signal_warning;
2592   sigaction(SIGHUP, &sa, (struct sigaction*) 0);
2593 #ifdef SIGTSTP
2594   sigaddset(&set,SIGTSTP);
2595 #endif
2596   if (thd_lib_detected != THD_LIB_LT)
2597     sigaddset(&set,THR_SERVER_ALARM);
2598   if (test_flags & TEST_SIGINT)
2599   {
2600     my_sigset(thr_kill_signal, end_thread_signal);
2601     // May be SIGINT
2602     sigdelset(&set, thr_kill_signal);
2603   }
2604   else
2605     sigaddset(&set,SIGINT);
2606   sigprocmask(SIG_SETMASK,&set,NULL);
2607   pthread_sigmask(SIG_SETMASK,&set,NULL);
2608   DBUG_VOID_RETURN;
2609 }
2610 
2611 
start_signal_handler(void)2612 static void start_signal_handler(void)
2613 {
2614   int error;
2615   pthread_attr_t thr_attr;
2616   DBUG_ENTER("start_signal_handler");
2617 
2618   (void) pthread_attr_init(&thr_attr);
2619 #if !defined(HAVE_DEC_3_2_THREADS)
2620   pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_SYSTEM);
2621   (void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
2622 #if defined(__ia64__) || defined(__ia64)
2623   /*
2624     Peculiar things with ia64 platforms - it seems we only have half the
2625     stack size in reality, so we have to double it here
2626   */
2627   pthread_attr_setstacksize(&thr_attr,my_thread_stack_size*2);
2628 #else
2629   pthread_attr_setstacksize(&thr_attr,my_thread_stack_size);
2630 #endif
2631 #endif
2632 
2633   mysql_mutex_lock(&LOCK_thread_count);
2634   if ((error= mysql_thread_create(key_thread_signal_hand,
2635                                   &signal_thread, &thr_attr, signal_hand, 0)))
2636   {
2637     sql_print_error("Can't create interrupt-thread (error %d, errno: %d)",
2638 		    error,errno);
2639     exit(1);
2640   }
2641   mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
2642   mysql_mutex_unlock(&LOCK_thread_count);
2643 
2644   (void) pthread_attr_destroy(&thr_attr);
2645   DBUG_VOID_RETURN;
2646 }
2647 
2648 
2649 /** This threads handles all signals and alarms. */
2650 /* ARGSUSED */
signal_hand(void * arg)2651 pthread_handler_t signal_hand(void *arg __attribute__((unused)))
2652 {
2653   sigset_t set;
2654   int sig;
2655   my_thread_init();				// Init new thread
2656   DBUG_ENTER("signal_hand");
2657   signal_thread_in_use= 1;
2658 
2659   /*
2660     Setup alarm handler
2661     This should actually be '+ max_number_of_slaves' instead of +10,
2662     but the +10 should be quite safe.
2663   */
2664   init_thr_alarm(thread_scheduler->max_threads +
2665 		 global_system_variables.max_insert_delayed_threads + 10);
2666   if (thd_lib_detected != THD_LIB_LT && (test_flags & TEST_SIGINT))
2667   {
2668     (void) sigemptyset(&set);			// Setup up SIGINT for debug
2669     (void) sigaddset(&set,SIGINT);		// For debugging
2670     (void) pthread_sigmask(SIG_UNBLOCK,&set,NULL);
2671   }
2672   (void) sigemptyset(&set);			// Setup up SIGINT for debug
2673 #ifdef USE_ONE_SIGNAL_HAND
2674   (void) sigaddset(&set,THR_SERVER_ALARM);	// For alarms
2675 #endif
2676 #ifndef IGNORE_SIGHUP_SIGQUIT
2677   (void) sigaddset(&set,SIGQUIT);
2678   (void) sigaddset(&set,SIGHUP);
2679 #endif
2680   (void) sigaddset(&set,SIGTERM);
2681   (void) sigaddset(&set,SIGTSTP);
2682 
2683   /* Save pid to this process (or thread on Linux) */
2684   if (!opt_bootstrap)
2685     create_pid_file();
2686 
2687   /*
2688     signal to start_signal_handler that we are ready
2689     This works by waiting for start_signal_handler to free mutex,
2690     after which we signal it that we are ready.
2691     At this pointer there is no other threads running, so there
2692     should not be any other mysql_cond_signal() calls.
2693   */
2694   mysql_mutex_lock(&LOCK_thread_count);
2695   mysql_mutex_unlock(&LOCK_thread_count);
2696   mysql_cond_broadcast(&COND_thread_count);
2697 
2698   (void) pthread_sigmask(SIG_BLOCK,&set,NULL);
2699   for (;;)
2700   {
2701     int error;					// Used when debugging
2702     if (shutdown_in_progress && !abort_loop)
2703     {
2704       sig= SIGTERM;
2705       error=0;
2706     }
2707     else
2708       while ((error=my_sigwait(&set,&sig)) == EINTR) ;
2709     if (cleanup_done)
2710     {
2711       DBUG_PRINT("quit",("signal_handler: calling my_thread_end()"));
2712       my_thread_end();
2713       signal_thread_in_use= 0;
2714       DBUG_LEAVE;                               // Must match DBUG_ENTER()
2715       pthread_exit(0);				// Safety
2716       return 0;                                 // Avoid compiler warnings
2717     }
2718     switch (sig) {
2719     case SIGTERM:
2720     case SIGQUIT:
2721     case SIGKILL:
2722 #ifdef EXTRA_DEBUG
2723       sql_print_information("Got signal %d to shutdown mysqld",sig);
2724 #endif
2725       /* switch to the old log message processing */
2726       logger.set_handlers(LOG_FILE, opt_slow_log ? LOG_FILE:LOG_NONE,
2727                           opt_log ? LOG_FILE:LOG_NONE);
2728       DBUG_PRINT("info",("Got signal: %d  abort_loop: %d",sig,abort_loop));
2729       if (!abort_loop)
2730       {
2731 	abort_loop=1;				// mark abort for threads
2732 #ifdef HAVE_PSI_INTERFACE
2733         /* Delete the instrumentation for the signal thread */
2734         if (likely(PSI_server != NULL))
2735           PSI_server->delete_current_thread();
2736 #endif
2737 #ifdef USE_ONE_SIGNAL_HAND
2738 	pthread_t tmp;
2739         if ((error= mysql_thread_create(0, /* Not instrumented */
2740                                         &tmp, &connection_attrib,
2741                                         kill_server_thread,
2742                                         (void*) &sig)))
2743           sql_print_error("Can't create thread to kill server (errno= %d)",
2744                           error);
2745 #else
2746 	kill_server((void*) sig);	// MIT THREAD has a alarm thread
2747 #endif
2748       }
2749       break;
2750     case SIGHUP:
2751       if (!abort_loop)
2752       {
2753         int not_used;
2754 	mysql_print_status();		// Print some debug info
2755 	reload_acl_and_cache((THD*) 0,
2756 			     (REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST |
2757 			      REFRESH_GRANT |
2758 			      REFRESH_THREADS | REFRESH_HOSTS),
2759 			     (TABLE_LIST*) 0, &not_used); // Flush logs
2760       }
2761       /* reenable logs after the options were reloaded */
2762       if (log_output_options & LOG_NONE)
2763       {
2764         logger.set_handlers(LOG_FILE,
2765                             opt_slow_log ? LOG_TABLE : LOG_NONE,
2766                             opt_log ? LOG_TABLE : LOG_NONE);
2767       }
2768       else
2769       {
2770         logger.set_handlers(LOG_FILE,
2771                             opt_slow_log ? log_output_options : LOG_NONE,
2772                             opt_log ? log_output_options : LOG_NONE);
2773       }
2774       break;
2775 #ifdef USE_ONE_SIGNAL_HAND
2776     case THR_SERVER_ALARM:
2777       process_alarm(sig);			// Trigger alarms.
2778       break;
2779 #endif
2780     default:
2781 #ifdef EXTRA_DEBUG
2782       sql_print_warning("Got signal: %d  error: %d",sig,error); /* purecov: tested */
2783 #endif
2784       break;					/* purecov: tested */
2785     }
2786   }
2787   return(0);					/* purecov: deadcode */
2788 }
2789 
check_data_home(const char * path)2790 static void check_data_home(const char *path)
2791 {}
2792 
2793 #endif /*!EMBEDDED_LIBRARY*/
2794 #endif	/* __WIN__*/
2795 
2796 
2797 /**
2798   All global error messages are sent here where the first one is stored
2799   for the client.
2800 */
2801 /* ARGSUSED */
2802 extern "C" void my_message_sql(uint error, const char *str, myf MyFlags);
2803 
my_message_sql(uint error,const char * str,myf MyFlags)2804 void my_message_sql(uint error, const char *str, myf MyFlags)
2805 {
2806   THD *thd= current_thd;
2807   DBUG_ENTER("my_message_sql");
2808   DBUG_PRINT("error", ("error: %u  message: '%s'", error, str));
2809 
2810   DBUG_ASSERT(str != NULL);
2811   /*
2812     An error should have a valid error number (!= 0), so it can be caught
2813     in stored procedures by SQL exception handlers.
2814     Calling my_error() with error == 0 is a bug.
2815     Remaining known places to fix:
2816     - storage/myisam/mi_create.c, my_printf_error()
2817     TODO:
2818     DBUG_ASSERT(error != 0);
2819   */
2820 
2821   if (error == 0)
2822   {
2823     /* At least, prevent new abuse ... */
2824     DBUG_ASSERT(strncmp(str, "MyISAM table", 12) == 0);
2825     error= ER_UNKNOWN_ERROR;
2826   }
2827 
2828   mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_ERROR, error, str);
2829 
2830   if (thd)
2831   {
2832     if (MyFlags & ME_FATALERROR)
2833       thd->is_fatal_error= 1;
2834     (void) thd->raise_condition(error,
2835                                 NULL,
2836                                 MYSQL_ERROR::WARN_LEVEL_ERROR,
2837                                 str);
2838   }
2839 
2840   /* When simulating OOM, skip writing to error log to avoid mtr errors */
2841   DBUG_EXECUTE_IF("simulate_out_of_memory", DBUG_VOID_RETURN;);
2842 
2843   if (!thd || MyFlags & ME_NOREFRESH)
2844     sql_print_error("%s: %s",my_progname,str); /* purecov: inspected */
2845   DBUG_VOID_RETURN;
2846 }
2847 
2848 
2849 #ifndef EMBEDDED_LIBRARY
2850 extern "C" void *my_str_malloc_mysqld(size_t size);
2851 extern "C" void my_str_free_mysqld(void *ptr);
2852 
my_str_malloc_mysqld(size_t size)2853 void *my_str_malloc_mysqld(size_t size)
2854 {
2855   return my_malloc(size, MYF(MY_FAE));
2856 }
2857 
2858 
my_str_free_mysqld(void * ptr)2859 void my_str_free_mysqld(void *ptr)
2860 {
2861   my_free(ptr);
2862 }
2863 #endif /* EMBEDDED_LIBRARY */
2864 
2865 
2866 #ifdef __WIN__
2867 
handle_shutdown(void * arg)2868 pthread_handler_t handle_shutdown(void *arg)
2869 {
2870   MSG msg;
2871   my_thread_init();
2872 
2873   /* this call should create the message queue for this thread */
2874   PeekMessage(&msg, NULL, 1, 65534,PM_NOREMOVE);
2875 #if !defined(EMBEDDED_LIBRARY)
2876   if (WaitForSingleObject(hEventShutdown,INFINITE)==WAIT_OBJECT_0)
2877 #endif /* EMBEDDED_LIBRARY */
2878      kill_server(MYSQL_KILL_SIGNAL);
2879   return 0;
2880 }
2881 #endif
2882 
2883 const char *load_default_groups[]= {
2884 #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
2885 "mysql_cluster",
2886 #endif
2887 "mysqld","server", MYSQL_BASE_VERSION, 0, 0};
2888 
2889 #if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
2890 static const int load_default_groups_sz=
2891 sizeof(load_default_groups)/sizeof(load_default_groups[0]);
2892 #endif
2893 
2894 
2895 #ifndef EMBEDDED_LIBRARY
2896 /**
2897   This function is used to check for stack overrun for pathological
2898   cases of  regular expressions and 'like' expressions.
2899   The call to current_thd is  quite expensive, so we try to avoid it
2900   for the normal cases.
2901   The size of  each stack frame for the wildcmp() routines is ~128 bytes,
2902   so checking  *every* recursive call is not necessary.
2903  */
2904 extern "C" int
check_enough_stack_size(int recurse_level)2905 check_enough_stack_size(int recurse_level)
2906 {
2907   uchar stack_top;
2908   if (recurse_level % 16 != 0)
2909     return 0;
2910 
2911   THD *my_thd= current_thd;
2912   if (my_thd != NULL)
2913     return check_stack_overrun(my_thd, STACK_MIN_SIZE * 2, &stack_top);
2914   return 0;
2915 }
2916 #endif
2917 
2918 
2919 /**
2920   Initialize one of the global date/time format variables.
2921 
2922   @param format_type		What kind of format should be supported
2923   @param var_ptr		Pointer to variable that should be updated
2924 
2925   @retval
2926     0 ok
2927   @retval
2928     1 error
2929 */
2930 
init_global_datetime_format(timestamp_type format_type,DATE_TIME_FORMAT * format)2931 static bool init_global_datetime_format(timestamp_type format_type,
2932                                         DATE_TIME_FORMAT *format)
2933 {
2934   /*
2935     Get command line option
2936     format->format.str is already set by my_getopt
2937   */
2938   format->format.length= strlen(format->format.str);
2939 
2940   if (parse_date_time_format(format_type, format))
2941   {
2942     fprintf(stderr, "Wrong date/time format specifier: %s\n",
2943             format->format.str);
2944     return true;
2945   }
2946   return false;
2947 }
2948 
2949 SHOW_VAR com_status_vars[]= {
2950   {"admin_commands",       (char*) offsetof(STATUS_VAR, com_other), SHOW_LONG_STATUS},
2951   {"assign_to_keycache",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ASSIGN_TO_KEYCACHE]), SHOW_LONG_STATUS},
2952   {"alter_db",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_DB]), SHOW_LONG_STATUS},
2953   {"alter_db_upgrade",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_DB_UPGRADE]), SHOW_LONG_STATUS},
2954   {"alter_event",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_EVENT]), SHOW_LONG_STATUS},
2955   {"alter_function",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_FUNCTION]), SHOW_LONG_STATUS},
2956   {"alter_procedure",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_PROCEDURE]), SHOW_LONG_STATUS},
2957   {"alter_server",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_SERVER]), SHOW_LONG_STATUS},
2958   {"alter_table",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_TABLE]), SHOW_LONG_STATUS},
2959   {"alter_tablespace",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ALTER_TABLESPACE]), SHOW_LONG_STATUS},
2960   {"analyze",              (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ANALYZE]), SHOW_LONG_STATUS},
2961   {"begin",                (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_BEGIN]), SHOW_LONG_STATUS},
2962   {"binlog",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_BINLOG_BASE64_EVENT]), SHOW_LONG_STATUS},
2963   {"call_procedure",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CALL]), SHOW_LONG_STATUS},
2964   {"change_db",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHANGE_DB]), SHOW_LONG_STATUS},
2965   {"change_master",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHANGE_MASTER]), SHOW_LONG_STATUS},
2966   {"check",                (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHECK]), SHOW_LONG_STATUS},
2967   {"checksum",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CHECKSUM]), SHOW_LONG_STATUS},
2968   {"commit",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_COMMIT]), SHOW_LONG_STATUS},
2969   {"create_db",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_DB]), SHOW_LONG_STATUS},
2970   {"create_event",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_EVENT]), SHOW_LONG_STATUS},
2971   {"create_function",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_SPFUNCTION]), SHOW_LONG_STATUS},
2972   {"create_index",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_INDEX]), SHOW_LONG_STATUS},
2973   {"create_procedure",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_PROCEDURE]), SHOW_LONG_STATUS},
2974   {"create_server",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_SERVER]), SHOW_LONG_STATUS},
2975   {"create_table",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_TABLE]), SHOW_LONG_STATUS},
2976   {"create_trigger",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_TRIGGER]), SHOW_LONG_STATUS},
2977   {"create_udf",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_FUNCTION]), SHOW_LONG_STATUS},
2978   {"create_user",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_USER]), SHOW_LONG_STATUS},
2979   {"create_view",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_CREATE_VIEW]), SHOW_LONG_STATUS},
2980   {"dealloc_sql",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DEALLOCATE_PREPARE]), SHOW_LONG_STATUS},
2981   {"delete",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DELETE]), SHOW_LONG_STATUS},
2982   {"delete_multi",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DELETE_MULTI]), SHOW_LONG_STATUS},
2983   {"do",                   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DO]), SHOW_LONG_STATUS},
2984   {"drop_db",              (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_DB]), SHOW_LONG_STATUS},
2985   {"drop_event",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_EVENT]), SHOW_LONG_STATUS},
2986   {"drop_function",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_FUNCTION]), SHOW_LONG_STATUS},
2987   {"drop_index",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_INDEX]), SHOW_LONG_STATUS},
2988   {"drop_procedure",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_PROCEDURE]), SHOW_LONG_STATUS},
2989   {"drop_server",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_SERVER]), SHOW_LONG_STATUS},
2990   {"drop_table",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_TABLE]), SHOW_LONG_STATUS},
2991   {"drop_trigger",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_TRIGGER]), SHOW_LONG_STATUS},
2992   {"drop_user",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_USER]), SHOW_LONG_STATUS},
2993   {"drop_view",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_DROP_VIEW]), SHOW_LONG_STATUS},
2994   {"empty_query",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EMPTY_QUERY]), SHOW_LONG_STATUS},
2995   {"execute_sql",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_EXECUTE]), SHOW_LONG_STATUS},
2996   {"flush",                (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_FLUSH]), SHOW_LONG_STATUS},
2997   {"grant",                (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_GRANT]), SHOW_LONG_STATUS},
2998   {"ha_close",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_CLOSE]), SHOW_LONG_STATUS},
2999   {"ha_open",              (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_OPEN]), SHOW_LONG_STATUS},
3000   {"ha_read",              (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HA_READ]), SHOW_LONG_STATUS},
3001   {"help",                 (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_HELP]), SHOW_LONG_STATUS},
3002   {"insert",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSERT]), SHOW_LONG_STATUS},
3003   {"insert_select",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSERT_SELECT]), SHOW_LONG_STATUS},
3004   {"install_plugin",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_INSTALL_PLUGIN]), SHOW_LONG_STATUS},
3005   {"kill",                 (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_KILL]), SHOW_LONG_STATUS},
3006   {"load",                 (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOAD]), SHOW_LONG_STATUS},
3007   {"lock_tables",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_LOCK_TABLES]), SHOW_LONG_STATUS},
3008   {"optimize",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_OPTIMIZE]), SHOW_LONG_STATUS},
3009   {"preload_keys",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PRELOAD_KEYS]), SHOW_LONG_STATUS},
3010   {"prepare_sql",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PREPARE]), SHOW_LONG_STATUS},
3011   {"purge",                (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PURGE]), SHOW_LONG_STATUS},
3012   {"purge_before_date",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_PURGE_BEFORE]), SHOW_LONG_STATUS},
3013   {"release_savepoint",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RELEASE_SAVEPOINT]), SHOW_LONG_STATUS},
3014   {"rename_table",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RENAME_TABLE]), SHOW_LONG_STATUS},
3015   {"rename_user",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RENAME_USER]), SHOW_LONG_STATUS},
3016   {"repair",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPAIR]), SHOW_LONG_STATUS},
3017   {"replace",              (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPLACE]), SHOW_LONG_STATUS},
3018   {"replace_select",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REPLACE_SELECT]), SHOW_LONG_STATUS},
3019   {"reset",                (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESET]), SHOW_LONG_STATUS},
3020   {"resignal",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_RESIGNAL]), SHOW_LONG_STATUS},
3021   {"revoke",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE]), SHOW_LONG_STATUS},
3022   {"revoke_all",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_REVOKE_ALL]), SHOW_LONG_STATUS},
3023   {"rollback",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ROLLBACK]), SHOW_LONG_STATUS},
3024   {"rollback_to_savepoint",(char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_ROLLBACK_TO_SAVEPOINT]), SHOW_LONG_STATUS},
3025   {"savepoint",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SAVEPOINT]), SHOW_LONG_STATUS},
3026   {"select",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SELECT]), SHOW_LONG_STATUS},
3027   {"set_option",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SET_OPTION]), SHOW_LONG_STATUS},
3028   {"signal",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SIGNAL]), SHOW_LONG_STATUS},
3029   {"show_authors",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_AUTHORS]), SHOW_LONG_STATUS},
3030   {"show_binlog_events",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOG_EVENTS]), SHOW_LONG_STATUS},
3031   {"show_binlogs",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_BINLOGS]), SHOW_LONG_STATUS},
3032   {"show_charsets",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CHARSETS]), SHOW_LONG_STATUS},
3033   {"show_collations",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_COLLATIONS]), SHOW_LONG_STATUS},
3034   {"show_contributors",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CONTRIBUTORS]), SHOW_LONG_STATUS},
3035   {"show_create_db",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_DB]), SHOW_LONG_STATUS},
3036   {"show_create_event",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_EVENT]), SHOW_LONG_STATUS},
3037   {"show_create_func",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_FUNC]), SHOW_LONG_STATUS},
3038   {"show_create_proc",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_PROC]), SHOW_LONG_STATUS},
3039   {"show_create_table",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE]), SHOW_LONG_STATUS},
3040   {"show_create_trigger",  (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_CREATE_TRIGGER]), SHOW_LONG_STATUS},
3041   {"show_databases",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_DATABASES]), SHOW_LONG_STATUS},
3042   {"show_engine_logs",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_LOGS]), SHOW_LONG_STATUS},
3043   {"show_engine_mutex",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_MUTEX]), SHOW_LONG_STATUS},
3044   {"show_engine_status",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ENGINE_STATUS]), SHOW_LONG_STATUS},
3045   {"show_events",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_EVENTS]), SHOW_LONG_STATUS},
3046   {"show_errors",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_ERRORS]), SHOW_LONG_STATUS},
3047   {"show_fields",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_FIELDS]), SHOW_LONG_STATUS},
3048 #ifndef DBUG_OFF
3049   {"show_function_code",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_FUNC_CODE]), SHOW_LONG_STATUS},
3050 #endif
3051   {"show_function_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS_FUNC]), SHOW_LONG_STATUS},
3052   {"show_grants",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_GRANTS]), SHOW_LONG_STATUS},
3053   {"show_keys",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_KEYS]), SHOW_LONG_STATUS},
3054   {"show_master_status",   (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_MASTER_STAT]), SHOW_LONG_STATUS},
3055   {"show_open_tables",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_OPEN_TABLES]), SHOW_LONG_STATUS},
3056   {"show_plugins",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PLUGINS]), SHOW_LONG_STATUS},
3057   {"show_privileges",      (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PRIVILEGES]), SHOW_LONG_STATUS},
3058 #ifndef DBUG_OFF
3059   {"show_procedure_code",  (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROC_CODE]), SHOW_LONG_STATUS},
3060 #endif
3061   {"show_procedure_status",(char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS_PROC]), SHOW_LONG_STATUS},
3062   {"show_processlist",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROCESSLIST]), SHOW_LONG_STATUS},
3063   {"show_profile",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROFILE]), SHOW_LONG_STATUS},
3064   {"show_profiles",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_PROFILES]), SHOW_LONG_STATUS},
3065   {"show_relaylog_events", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_RELAYLOG_EVENTS]), SHOW_LONG_STATUS},
3066   {"show_slave_hosts",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_HOSTS]), SHOW_LONG_STATUS},
3067   {"show_slave_status",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_STAT]), SHOW_LONG_STATUS},
3068   {"show_status",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS]), SHOW_LONG_STATUS},
3069   {"show_storage_engines", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STORAGE_ENGINES]), SHOW_LONG_STATUS},
3070   {"show_table_status",    (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLE_STATUS]), SHOW_LONG_STATUS},
3071   {"show_tables",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TABLES]), SHOW_LONG_STATUS},
3072   {"show_triggers",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_TRIGGERS]), SHOW_LONG_STATUS},
3073   {"show_variables",       (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_VARIABLES]), SHOW_LONG_STATUS},
3074   {"show_warnings",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_WARNS]), SHOW_LONG_STATUS},
3075   {"slave_start",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_START]), SHOW_LONG_STATUS},
3076   {"slave_stop",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_STOP]), SHOW_LONG_STATUS},
3077   {"stmt_close",           (char*) offsetof(STATUS_VAR, com_stmt_close), SHOW_LONG_STATUS},
3078   {"stmt_execute",         (char*) offsetof(STATUS_VAR, com_stmt_execute), SHOW_LONG_STATUS},
3079   {"stmt_fetch",           (char*) offsetof(STATUS_VAR, com_stmt_fetch), SHOW_LONG_STATUS},
3080   {"stmt_prepare",         (char*) offsetof(STATUS_VAR, com_stmt_prepare), SHOW_LONG_STATUS},
3081   {"stmt_reprepare",       (char*) offsetof(STATUS_VAR, com_stmt_reprepare), SHOW_LONG_STATUS},
3082   {"stmt_reset",           (char*) offsetof(STATUS_VAR, com_stmt_reset), SHOW_LONG_STATUS},
3083   {"stmt_send_long_data",  (char*) offsetof(STATUS_VAR, com_stmt_send_long_data), SHOW_LONG_STATUS},
3084   {"truncate",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_TRUNCATE]), SHOW_LONG_STATUS},
3085   {"uninstall_plugin",     (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UNINSTALL_PLUGIN]), SHOW_LONG_STATUS},
3086   {"unlock_tables",        (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UNLOCK_TABLES]), SHOW_LONG_STATUS},
3087   {"update",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UPDATE]), SHOW_LONG_STATUS},
3088   {"update_multi",         (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_UPDATE_MULTI]), SHOW_LONG_STATUS},
3089   {"xa_commit",            (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_COMMIT]),SHOW_LONG_STATUS},
3090   {"xa_end",               (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_END]),SHOW_LONG_STATUS},
3091   {"xa_prepare",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_PREPARE]),SHOW_LONG_STATUS},
3092   {"xa_recover",           (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_RECOVER]),SHOW_LONG_STATUS},
3093   {"xa_rollback",          (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_ROLLBACK]),SHOW_LONG_STATUS},
3094   {"xa_start",             (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_XA_START]),SHOW_LONG_STATUS},
3095   {NullS, NullS, SHOW_LONG}
3096 };
3097 
3098 LEX_CSTRING sql_statement_names[(uint) SQLCOM_END + 1];
3099 
init_sql_statement_names()3100 void init_sql_statement_names()
3101 {
3102   static LEX_CSTRING empty= { C_STRING_WITH_LEN("") };
3103 
3104   char *first_com= (char*) offsetof(STATUS_VAR, com_stat[0]);
3105   char *last_com= (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_END]);
3106   int record_size= (char*) offsetof(STATUS_VAR, com_stat[1])
3107                    - (char*) offsetof(STATUS_VAR, com_stat[0]);
3108   char *ptr;
3109   uint i;
3110   uint com_index;
3111 
3112   for (i= 0; i < ((uint) SQLCOM_END + 1); i++)
3113     sql_statement_names[i]= empty;
3114 
3115   SHOW_VAR *var= &com_status_vars[0];
3116   while (var->name != NULL)
3117   {
3118     ptr= var->value;
3119     if ((first_com <= ptr) && (ptr <= last_com))
3120     {
3121       com_index= ((int)(ptr - first_com))/record_size;
3122       DBUG_ASSERT(com_index < (uint) SQLCOM_END);
3123       sql_statement_names[com_index].str= var->name;
3124       /* TODO: Change SHOW_VAR::name to a LEX_STRING, to avoid strlen() */
3125       sql_statement_names[com_index].length= strlen(var->name);
3126     }
3127     var++;
3128   }
3129 
3130   DBUG_ASSERT(strcmp(sql_statement_names[(uint) SQLCOM_SELECT].str, "select") == 0);
3131   DBUG_ASSERT(strcmp(sql_statement_names[(uint) SQLCOM_SIGNAL].str, "signal") == 0);
3132 
3133   sql_statement_names[(uint) SQLCOM_END].str= "error";
3134 }
3135 
3136 /**
3137   Create the name of the default general log file
3138 
3139   @param[IN] buff    Location for building new string.
3140   @param[IN] log_ext The extension for the file (e.g .log)
3141   @returns Pointer to a new string containing the name
3142 */
make_default_log_name(char * buff,const char * log_ext)3143 static inline char *make_default_log_name(char *buff,const char* log_ext)
3144 {
3145   return make_log_name(buff, default_logfile_name, log_ext);
3146 }
3147 
init_common_variables()3148 static int init_common_variables()
3149 {
3150   char buff[FN_REFLEN];
3151   umask(((~my_umask) & 0666));
3152   my_decimal_set_zero(&decimal_zero); // set decimal_zero constant;
3153   tzset();			// Set tzname
3154 
3155   max_system_variables.pseudo_thread_id= (ulong)~0;
3156   server_start_time= flush_status_time= my_time(0);
3157 
3158   rpl_filter= new Rpl_filter;
3159   binlog_filter= new Rpl_filter;
3160   if (!rpl_filter || !binlog_filter)
3161   {
3162     sql_perror("Could not allocate replication and binlog filters");
3163     return 1;
3164   }
3165 
3166   if (init_thread_environment() ||
3167       mysql_init_variables())
3168     return 1;
3169 
3170 #ifdef HAVE_TZNAME
3171   {
3172     struct tm tm_tmp;
3173     localtime_r(&server_start_time,&tm_tmp);
3174     strmake(system_time_zone, tzname[tm_tmp.tm_isdst != 0 ? 1 : 0],
3175             sizeof(system_time_zone)-1);
3176 
3177  }
3178 #endif
3179   /*
3180     We set SYSTEM time zone as reasonable default and
3181     also for failure of my_tz_init() and bootstrap mode.
3182     If user explicitly set time zone with --default-time-zone
3183     option we will change this value in my_tz_init().
3184   */
3185   global_system_variables.time_zone= my_tz_SYSTEM;
3186 
3187 #ifdef HAVE_PSI_INTERFACE
3188   /*
3189     Complete the mysql_bin_log initialization.
3190     Instrumentation keys are known only after the performance schema initialization,
3191     and can not be set in the MYSQL_BIN_LOG constructor (called before main()).
3192   */
3193   mysql_bin_log.set_psi_keys(key_BINLOG_LOCK_index,
3194                              key_BINLOG_update_cond,
3195                              key_file_binlog,
3196                              key_file_binlog_index);
3197 #endif
3198 
3199   /*
3200     Init mutexes for the global MYSQL_BIN_LOG objects.
3201     As safe_mutex depends on what MY_INIT() does, we can't init the mutexes of
3202     global MYSQL_BIN_LOGs in their constructors, because then they would be
3203     inited before MY_INIT(). So we do it here.
3204   */
3205   mysql_bin_log.init_pthread_objects();
3206 
3207   /* TODO: remove this when my_time_t is 64 bit compatible */
3208   if (!IS_TIME_T_VALID_FOR_TIMESTAMP(server_start_time))
3209   {
3210     sql_print_error("This MySQL server doesn't support dates later then 2038");
3211     return 1;
3212   }
3213 
3214   if (gethostname(glob_hostname,sizeof(glob_hostname)) < 0)
3215   {
3216     strmake(glob_hostname, STRING_WITH_LEN("localhost"));
3217     sql_print_warning("gethostname failed, using '%s' as hostname",
3218                       glob_hostname);
3219     strmake(default_logfile_name, STRING_WITH_LEN("mysql"));
3220   }
3221   else
3222     strmake(default_logfile_name, glob_hostname,
3223 	    sizeof(default_logfile_name)-5);
3224 
3225   strmake(pidfile_name, default_logfile_name, sizeof(pidfile_name)-5);
3226   strmov(fn_ext(pidfile_name),".pid");		// Add proper extension
3227 
3228   /*
3229     The default-storage-engine entry in my_long_options should have a
3230     non-null default value. It was earlier intialized as
3231     (longlong)"MyISAM" in my_long_options but this triggered a
3232     compiler error in the Sun Studio 12 compiler. As a work-around we
3233     set the def_value member to 0 in my_long_options and initialize it
3234     to the correct value here.
3235 
3236     From MySQL 5.5 onwards, the default storage engine is InnoDB
3237     (except in the embedded server, where the default continues to
3238     be MyISAM)
3239   */
3240 #ifdef EMBEDDED_LIBRARY
3241   default_storage_engine= const_cast<char *>("MyISAM");
3242 #else
3243   default_storage_engine= const_cast<char *>("InnoDB");
3244 #endif
3245 
3246   /*
3247     Add server status variables to the dynamic list of
3248     status variables that is shown by SHOW STATUS.
3249     Later, in plugin_init, and mysql_install_plugin
3250     new entries could be added to that list.
3251   */
3252   if (add_status_vars(status_vars))
3253     return 1; // an error was already reported
3254 
3255 #ifndef DBUG_OFF
3256   /*
3257     We have few debug-only commands in com_status_vars, only visible in debug
3258     builds. for simplicity we enable the assert only in debug builds
3259 
3260     There are 8 Com_ variables which don't have corresponding SQLCOM_ values:
3261     (TODO strictly speaking they shouldn't be here, should not have Com_ prefix
3262     that is. Perhaps Stmt_ ? Comstmt_ ? Prepstmt_ ?)
3263 
3264       Com_admin_commands       => com_other
3265       Com_stmt_close           => com_stmt_close
3266       Com_stmt_execute         => com_stmt_execute
3267       Com_stmt_fetch           => com_stmt_fetch
3268       Com_stmt_prepare         => com_stmt_prepare
3269       Com_stmt_reprepare       => com_stmt_reprepare
3270       Com_stmt_reset           => com_stmt_reset
3271       Com_stmt_send_long_data  => com_stmt_send_long_data
3272 
3273     With this correction the number of Com_ variables (number of elements in
3274     the array, excluding the last element - terminator) must match the number
3275     of SQLCOM_ constants.
3276   */
3277   compile_time_assert(sizeof(com_status_vars)/sizeof(com_status_vars[0]) - 1 ==
3278                      SQLCOM_END + 8);
3279 #endif
3280 
3281   if (get_options(&remaining_argc, &remaining_argv))
3282     return 1;
3283   set_server_version();
3284 
3285   sql_print_information("%s (mysqld %s) starting as process %lu ...",
3286                         my_progname, server_version, (ulong) getpid());
3287 
3288 #ifndef EMBEDDED_LIBRARY
3289   if (opt_help && !opt_verbose)
3290     unireg_abort(0);
3291 #endif /*!EMBEDDED_LIBRARY*/
3292 
3293   DBUG_PRINT("info",("%s  Ver %s for %s on %s\n",my_progname,
3294 		     server_version, SYSTEM_TYPE,MACHINE_TYPE));
3295 
3296 #ifdef HAVE_LARGE_PAGES
3297   /* Initialize large page size */
3298   if (opt_large_pages && (opt_large_page_size= my_get_large_page_size()))
3299   {
3300       DBUG_PRINT("info", ("Large page set, large_page_size = %d",
3301                  opt_large_page_size));
3302       my_use_large_pages= 1;
3303       my_large_page_size= opt_large_page_size;
3304   }
3305   else
3306   {
3307     opt_large_pages= 0;
3308     /*
3309        Either not configured to use large pages or Linux haven't
3310        been compiled with large page support
3311     */
3312   }
3313 #endif /* HAVE_LARGE_PAGES */
3314 #ifdef HAVE_SOLARIS_LARGE_PAGES
3315 #define LARGE_PAGESIZE (4*1024*1024)  /* 4MB */
3316 #define SUPER_LARGE_PAGESIZE (256*1024*1024)  /* 256MB */
3317   if (opt_large_pages)
3318   {
3319   /*
3320     tell the kernel that we want to use 4/256MB page for heap storage
3321     and also for the stack. We use 4 MByte as default and if the
3322     super-large-page is set we increase it to 256 MByte. 256 MByte
3323     is for server installations with GBytes of RAM memory where
3324     the MySQL Server will have page caches and other memory regions
3325     measured in a number of GBytes.
3326     We use as big pages as possible which isn't bigger than the above
3327     desired page sizes.
3328   */
3329    int nelem;
3330    size_t max_desired_page_size;
3331    if (opt_super_large_pages)
3332      max_desired_page_size= SUPER_LARGE_PAGESIZE;
3333    else
3334      max_desired_page_size= LARGE_PAGESIZE;
3335    nelem = getpagesizes(NULL, 0);
3336    if (nelem > 0)
3337    {
3338      size_t *pagesize = (size_t *) malloc(sizeof(size_t) * nelem);
3339      if (pagesize != NULL && getpagesizes(pagesize, nelem) > 0)
3340      {
3341        size_t max_page_size= 0;
3342        for (int i= 0; i < nelem; i++)
3343        {
3344          if (pagesize[i] > max_page_size &&
3345              pagesize[i] <= max_desired_page_size)
3346             max_page_size= pagesize[i];
3347        }
3348        free(pagesize);
3349        if (max_page_size > 0)
3350        {
3351          struct memcntl_mha mpss;
3352 
3353          mpss.mha_cmd= MHA_MAPSIZE_BSSBRK;
3354          mpss.mha_pagesize= max_page_size;
3355          mpss.mha_flags= 0;
3356          memcntl(NULL, 0, MC_HAT_ADVISE, (caddr_t)&mpss, 0, 0);
3357          mpss.mha_cmd= MHA_MAPSIZE_STACK;
3358          memcntl(NULL, 0, MC_HAT_ADVISE, (caddr_t)&mpss, 0, 0);
3359        }
3360      }
3361    }
3362   }
3363 #endif /* HAVE_SOLARIS_LARGE_PAGES */
3364 
3365   /* connections and databases needs lots of files */
3366   {
3367     uint files, wanted_files, max_open_files;
3368 
3369     /* MyISAM requires two file handles per table. */
3370     wanted_files= 10+max_connections+table_cache_size*2;
3371     /*
3372       We are trying to allocate no less than max_connections*5 file
3373       handles (i.e. we are trying to set the limit so that they will
3374       be available).  In addition, we allocate no less than how much
3375       was already allocated.  However below we report a warning and
3376       recompute values only if we got less file handles than were
3377       explicitly requested.  No warning and re-computation occur if we
3378       can't get max_connections*5 but still got no less than was
3379       requested (value of wanted_files).
3380     */
3381     max_open_files= max(max(wanted_files, max_connections*5),
3382                         open_files_limit);
3383     files= my_set_max_open_files(max_open_files);
3384 
3385     if (files < wanted_files)
3386     {
3387       if (!open_files_limit)
3388       {
3389         /*
3390           If we have requested too much file handles than we bring
3391           max_connections in supported bounds.
3392         */
3393         max_connections= (ulong) min(files-10-TABLE_OPEN_CACHE_MIN*2,
3394                                      max_connections);
3395         /*
3396           Decrease table_cache_size according to max_connections, but
3397           not below TABLE_OPEN_CACHE_MIN.  Outer min() ensures that we
3398           never increase table_cache_size automatically (that could
3399           happen if max_connections is decreased above).
3400         */
3401         table_cache_size= (ulong) min(max((files-10-max_connections)/2,
3402                                           TABLE_OPEN_CACHE_MIN),
3403                                       table_cache_size);
3404 	DBUG_PRINT("warning",
3405 		   ("Changed limits: max_open_files: %u  max_connections: %ld  table_cache: %ld",
3406 		    files, max_connections, table_cache_size));
3407 	if (global_system_variables.log_warnings)
3408 	  sql_print_warning("Changed limits: max_open_files: %u  max_connections: %ld  table_cache: %ld",
3409 			files, max_connections, table_cache_size);
3410       }
3411       else if (global_system_variables.log_warnings)
3412 	sql_print_warning("Could not increase number of max_open_files to more than %u (request: %u)", files, wanted_files);
3413     }
3414     open_files_limit= files;
3415   }
3416   unireg_init(opt_specialflag); /* Set up extern variabels */
3417   if (!(my_default_lc_messages=
3418         my_locale_by_name(lc_messages)))
3419   {
3420     sql_print_error("Unknown locale: '%s'", lc_messages);
3421     return 1;
3422   }
3423   global_system_variables.lc_messages= my_default_lc_messages;
3424   if (init_errmessage())	/* Read error messages from file */
3425     return 1;
3426   init_client_errs();
3427   mysql_client_plugin_init();
3428   lex_init();
3429   if (item_create_init())
3430     return 1;
3431   item_init();
3432 #ifndef EMBEDDED_LIBRARY
3433   my_regex_init(&my_charset_latin1, check_enough_stack_size);
3434   my_string_stack_guard= check_enough_stack_size;
3435 #else
3436   my_regex_init(&my_charset_latin1, NULL);
3437 #endif
3438   /*
3439     Process a comma-separated character set list and choose
3440     the first available character set. This is mostly for
3441     test purposes, to be able to start "mysqld" even if
3442     the requested character set is not available (see bug#18743).
3443   */
3444   for (;;)
3445   {
3446     char *next_character_set_name= strchr(default_character_set_name, ',');
3447     if (next_character_set_name)
3448       *next_character_set_name++= '\0';
3449     if (!(default_charset_info=
3450           get_charset_by_csname(default_character_set_name,
3451                                 MY_CS_PRIMARY, MYF(MY_WME))))
3452     {
3453       if (next_character_set_name)
3454       {
3455         default_character_set_name= next_character_set_name;
3456         default_collation_name= 0;          // Ignore collation
3457       }
3458       else
3459         return 1;                           // Eof of the list
3460     }
3461     else
3462       break;
3463   }
3464 
3465   if (default_collation_name)
3466   {
3467     CHARSET_INFO *default_collation;
3468     default_collation= get_charset_by_name(default_collation_name, MYF(0));
3469     if (!default_collation)
3470     {
3471       sql_print_error(ER_DEFAULT(ER_UNKNOWN_COLLATION), default_collation_name);
3472       return 1;
3473     }
3474     if (!my_charset_same(default_charset_info, default_collation))
3475     {
3476       sql_print_error(ER_DEFAULT(ER_COLLATION_CHARSET_MISMATCH),
3477 		      default_collation_name,
3478 		      default_charset_info->csname);
3479       return 1;
3480     }
3481     default_charset_info= default_collation;
3482   }
3483   /* Set collactions that depends on the default collation */
3484   global_system_variables.collation_server=	 default_charset_info;
3485   global_system_variables.collation_database=	 default_charset_info;
3486 
3487   if (is_supported_parser_charset(default_charset_info))
3488   {
3489     global_system_variables.collation_connection= default_charset_info;
3490     global_system_variables.character_set_results= default_charset_info;
3491     global_system_variables.character_set_client= default_charset_info;
3492   }
3493   else
3494   {
3495     sql_print_information("'%s' can not be used as client character set. "
3496                           "'%s' will be used as default client character set.",
3497                           default_charset_info->csname,
3498                           my_charset_latin1.csname);
3499     global_system_variables.collation_connection= &my_charset_latin1;
3500     global_system_variables.character_set_results= &my_charset_latin1;
3501     global_system_variables.character_set_client= &my_charset_latin1;
3502   }
3503 
3504   if (!(character_set_filesystem=
3505         get_charset_by_csname(character_set_filesystem_name,
3506                               MY_CS_PRIMARY, MYF(MY_WME))))
3507     return 1;
3508   global_system_variables.character_set_filesystem= character_set_filesystem;
3509 
3510   if (!(my_default_lc_time_names=
3511         my_locale_by_name(lc_time_names_name)))
3512   {
3513     sql_print_error("Unknown locale: '%s'", lc_time_names_name);
3514     return 1;
3515   }
3516   global_system_variables.lc_time_names= my_default_lc_time_names;
3517 
3518   /* check log options and issue warnings if needed */
3519   if (opt_log && opt_logname && !(log_output_options & LOG_FILE) &&
3520       !(log_output_options & LOG_NONE))
3521     sql_print_warning("Although a path was specified for the "
3522                       "--log option, log tables are used. "
3523                       "To enable logging to files use the --log-output option.");
3524 
3525   if (opt_slow_log && opt_slow_logname && !(log_output_options & LOG_FILE)
3526       && !(log_output_options & LOG_NONE))
3527     sql_print_warning("Although a path was specified for the "
3528                       "--log-slow-queries option, log tables are used. "
3529                       "To enable logging to files use the --log-output=file option.");
3530 
3531   if (opt_logname &&
3532       !is_valid_log_name(opt_logname, strlen(opt_logname)))
3533   {
3534     sql_print_error("Invalid value for --general_log_file: %s",
3535                     opt_logname);
3536     return 1;
3537   }
3538 
3539   if (opt_slow_logname &&
3540       !is_valid_log_name(opt_slow_logname, strlen(opt_slow_logname)))
3541   {
3542     sql_print_error("Invalid value for --slow_query_log_file: %s",
3543                     opt_slow_logname);
3544     return 1;
3545   }
3546 
3547 #define FIX_LOG_VAR(VAR, ALT)                                   \
3548   if (!VAR || !*VAR)                                            \
3549   {                                                             \
3550     my_free(VAR); /* it could be an allocated empty string "" */ \
3551     VAR= my_strdup(ALT, MYF(0));                                \
3552   }
3553 
3554   FIX_LOG_VAR(opt_logname,
3555               make_default_log_name(buff, ".log"));
3556   FIX_LOG_VAR(opt_slow_logname,
3557               make_default_log_name(buff, "-slow.log"));
3558 
3559 #if defined(ENABLED_DEBUG_SYNC)
3560   /* Initialize the debug sync facility. See debug_sync.cc. */
3561   if (debug_sync_init())
3562     return 1; /* purecov: tested */
3563 #endif /* defined(ENABLED_DEBUG_SYNC) */
3564 
3565 #if (ENABLE_TEMP_POOL)
3566   if (use_temp_pool && bitmap_init(&temp_pool,0,1024,1))
3567     return 1;
3568 #else
3569   use_temp_pool= 0;
3570 #endif
3571 
3572   if (my_dboptions_cache_init())
3573     return 1;
3574 
3575   /*
3576     Ensure that lower_case_table_names is set on system where we have case
3577     insensitive names.  If this is not done the users MyISAM tables will
3578     get corrupted if accesses with names of different case.
3579   */
3580   DBUG_PRINT("info", ("lower_case_table_names: %d", lower_case_table_names));
3581   lower_case_file_system= test_if_case_insensitive(mysql_real_data_home);
3582   if (!lower_case_table_names && lower_case_file_system == 1)
3583   {
3584     if (lower_case_table_names_used)
3585     {
3586       sql_print_error("The server option 'lower_case_table_names' is "
3587                       "configured to use case sensitive table names but the "
3588                       "data directory is on a case-insensitive file system "
3589                       "which is an unsupported combination. Please consider "
3590                       "either using a case sensitive file system for your data "
3591                       "directory or switching to a case-insensitive table name "
3592                       "mode.");
3593       return 1;
3594     }
3595     else
3596     {
3597       if (global_system_variables.log_warnings)
3598 	sql_print_warning("Setting lower_case_table_names=2 because file system for %s is case insensitive", mysql_real_data_home);
3599       lower_case_table_names= 2;
3600     }
3601   }
3602   else if (lower_case_table_names == 2 &&
3603            !(lower_case_file_system=
3604              (test_if_case_insensitive(mysql_real_data_home) == 1)))
3605   {
3606     if (global_system_variables.log_warnings)
3607       sql_print_warning("lower_case_table_names was set to 2, even though your "
3608                         "the file system '%s' is case sensitive.  Now setting "
3609                         "lower_case_table_names to 0 to avoid future problems.",
3610 			mysql_real_data_home);
3611     lower_case_table_names= 0;
3612   }
3613   else
3614   {
3615     lower_case_file_system=
3616       (test_if_case_insensitive(mysql_real_data_home) == 1);
3617   }
3618 
3619   /* Reset table_alias_charset, now that lower_case_table_names is set. */
3620   table_alias_charset= (lower_case_table_names ?
3621 			files_charset_info :
3622 			&my_charset_bin);
3623 
3624   return 0;
3625 }
3626 
3627 
init_thread_environment()3628 static int init_thread_environment()
3629 {
3630   mysql_mutex_init(key_LOCK_thread_created, &LOCK_thread_created, MY_MUTEX_INIT_FAST);
3631   mysql_mutex_init(key_LOCK_thread_count, &LOCK_thread_count, MY_MUTEX_INIT_FAST);
3632   mysql_mutex_init(key_LOCK_status, &LOCK_status, MY_MUTEX_INIT_FAST);
3633   mysql_mutex_init(key_LOCK_thd_remove,
3634                    &LOCK_thd_remove, MY_MUTEX_INIT_FAST);
3635   mysql_mutex_init(key_LOCK_delayed_insert,
3636                    &LOCK_delayed_insert, MY_MUTEX_INIT_FAST);
3637   mysql_mutex_init(key_LOCK_delayed_status,
3638                    &LOCK_delayed_status, MY_MUTEX_INIT_FAST);
3639   mysql_mutex_init(key_LOCK_delayed_create,
3640                    &LOCK_delayed_create, MY_MUTEX_INIT_SLOW);
3641   mysql_mutex_init(key_LOCK_manager,
3642                    &LOCK_manager, MY_MUTEX_INIT_FAST);
3643   mysql_mutex_init(key_LOCK_crypt, &LOCK_crypt, MY_MUTEX_INIT_FAST);
3644   mysql_mutex_init(key_LOCK_user_conn, &LOCK_user_conn, MY_MUTEX_INIT_FAST);
3645   mysql_mutex_init(key_LOCK_active_mi, &LOCK_active_mi, MY_MUTEX_INIT_FAST);
3646   mysql_mutex_init(key_LOCK_global_system_variables,
3647                    &LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
3648   mysql_rwlock_init(key_rwlock_LOCK_system_variables_hash,
3649                     &LOCK_system_variables_hash);
3650   mysql_mutex_init(key_LOCK_prepared_stmt_count,
3651                    &LOCK_prepared_stmt_count, MY_MUTEX_INIT_FAST);
3652   mysql_mutex_init(key_LOCK_error_messages,
3653                    &LOCK_error_messages, MY_MUTEX_INIT_FAST);
3654   mysql_mutex_init(key_LOCK_uuid_generator,
3655                    &LOCK_uuid_generator, MY_MUTEX_INIT_FAST);
3656   mysql_mutex_init(key_LOCK_connection_count,
3657                    &LOCK_connection_count, MY_MUTEX_INIT_FAST);
3658 #ifdef HAVE_OPENSSL
3659   mysql_mutex_init(key_LOCK_des_key_file,
3660                    &LOCK_des_key_file, MY_MUTEX_INIT_FAST);
3661 #ifndef HAVE_YASSL
3662   openssl_stdlocks= (openssl_lock_t*) OPENSSL_malloc(CRYPTO_num_locks() *
3663                                                      sizeof(openssl_lock_t));
3664   for (int i= 0; i < CRYPTO_num_locks(); ++i)
3665     mysql_rwlock_init(key_rwlock_openssl, &openssl_stdlocks[i].lock);
3666   CRYPTO_set_dynlock_create_callback(openssl_dynlock_create);
3667   CRYPTO_set_dynlock_destroy_callback(openssl_dynlock_destroy);
3668   CRYPTO_set_dynlock_lock_callback(openssl_lock);
3669   CRYPTO_set_locking_callback(openssl_lock_function);
3670   CRYPTO_set_id_callback(openssl_id_function);
3671 #endif
3672 #endif
3673   mysql_rwlock_init(key_rwlock_LOCK_sys_init_connect, &LOCK_sys_init_connect);
3674   mysql_rwlock_init(key_rwlock_LOCK_sys_init_slave, &LOCK_sys_init_slave);
3675   mysql_rwlock_init(key_rwlock_LOCK_grant, &LOCK_grant);
3676   mysql_cond_init(key_COND_thread_count, &COND_thread_count, NULL);
3677   mysql_cond_init(key_COND_thread_cache, &COND_thread_cache, NULL);
3678   mysql_cond_init(key_COND_flush_thread_cache, &COND_flush_thread_cache, NULL);
3679   mysql_cond_init(key_COND_manager, &COND_manager, NULL);
3680 #ifdef HAVE_REPLICATION
3681   mysql_mutex_init(key_LOCK_rpl_status, &LOCK_rpl_status, MY_MUTEX_INIT_FAST);
3682   mysql_cond_init(key_COND_rpl_status, &COND_rpl_status, NULL);
3683 #endif
3684   mysql_mutex_init(key_LOCK_server_started,
3685                    &LOCK_server_started, MY_MUTEX_INIT_FAST);
3686   mysql_cond_init(key_COND_server_started, &COND_server_started, NULL);
3687   sp_cache_init();
3688 #ifdef HAVE_EVENT_SCHEDULER
3689   Events::init_mutexes();
3690 #endif
3691   /* Parameter for threads created for connections */
3692   (void) pthread_attr_init(&connection_attrib);
3693   (void) pthread_attr_setdetachstate(&connection_attrib,
3694 				     PTHREAD_CREATE_DETACHED);
3695   pthread_attr_setscope(&connection_attrib, PTHREAD_SCOPE_SYSTEM);
3696 
3697   if (pthread_key_create(&THR_THD,NULL) ||
3698       pthread_key_create(&THR_MALLOC,NULL))
3699   {
3700     sql_print_error("Can't create thread-keys");
3701     return 1;
3702   }
3703   return 0;
3704 }
3705 
3706 
3707 #if defined(HAVE_OPENSSL) && !defined(HAVE_YASSL)
openssl_id_function()3708 static unsigned long openssl_id_function()
3709 {
3710   return (unsigned long) pthread_self();
3711 }
3712 
3713 
openssl_dynlock_create(const char * file,int line)3714 static openssl_lock_t *openssl_dynlock_create(const char *file, int line)
3715 {
3716   openssl_lock_t *lock= new openssl_lock_t;
3717   mysql_rwlock_init(key_rwlock_openssl, &lock->lock);
3718   return lock;
3719 }
3720 
3721 
openssl_dynlock_destroy(openssl_lock_t * lock,const char * file,int line)3722 static void openssl_dynlock_destroy(openssl_lock_t *lock, const char *file,
3723 				    int line)
3724 {
3725   mysql_rwlock_destroy(&lock->lock);
3726   delete lock;
3727 }
3728 
3729 
openssl_lock_function(int mode,int n,const char * file,int line)3730 static void openssl_lock_function(int mode, int n, const char *file, int line)
3731 {
3732   if (n < 0 || n > CRYPTO_num_locks())
3733   {
3734     /* Lock number out of bounds. */
3735     sql_print_error("Fatal: OpenSSL interface problem (n = %d)", n);
3736     abort();
3737   }
3738   openssl_lock(mode, &openssl_stdlocks[n], file, line);
3739 }
3740 
3741 
openssl_lock(int mode,openssl_lock_t * lock,const char * file,int line)3742 static void openssl_lock(int mode, openssl_lock_t *lock, const char *file,
3743 			 int line)
3744 {
3745   int err;
3746   char const *what;
3747 
3748   switch (mode) {
3749   case CRYPTO_LOCK|CRYPTO_READ:
3750     what = "read lock";
3751     err= mysql_rwlock_rdlock(&lock->lock);
3752     break;
3753   case CRYPTO_LOCK|CRYPTO_WRITE:
3754     what = "write lock";
3755     err= mysql_rwlock_wrlock(&lock->lock);
3756     break;
3757   case CRYPTO_UNLOCK|CRYPTO_READ:
3758   case CRYPTO_UNLOCK|CRYPTO_WRITE:
3759     what = "unlock";
3760     err= mysql_rwlock_unlock(&lock->lock);
3761     break;
3762   default:
3763     /* Unknown locking mode. */
3764     sql_print_error("Fatal: OpenSSL interface problem (mode=0x%x)", mode);
3765     abort();
3766   }
3767   if (err)
3768   {
3769     sql_print_error("Fatal: can't %s OpenSSL lock", what);
3770     abort();
3771   }
3772 }
3773 #endif /* HAVE_OPENSSL */
3774 
3775 
init_ssl()3776 static void init_ssl()
3777 {
3778 #ifdef HAVE_OPENSSL
3779 #ifndef EMBEDDED_LIBRARY
3780   if (opt_use_ssl)
3781   {
3782     enum enum_ssl_init_error error= SSL_INITERR_NOERROR;
3783 
3784     /* having ssl_acceptor_fd != 0 signals the use of SSL */
3785     ssl_acceptor_fd= new_VioSSLAcceptorFd(opt_ssl_key, opt_ssl_cert,
3786 					  opt_ssl_ca, opt_ssl_capath,
3787 					  opt_ssl_cipher, &error);
3788     DBUG_PRINT("info",("ssl_acceptor_fd: 0x%lx", (long) ssl_acceptor_fd));
3789     if (!ssl_acceptor_fd)
3790     {
3791       sql_print_warning("Failed to setup SSL");
3792       sql_print_warning("SSL error: %s", sslGetErrString(error));
3793       opt_use_ssl = 0;
3794       have_ssl= SHOW_OPTION_DISABLED;
3795     }
3796   }
3797   else
3798   {
3799     have_ssl= SHOW_OPTION_DISABLED;
3800   }
3801 #else
3802   have_ssl= SHOW_OPTION_DISABLED;
3803 #endif /* ! EMBEDDED_LIBRARY */
3804   if (des_key_file)
3805     load_des_key_file(des_key_file);
3806 #endif /* HAVE_OPENSSL */
3807 }
3808 
3809 
end_ssl()3810 static void end_ssl()
3811 {
3812 #ifdef HAVE_OPENSSL
3813 #ifndef EMBEDDED_LIBRARY
3814   if (ssl_acceptor_fd)
3815   {
3816     free_vio_ssl_acceptor_fd(ssl_acceptor_fd);
3817     ssl_acceptor_fd= 0;
3818   }
3819 #endif /* ! EMBEDDED_LIBRARY */
3820 #endif /* HAVE_OPENSSL */
3821 }
3822 
3823 
init_server_components()3824 static int init_server_components()
3825 {
3826   DBUG_ENTER("init_server_components");
3827   /*
3828     We need to call each of these following functions to ensure that
3829     all things are initialized so that unireg_abort() doesn't fail
3830   */
3831   mdl_init();
3832   if (table_def_init() | hostname_cache_init())
3833     unireg_abort(1);
3834 
3835   query_cache_set_min_res_unit(query_cache_min_res_unit);
3836   query_cache_init();
3837   query_cache_resize(query_cache_size);
3838   randominit(&sql_rand,(ulong) server_start_time,(ulong) server_start_time/2);
3839   setup_fpu();
3840   init_thr_lock();
3841 #ifdef HAVE_REPLICATION
3842   init_slave_list();
3843 #endif
3844 
3845   /* Setup logs */
3846 
3847   /*
3848     Enable old-fashioned error log, except when the user has requested
3849     help information. Since the implementation of plugin server
3850     variables the help output is now written much later.
3851   */
3852   if (opt_error_log && !opt_help)
3853   {
3854     if (!log_error_file_ptr[0])
3855       fn_format(log_error_file, pidfile_name, mysql_data_home, ".err",
3856                 MY_REPLACE_EXT); /* replace '.<domain>' by '.err', bug#4997 */
3857     else
3858       fn_format(log_error_file, log_error_file_ptr, mysql_data_home, ".err",
3859                 MY_UNPACK_FILENAME | MY_SAFE_PATH);
3860     /*
3861       _ptr may have been set to my_disabled_option or "" if no argument was
3862       passed, but we need to show the real name in SHOW VARIABLES:
3863     */
3864     log_error_file_ptr= log_error_file;
3865     if (!log_error_file[0])
3866       opt_error_log= 0;                         // Too long file name
3867     else
3868     {
3869       my_bool res;
3870 #ifndef EMBEDDED_LIBRARY
3871       res= reopen_fstreams(log_error_file, stdout, stderr);
3872 #else
3873       res= reopen_fstreams(log_error_file, NULL, stderr);
3874 #endif
3875 
3876       if (!res)
3877         setbuf(stderr, NULL);
3878     }
3879   }
3880 
3881   proc_info_hook= set_thd_proc_info;
3882 
3883 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
3884   /*
3885     Parsing the performance schema command line option may have reported
3886     warnings/information messages.
3887     Now that the logger is finally available, and redirected
3888     to the proper file when the --log--error option is used,
3889     print the buffered messages to the log.
3890   */
3891   buffered_logs.print();
3892   buffered_logs.cleanup();
3893 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
3894 
3895   if (xid_cache_init())
3896   {
3897     sql_print_error("Out of memory");
3898     unireg_abort(1);
3899   }
3900 
3901   /*
3902     initialize delegates for extension observers, errors have already
3903     been reported in the function
3904   */
3905   if (delegates_init())
3906     unireg_abort(1);
3907 
3908   /* need to configure logging before initializing storage engines */
3909   if (opt_log_slave_updates && !opt_bin_log)
3910   {
3911     sql_print_warning("You need to use --log-bin to make "
3912                     "--log-slave-updates work.");
3913   }
3914   if (!opt_bin_log && binlog_format_used)
3915     sql_print_warning("You need to use --log-bin to make "
3916                       "--binlog-format work.");
3917 
3918   /* Check that we have not let the format to unspecified at this point */
3919   DBUG_ASSERT((uint)global_system_variables.binlog_format <=
3920               array_elements(binlog_format_names)-1);
3921 
3922 #ifdef HAVE_REPLICATION
3923   if (opt_log_slave_updates && replicate_same_server_id)
3924   {
3925     if (opt_bin_log)
3926     {
3927       sql_print_error("using --replicate-same-server-id in conjunction with \
3928 --log-slave-updates is impossible, it would lead to infinite loops in this \
3929 server.");
3930       unireg_abort(1);
3931     }
3932     else
3933       sql_print_warning("using --replicate-same-server-id in conjunction with \
3934 --log-slave-updates would lead to infinite loops in this server. However this \
3935 will be ignored as the --log-bin option is not defined.");
3936   }
3937 #endif
3938 
3939   if (opt_bin_log)
3940   {
3941     /* Reports an error and aborts, if the --log-bin's path
3942        is a directory.*/
3943     if (opt_bin_logname &&
3944         opt_bin_logname[strlen(opt_bin_logname) - 1] == FN_LIBCHAR)
3945     {
3946       sql_print_error("Path '%s' is a directory name, please specify \
3947 a file name for --log-bin option", opt_bin_logname);
3948       unireg_abort(1);
3949     }
3950 
3951     /* Reports an error and aborts, if the --log-bin-index's path
3952        is a directory.*/
3953     if (opt_binlog_index_name &&
3954         opt_binlog_index_name[strlen(opt_binlog_index_name) - 1]
3955         == FN_LIBCHAR)
3956     {
3957       sql_print_error("Path '%s' is a directory name, please specify \
3958 a file name for --log-bin-index option", opt_binlog_index_name);
3959       unireg_abort(1);
3960     }
3961 
3962     char buf[FN_REFLEN];
3963     const char *ln;
3964     ln= mysql_bin_log.generate_name(opt_bin_logname, "-bin", 1, buf);
3965     if (!opt_bin_logname && !opt_binlog_index_name)
3966     {
3967       /*
3968         User didn't give us info to name the binlog index file.
3969         Picking `hostname`-bin.index like did in 4.x, causes replication to
3970         fail if the hostname is changed later. So, we would like to instead
3971         require a name. But as we don't want to break many existing setups, we
3972         only give warning, not error.
3973       */
3974       sql_print_warning("No argument was provided to --log-bin, and "
3975                         "--log-bin-index was not used; so replication "
3976                         "may break when this MySQL server acts as a "
3977                         "master and has his hostname changed!! Please "
3978                         "use '--log-bin=%s' to avoid this problem.", ln);
3979     }
3980     if (ln == buf)
3981     {
3982       my_free(opt_bin_logname);
3983       opt_bin_logname=my_strdup(buf, MYF(0));
3984     }
3985     if (mysql_bin_log.open_index_file(opt_binlog_index_name, ln, TRUE))
3986     {
3987       unireg_abort(1);
3988     }
3989   }
3990 
3991   /* call ha_init_key_cache() on all key caches to init them */
3992   process_key_caches(&ha_init_key_cache);
3993 
3994   /* Allow storage engine to give real error messages */
3995   if (ha_init_errors())
3996     DBUG_RETURN(1);
3997 
3998   if (opt_ignore_builtin_innodb)
3999     sql_print_warning("ignore-builtin-innodb is deprecated "
4000                       "and will be removed in future releases.");
4001 
4002   if (plugin_init(&remaining_argc, remaining_argv,
4003                   (opt_noacl ? PLUGIN_INIT_SKIP_PLUGIN_TABLE : 0) |
4004                   (opt_help ? PLUGIN_INIT_SKIP_INITIALIZATION : 0)))
4005   {
4006     sql_print_error("Failed to initialize plugins.");
4007     unireg_abort(1);
4008   }
4009   plugins_are_initialized= TRUE;  /* Don't separate from init function */
4010 
4011   have_csv= plugin_status(STRING_WITH_LEN("csv"),
4012                           MYSQL_STORAGE_ENGINE_PLUGIN);
4013   have_ndbcluster= plugin_status(STRING_WITH_LEN("ndbcluster"),
4014                                  MYSQL_STORAGE_ENGINE_PLUGIN);
4015   have_partitioning= plugin_status(STRING_WITH_LEN("partition"),
4016                                    MYSQL_STORAGE_ENGINE_PLUGIN);
4017 
4018   /* we do want to exit if there are any other unknown options */
4019   if (remaining_argc > 1)
4020   {
4021     int ho_error;
4022     struct my_option no_opts[]=
4023     {
4024       {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
4025     };
4026     /*
4027       We need to eat any 'loose' arguments first before we conclude
4028       that there are unprocessed options.
4029     */
4030     my_getopt_skip_unknown= 0;
4031 
4032     if ((ho_error= handle_options(&remaining_argc, &remaining_argv, no_opts,
4033                                   mysqld_get_one_option)))
4034       unireg_abort(ho_error);
4035     /* Add back the program name handle_options removes */
4036     remaining_argc++;
4037     remaining_argv--;
4038     my_getopt_skip_unknown= TRUE;
4039 
4040     if (remaining_argc > 1)
4041     {
4042       fprintf(stderr, "%s: Too many arguments (first extra is '%s').\n"
4043               "Use --verbose --help to get a list of available options\n",
4044               my_progname, remaining_argv[1]);
4045       unireg_abort(1);
4046     }
4047   }
4048 
4049   if (opt_help)
4050     unireg_abort(0);
4051 
4052   /* if the errmsg.sys is not loaded, terminate to maintain behaviour */
4053   if (!DEFAULT_ERRMSGS[0][0])
4054     unireg_abort(1);
4055 
4056   /* We have to initialize the storage engines before CSV logging */
4057   if (ha_init())
4058   {
4059     sql_print_error("Can't init databases");
4060     unireg_abort(1);
4061   }
4062 
4063 #ifdef WITH_CSV_STORAGE_ENGINE
4064   if (opt_bootstrap)
4065     log_output_options= LOG_FILE;
4066   else
4067     logger.init_log_tables();
4068 
4069   if (log_output_options & LOG_NONE)
4070   {
4071     /*
4072       Issue a warining if there were specified additional options to the
4073       log-output along with NONE. Probably this wasn't what user wanted.
4074     */
4075     if ((log_output_options & LOG_NONE) && (log_output_options & ~LOG_NONE))
4076       sql_print_warning("There were other values specified to "
4077                         "log-output besides NONE. Disabling slow "
4078                         "and general logs anyway.");
4079     logger.set_handlers(LOG_FILE, LOG_NONE, LOG_NONE);
4080   }
4081   else
4082   {
4083     /* fall back to the log files if tables are not present */
4084     LEX_STRING csv_name={C_STRING_WITH_LEN("csv")};
4085     if (!plugin_is_ready(&csv_name, MYSQL_STORAGE_ENGINE_PLUGIN))
4086     {
4087       /* purecov: begin inspected */
4088       sql_print_error("CSV engine is not present, falling back to the "
4089                       "log files");
4090       log_output_options= (log_output_options & ~LOG_TABLE) | LOG_FILE;
4091       /* purecov: end */
4092     }
4093 
4094     logger.set_handlers(LOG_FILE, opt_slow_log ? log_output_options:LOG_NONE,
4095                         opt_log ? log_output_options:LOG_NONE);
4096   }
4097 #else
4098   logger.set_handlers(LOG_FILE, opt_slow_log ? LOG_FILE:LOG_NONE,
4099                       opt_log ? LOG_FILE:LOG_NONE);
4100 #endif
4101 
4102   /*
4103     Set the default storage engine
4104   */
4105   LEX_STRING name= { default_storage_engine, strlen(default_storage_engine) };
4106   plugin_ref plugin;
4107   handlerton *hton;
4108   if ((plugin= ha_resolve_by_name(0, &name)))
4109     hton= plugin_data(plugin, handlerton*);
4110   else
4111   {
4112     sql_print_error("Unknown/unsupported storage engine: %s",
4113                     default_storage_engine);
4114     unireg_abort(1);
4115   }
4116   if (!ha_storage_engine_is_enabled(hton))
4117   {
4118     if (!opt_bootstrap)
4119     {
4120       sql_print_error("Default storage engine (%s) is not available",
4121                       default_storage_engine);
4122       unireg_abort(1);
4123     }
4124     DBUG_ASSERT(global_system_variables.table_plugin);
4125   }
4126   else
4127   {
4128     /*
4129       Need to unlock as global_system_variables.table_plugin
4130       was acquired during plugin_init()
4131     */
4132     plugin_unlock(0, global_system_variables.table_plugin);
4133     global_system_variables.table_plugin= plugin;
4134   }
4135 
4136   tc_log= (total_ha_2pc > 1 ? (opt_bin_log  ?
4137                                (TC_LOG *) &mysql_bin_log :
4138                                (TC_LOG *) &tc_log_mmap) :
4139            (TC_LOG *) &tc_log_dummy);
4140 
4141   if (tc_log->open(opt_bin_log ? opt_bin_logname : opt_tc_log_file))
4142   {
4143     sql_print_error("Can't init tc log");
4144     unireg_abort(1);
4145   }
4146 
4147   if (ha_recover(0))
4148   {
4149     unireg_abort(1);
4150   }
4151 
4152   if (opt_bin_log && mysql_bin_log.open(opt_bin_logname, LOG_BIN, 0,
4153                                         WRITE_CACHE, 0, max_binlog_size, 0, TRUE))
4154     unireg_abort(1);
4155 
4156 #ifdef HAVE_REPLICATION
4157   if (opt_bin_log && expire_logs_days)
4158   {
4159     time_t purge_time= server_start_time - expire_logs_days*24*60*60;
4160     if (purge_time >= 0)
4161       mysql_bin_log.purge_logs_before_date(purge_time);
4162   }
4163 #endif
4164 
4165   if (opt_myisam_log)
4166     (void) mi_log(1);
4167 
4168 #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && !defined(EMBEDDED_LIBRARY)
4169   if (locked_in_memory && !getuid())
4170   {
4171     if (setreuid((uid_t)-1, 0) == -1)
4172     {                        // this should never happen
4173       sql_perror("setreuid");
4174       unireg_abort(1);
4175     }
4176     if (mlockall(MCL_CURRENT))
4177     {
4178       if (global_system_variables.log_warnings)
4179 	sql_print_warning("Failed to lock memory. Errno: %d\n",errno);
4180       locked_in_memory= 0;
4181     }
4182     if (user_info)
4183       set_user(mysqld_user, user_info);
4184   }
4185   else
4186 #endif
4187     locked_in_memory=0;
4188 
4189   ft_init_stopwords();
4190 
4191   init_max_user_conn();
4192   init_update_queries();
4193   DBUG_RETURN(0);
4194 }
4195 
4196 
4197 #ifndef EMBEDDED_LIBRARY
4198 
create_shutdown_thread()4199 static void create_shutdown_thread()
4200 {
4201 #ifdef __WIN__
4202   hEventShutdown=CreateEvent(0, FALSE, FALSE, shutdown_event_name);
4203   pthread_t hThread;
4204   int error;
4205   if ((error= mysql_thread_create(key_thread_handle_shutdown,
4206                                   &hThread, &connection_attrib,
4207                                   handle_shutdown, 0)))
4208     sql_print_warning("Can't create thread to handle shutdown requests"
4209                       " (errno= %d)", error);
4210 
4211   // On "Stop Service" we have to do regular shutdown
4212   Service.SetShutdownEvent(hEventShutdown);
4213 #endif /* __WIN__ */
4214 }
4215 
4216 #endif /* EMBEDDED_LIBRARY */
4217 
4218 
4219 #if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
handle_connections_methods()4220 static void handle_connections_methods()
4221 {
4222   pthread_t hThread;
4223   int error;
4224   DBUG_ENTER("handle_connections_methods");
4225   if (hPipe == INVALID_HANDLE_VALUE &&
4226       (!have_tcpip || opt_disable_networking) &&
4227       !opt_enable_shared_memory)
4228   {
4229     sql_print_error("TCP/IP, --shared-memory, or --named-pipe should be configured on NT OS");
4230     unireg_abort(1);				// Will not return
4231   }
4232 
4233   mysql_mutex_lock(&LOCK_thread_count);
4234   mysql_cond_init(key_COND_handler_count, &COND_handler_count, NULL);
4235   handler_count=0;
4236   if (hPipe != INVALID_HANDLE_VALUE)
4237   {
4238     handler_count++;
4239     if ((error= mysql_thread_create(key_thread_handle_con_namedpipes,
4240                                     &hThread, &connection_attrib,
4241                                     handle_connections_namedpipes, 0)))
4242     {
4243       sql_print_warning("Can't create thread to handle named pipes"
4244                         " (errno= %d)", error);
4245       handler_count--;
4246     }
4247   }
4248   if (have_tcpip && !opt_disable_networking)
4249   {
4250     handler_count++;
4251     if ((error= mysql_thread_create(key_thread_handle_con_sockets,
4252                                     &hThread, &connection_attrib,
4253                                     handle_connections_sockets_thread, 0)))
4254     {
4255       sql_print_warning("Can't create thread to handle TCP/IP",
4256                         " (errno= %d)", error);
4257       handler_count--;
4258     }
4259   }
4260 #ifdef HAVE_SMEM
4261   if (opt_enable_shared_memory)
4262   {
4263     handler_count++;
4264     if ((error= mysql_thread_create(key_thread_handle_con_sharedmem,
4265                                     &hThread, &connection_attrib,
4266                                     handle_connections_shared_memory, 0)))
4267     {
4268       sql_print_warning("Can't create thread to handle shared memory",
4269                         " (errno= %d)", error);
4270       handler_count--;
4271     }
4272   }
4273 #endif
4274 
4275   while (handler_count > 0)
4276     mysql_cond_wait(&COND_handler_count, &LOCK_thread_count);
4277   mysql_mutex_unlock(&LOCK_thread_count);
4278   DBUG_VOID_RETURN;
4279 }
4280 
decrement_handler_count()4281 void decrement_handler_count()
4282 {
4283   mysql_mutex_lock(&LOCK_thread_count);
4284   handler_count--;
4285   mysql_cond_signal(&COND_handler_count);
4286   mysql_mutex_unlock(&LOCK_thread_count);
4287   my_thread_end();
4288 }
4289 #else
4290 #define decrement_handler_count()
4291 #endif /* defined(_WIN32) || defined(HAVE_SMEM) */
4292 
4293 
4294 #ifndef EMBEDDED_LIBRARY
4295 #ifndef DBUG_OFF
4296 /*
4297   Debugging helper function to keep the locale database
4298   (see sql_locale.cc) and max_month_name_length and
4299   max_day_name_length variable values in consistent state.
4300 */
test_lc_time_sz()4301 static void test_lc_time_sz()
4302 {
4303   DBUG_ENTER("test_lc_time_sz");
4304   for (MY_LOCALE **loc= my_locales; *loc; loc++)
4305   {
4306     uint max_month_len= 0;
4307     uint max_day_len = 0;
4308     for (const char **month= (*loc)->month_names->type_names; *month; month++)
4309     {
4310       set_if_bigger(max_month_len,
4311                     my_numchars_mb(&my_charset_utf8_general_ci,
4312                                    *month, *month + strlen(*month)));
4313     }
4314     for (const char **day= (*loc)->day_names->type_names; *day; day++)
4315     {
4316       set_if_bigger(max_day_len,
4317                     my_numchars_mb(&my_charset_utf8_general_ci,
4318                                    *day, *day + strlen(*day)));
4319     }
4320     if ((*loc)->max_month_name_length != max_month_len ||
4321         (*loc)->max_day_name_length != max_day_len)
4322     {
4323       DBUG_PRINT("Wrong max day name(or month name) length for locale:",
4324                  ("%s", (*loc)->name));
4325       DBUG_ASSERT(0);
4326     }
4327   }
4328   DBUG_VOID_RETURN;
4329 }
4330 #endif//DBUG_OFF
4331 
4332 #ifdef __WIN__
win_main(int argc,char ** argv)4333 int win_main(int argc, char **argv)
4334 #else
4335 int mysqld_main(int argc, char **argv)
4336 #endif
4337 {
4338   /*
4339     Perform basic thread library and malloc initialization,
4340     to be able to read defaults files and parse options.
4341   */
4342   my_progname= argv[0];
4343 #ifdef HAVE_NPTL
4344   ld_assume_kernel_is_set= (getenv("LD_ASSUME_KERNEL") != 0);
4345 #endif
4346 #ifndef _WIN32
4347   // For windows, my_init() is called from the win specific mysqld_main
4348   if (my_init())                 // init my_sys library & pthreads
4349   {
4350     fprintf(stderr, "my_init() failed.");
4351     return 1;
4352   }
4353 #endif
4354 
4355   orig_argc= argc;
4356   orig_argv= argv;
4357   my_getopt_use_args_separator= TRUE;
4358   if (load_defaults(MYSQL_CONFIG_NAME, load_default_groups, &argc, &argv))
4359     return 1;
4360   my_getopt_use_args_separator= FALSE;
4361   defaults_argc= argc;
4362   defaults_argv= argv;
4363   remaining_argc= argc;
4364   remaining_argv= argv;
4365 
4366   /* Must be initialized early for comparison of options name */
4367   system_charset_info= &my_charset_utf8_general_ci;
4368 
4369   init_sql_statement_names();
4370   sys_var_init();
4371 
4372 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
4373   /*
4374     The performance schema needs to be initialized as early as possible,
4375     before to-be-instrumented objects of the server are initialized.
4376   */
4377   int ho_error;
4378   DYNAMIC_ARRAY all_early_options;
4379 
4380   my_getopt_register_get_addr(NULL);
4381   /* Skip unknown options so that they may be processed later */
4382   my_getopt_skip_unknown= TRUE;
4383 
4384   /* prepare all_early_options array */
4385   my_init_dynamic_array(&all_early_options, sizeof(my_option), 100, 25);
4386   sys_var_add_options(&all_early_options, sys_var::PARSE_EARLY);
4387   add_terminator(&all_early_options);
4388 
4389   /*
4390     Logs generated while parsing the command line
4391     options are buffered and printed later.
4392   */
4393   buffered_logs.init();
4394   my_getopt_error_reporter= buffered_option_error_reporter;
4395 
4396   ho_error= handle_options(&remaining_argc, &remaining_argv,
4397                            (my_option*)(all_early_options.buffer), NULL);
4398   delete_dynamic(&all_early_options);
4399   if (ho_error == 0)
4400   {
4401     /* Add back the program name handle_options removes */
4402     remaining_argc++;
4403     remaining_argv--;
4404     if (pfs_param.m_enabled)
4405     {
4406       PSI_hook= initialize_performance_schema(&pfs_param);
4407       if (PSI_hook == NULL)
4408       {
4409         pfs_param.m_enabled= false;
4410         buffered_logs.buffer(WARNING_LEVEL,
4411                              "Performance schema disabled (reason: init failed).");
4412       }
4413     }
4414   }
4415 #else
4416   /*
4417     Other provider of the instrumentation interface should
4418     initialize PSI_hook here:
4419     - HAVE_PSI_INTERFACE is for the instrumentation interface
4420     - WITH_PERFSCHEMA_STORAGE_ENGINE is for one implementation
4421       of the interface,
4422     but there could be alternate implementations, which is why
4423     these two defines are kept separate.
4424   */
4425 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
4426 
4427 #ifdef HAVE_PSI_INTERFACE
4428   /*
4429     Obtain the current performance schema instrumentation interface,
4430     if available.
4431   */
4432   if (PSI_hook)
4433     PSI_server= (PSI*) PSI_hook->get_interface(PSI_CURRENT_VERSION);
4434 
4435   if (PSI_server)
4436   {
4437     /*
4438       Now that we have parsed the command line arguments, and have initialized
4439       the performance schema itself, the next step is to register all the
4440       server instruments.
4441     */
4442     init_server_psi_keys();
4443     /* Instrument the main thread */
4444     PSI_thread *psi= PSI_server->new_thread(key_thread_main, NULL, 0);
4445     if (psi)
4446       PSI_server->set_thread(psi);
4447 
4448     /*
4449       Now that some instrumentation is in place,
4450       recreate objects which were initialised early,
4451       so that they are instrumented as well.
4452     */
4453     my_thread_global_reinit();
4454   }
4455 #endif /* HAVE_PSI_INTERFACE */
4456 
4457   init_error_log_mutex();
4458 
4459   /* Set signal used to kill MySQL */
4460 #if defined(SIGUSR2)
4461   thr_kill_signal= thd_lib_detected == THD_LIB_LT ? SIGINT : SIGUSR2;
4462 #else
4463   thr_kill_signal= SIGINT;
4464 #endif
4465 
4466   /* Initialize audit interface globals. Audit plugins are inited later. */
4467   mysql_audit_initialize();
4468 
4469   /*
4470     Perform basic logger initialization logger. Should be called after
4471     MY_INIT, as it initializes mutexes. Log tables are inited later.
4472   */
4473   logger.init_base();
4474 
4475 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
4476   if (ho_error)
4477   {
4478     /*
4479       Parsing command line option failed,
4480       Since we don't have a workable remaining_argc/remaining_argv
4481       to continue the server initialization, this is as far as this
4482       code can go.
4483       This is the best effort to log meaningful messages:
4484       - messages will be printed to stderr, which is not redirected yet,
4485       - messages will be printed in the NT event log, for windows.
4486     */
4487     buffered_logs.print();
4488     buffered_logs.cleanup();
4489     /*
4490       Not enough initializations for unireg_abort()
4491       Using exit() for windows.
4492     */
4493     exit (ho_error);
4494   }
4495 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
4496 
4497 #ifdef _CUSTOMSTARTUPCONFIG_
4498   if (_cust_check_startup())
4499   {
4500     / * _cust_check_startup will report startup failure error * /
4501     exit(1);
4502   }
4503 #endif
4504 
4505   if (init_common_variables())
4506     unireg_abort(1);				// Will do exit
4507 
4508   init_signals();
4509 #if defined(__ia64__) || defined(__ia64)
4510   /*
4511     Peculiar things with ia64 platforms - it seems we only have half the
4512     stack size in reality, so we have to double it here
4513   */
4514   pthread_attr_setstacksize(&connection_attrib,my_thread_stack_size*2);
4515 #else
4516   pthread_attr_setstacksize(&connection_attrib,my_thread_stack_size);
4517 #endif
4518 #ifdef HAVE_PTHREAD_ATTR_GETSTACKSIZE
4519   {
4520     /* Retrieve used stack size;  Needed for checking stack overflows */
4521     size_t stack_size= 0;
4522     pthread_attr_getstacksize(&connection_attrib, &stack_size);
4523 #if defined(__ia64__) || defined(__ia64)
4524     stack_size/= 2;
4525 #endif
4526     /* We must check if stack_size = 0 as Solaris 2.9 can return 0 here */
4527     if (stack_size && stack_size < my_thread_stack_size)
4528     {
4529       if (global_system_variables.log_warnings)
4530 	sql_print_warning("Asked for %lu thread stack, but got %ld",
4531 			  my_thread_stack_size, (long) stack_size);
4532 #if defined(__ia64__) || defined(__ia64)
4533       my_thread_stack_size= stack_size*2;
4534 #else
4535       my_thread_stack_size= stack_size;
4536 #endif
4537     }
4538   }
4539 #endif
4540 
4541   (void) thr_setconcurrency(concurrency);	// 10 by default
4542 
4543   select_thread=pthread_self();
4544   select_thread_in_use=1;
4545 
4546 #ifdef HAVE_LIBWRAP
4547   libwrapName= my_progname+dirname_length(my_progname);
4548   openlog(libwrapName, LOG_PID, LOG_AUTH);
4549 #endif
4550 
4551 #ifndef DBUG_OFF
4552   test_lc_time_sz();
4553 #endif
4554 
4555   /*
4556     We have enough space for fiddling with the argv, continue
4557   */
4558   check_data_home(mysql_real_data_home);
4559   if (my_setwd(mysql_real_data_home,MYF(MY_WME)) && !opt_help)
4560     unireg_abort(1);				/* purecov: inspected */
4561 
4562   if ((user_info= check_user(mysqld_user)))
4563   {
4564 #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
4565     if (locked_in_memory) // getuid() == 0 here
4566       set_effective_user(user_info);
4567     else
4568 #endif
4569       set_user(mysqld_user, user_info);
4570   }
4571 
4572   if (opt_bin_log && !server_id)
4573   {
4574     server_id= 1;
4575 #ifdef EXTRA_DEBUG
4576     sql_print_warning("You have enabled the binary log, but you haven't set "
4577                       "server-id to a non-zero value: we force server id to 1; "
4578                       "updates will be logged to the binary log, but "
4579                       "connections from slaves will not be accepted.");
4580 #endif
4581   }
4582 
4583   /*
4584    The subsequent calls may take a long time : e.g. innodb log read.
4585    Thus set the long running service control manager timeout
4586   */
4587 #if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
4588   Service.SetSlowStarting(slow_start_timeout);
4589 #endif
4590 
4591   if (init_server_components())
4592     unireg_abort(1);
4593 
4594   init_ssl();
4595   network_init();
4596 
4597 #ifdef __WIN__
4598   if (!opt_console)
4599   {
4600     if (reopen_fstreams(log_error_file, stdout, stderr))
4601       unireg_abort(1);
4602     setbuf(stderr, NULL);
4603     FreeConsole();				// Remove window
4604   }
4605 #endif
4606 
4607   /*
4608    Initialize my_str_malloc() and my_str_free()
4609   */
4610   my_str_malloc= &my_str_malloc_mysqld;
4611   my_str_free= &my_str_free_mysqld;
4612 
4613   /*
4614     init signals & alarm
4615     After this we can't quit by a simple unireg_abort
4616   */
4617   error_handler_hook= my_message_sql;
4618   sql_print_warning_hook = sql_print_warning;
4619   start_signal_handler();				// Creates pidfile
4620 
4621   if (mysql_rm_tmp_tables() || acl_init(opt_noacl) ||
4622       my_tz_init((THD *)0, default_tz_name, opt_bootstrap))
4623   {
4624     abort_loop=1;
4625     select_thread_in_use=0;
4626 
4627     (void) pthread_kill(signal_thread, MYSQL_KILL_SIGNAL);
4628 
4629     delete_pid_file(MYF(MY_WME));
4630 
4631     if (unix_sock != INVALID_SOCKET)
4632       unlink(mysqld_unix_port);
4633     exit(1);
4634   }
4635 
4636   if (!opt_noacl)
4637     (void) grant_init();
4638 
4639   if (!opt_bootstrap)
4640     servers_init(0);
4641 
4642   if (!opt_noacl)
4643   {
4644 #ifdef HAVE_DLOPEN
4645     udf_init();
4646 #endif
4647   }
4648 
4649   init_status_vars();
4650   if (opt_bootstrap) /* If running with bootstrap, do not start replication. */
4651     opt_skip_slave_start= 1;
4652 
4653   binlog_unsafe_map_init();
4654   /*
4655     init_slave() must be called after the thread keys are created.
4656     Some parts of the code (e.g. SHOW STATUS LIKE 'slave_running' and other
4657     places) assume that active_mi != 0, so let's fail if it's 0 (out of
4658     memory); a message has already been printed.
4659   */
4660   if (init_slave() && !active_mi)
4661   {
4662     unireg_abort(1);
4663   }
4664 
4665 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
4666   initialize_performance_schema_acl(opt_bootstrap);
4667   /*
4668     Do not check the structure of the performance schema tables
4669     during bootstrap:
4670     - the tables are not supposed to exist yet, bootstrap will create them
4671     - a check would print spurious error messages
4672   */
4673   if (! opt_bootstrap)
4674     check_performance_schema();
4675 #endif
4676 
4677   initialize_information_schema_acl();
4678 
4679   execute_ddl_log_recovery();
4680 
4681   if (Events::init(opt_noacl || opt_bootstrap))
4682     unireg_abort(1);
4683 
4684   if (opt_bootstrap)
4685   {
4686     select_thread_in_use= 0;                    // Allow 'kill' to work
4687     bootstrap(mysql_stdin);
4688     unireg_abort(bootstrap_error ? 1 : 0);
4689   }
4690   if (opt_init_file && *opt_init_file)
4691   {
4692     if (read_init_file(opt_init_file))
4693       unireg_abort(1);
4694   }
4695 
4696   create_shutdown_thread();
4697   start_handle_manager();
4698 
4699   sql_print_information(ER_DEFAULT(ER_STARTUP),my_progname,server_version,
4700                         ((unix_sock == INVALID_SOCKET) ? (char*) ""
4701                                                        : mysqld_unix_port),
4702                          mysqld_port,
4703                          MYSQL_COMPILATION_COMMENT);
4704 #if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
4705   Service.SetRunning();
4706 #endif
4707 
4708 
4709   /* Signal threads waiting for server to be started */
4710   mysql_mutex_lock(&LOCK_server_started);
4711   mysqld_server_started= 1;
4712   mysql_cond_signal(&COND_server_started);
4713   mysql_mutex_unlock(&LOCK_server_started);
4714 
4715 #if defined(_WIN32) || defined(HAVE_SMEM)
4716   handle_connections_methods();
4717 #else
4718   handle_connections_sockets();
4719 #endif /* _WIN32 || HAVE_SMEM */
4720 
4721   /* (void) pthread_attr_destroy(&connection_attrib); */
4722 
4723   DBUG_PRINT("quit",("Exiting main thread"));
4724 
4725 #ifndef __WIN__
4726 #ifdef EXTRA_DEBUG2
4727   sql_print_error("Before Lock_thread_count");
4728 #endif
4729   mysql_mutex_lock(&LOCK_thread_count);
4730   DBUG_PRINT("quit", ("Got thread_count mutex"));
4731   select_thread_in_use=0;			// For close_connections
4732   mysql_mutex_unlock(&LOCK_thread_count);
4733   mysql_cond_broadcast(&COND_thread_count);
4734 #ifdef EXTRA_DEBUG2
4735   sql_print_error("After lock_thread_count");
4736 #endif
4737 #endif /* __WIN__ */
4738 
4739 #ifdef HAVE_PSI_INTERFACE
4740   /*
4741     Disable the main thread instrumentation,
4742     to avoid recording events during the shutdown.
4743   */
4744   if (PSI_server)
4745     PSI_server->delete_current_thread();
4746 #endif
4747 
4748   /* Wait until cleanup is done */
4749   mysql_mutex_lock(&LOCK_thread_count);
4750   while (!ready_to_exit)
4751     mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
4752   mysql_mutex_unlock(&LOCK_thread_count);
4753 
4754 #if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
4755   if (Service.IsNT() && start_mode)
4756     Service.Stop();
4757   else
4758   {
4759     Service.SetShutdownEvent(0);
4760     if (hEventShutdown)
4761       CloseHandle(hEventShutdown);
4762   }
4763 #endif
4764   clean_up(1);
4765   mysqld_exit(0);
4766 }
4767 
4768 #endif /* !EMBEDDED_LIBRARY */
4769 
4770 
4771 /****************************************************************************
4772   Main and thread entry function for Win32
4773   (all this is needed only to run mysqld as a service on WinNT)
4774 ****************************************************************************/
4775 
4776 #if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
mysql_service(void * p)4777 int mysql_service(void *p)
4778 {
4779   if (my_thread_init())
4780     return 1;
4781 
4782   if (use_opt_args)
4783     win_main(opt_argc, opt_argv);
4784   else
4785     win_main(Service.my_argc, Service.my_argv);
4786 
4787   my_thread_end();
4788   return 0;
4789 }
4790 
4791 
4792 /* Quote string if it contains space, else copy */
4793 
add_quoted_string(char * to,const char * from,char * to_end)4794 static char *add_quoted_string(char *to, const char *from, char *to_end)
4795 {
4796   uint length= (uint) (to_end-to);
4797 
4798   if (!strchr(from, ' '))
4799     return strmake(to, from, length-1);
4800   return strxnmov(to, length-1, "\"", from, "\"", NullS);
4801 }
4802 
4803 
4804 /**
4805   Handle basic handling of services, like installation and removal.
4806 
4807   @param argv	   	        Pointer to argument list
4808   @param servicename		Internal name of service
4809   @param displayname		Display name of service (in taskbar ?)
4810   @param file_path		Path to this program
4811   @param startup_option	Startup option to mysqld
4812 
4813   @retval
4814     0		option handled
4815   @retval
4816     1		Could not handle option
4817 */
4818 
4819 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)4820 default_service_handling(char **argv,
4821 			 const char *servicename,
4822 			 const char *displayname,
4823 			 const char *file_path,
4824 			 const char *extra_opt,
4825 			 const char *account_name)
4826 {
4827   char path_and_service[FN_REFLEN+FN_REFLEN+32], *pos, *end;
4828   const char *opt_delim;
4829   end= path_and_service + sizeof(path_and_service)-3;
4830 
4831   /* We have to quote filename if it contains spaces */
4832   pos= add_quoted_string(path_and_service, file_path, end);
4833   if (extra_opt && *extra_opt)
4834   {
4835     /*
4836      Add option after file_path. There will be zero or one extra option.  It's
4837      assumed to be --defaults-file=file but isn't checked.  The variable (not
4838      the option name) should be quoted if it contains a string.
4839     */
4840     *pos++= ' ';
4841     if (opt_delim= strchr(extra_opt, '='))
4842     {
4843       size_t length= ++opt_delim - extra_opt;
4844       pos= strnmov(pos, extra_opt, length);
4845     }
4846     else
4847       opt_delim= extra_opt;
4848 
4849     pos= add_quoted_string(pos, opt_delim, end);
4850   }
4851   /* We must have servicename last */
4852   *pos++= ' ';
4853   (void) add_quoted_string(pos, servicename, end);
4854 
4855   if (Service.got_service_option(argv, "install"))
4856   {
4857     Service.Install(1, servicename, displayname, path_and_service,
4858                     account_name);
4859     return 0;
4860   }
4861   if (Service.got_service_option(argv, "install-manual"))
4862   {
4863     Service.Install(0, servicename, displayname, path_and_service,
4864                     account_name);
4865     return 0;
4866   }
4867   if (Service.got_service_option(argv, "remove"))
4868   {
4869     Service.Remove(servicename);
4870     return 0;
4871   }
4872   return 1;
4873 }
4874 
4875 
mysqld_main(int argc,char ** argv)4876 int mysqld_main(int argc, char **argv)
4877 {
4878   /*
4879     When several instances are running on the same machine, we
4880     need to have an  unique  named  hEventShudown  through the
4881     application PID e.g.: MySQLShutdown1890; MySQLShutdown2342
4882   */
4883   int10_to_str((int) GetCurrentProcessId(),strmov(shutdown_event_name,
4884                                                   "MySQLShutdown"), 10);
4885 
4886   /* Must be initialized early for comparison of service name */
4887   system_charset_info= &my_charset_utf8_general_ci;
4888 
4889   if (my_init())
4890   {
4891     fprintf(stderr, "my_init() failed.");
4892     return 1;
4893   }
4894 
4895   if (Service.GetOS())	/* true NT family */
4896   {
4897     char file_path[FN_REFLEN];
4898     my_path(file_path, argv[0], "");		      /* Find name in path */
4899     fn_format(file_path,argv[0],file_path,"",
4900 	      MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_RESOLVE_SYMLINKS);
4901 
4902     if (argc == 2)
4903     {
4904       if (!default_service_handling(argv, MYSQL_SERVICENAME, MYSQL_SERVICENAME,
4905 				   file_path, "", NULL))
4906 	return 0;
4907       if (Service.IsService(argv[1]))        /* Start an optional service */
4908       {
4909 	/*
4910 	  Only add the service name to the groups read from the config file
4911 	  if it's not "MySQL". (The default service name should be 'mysqld'
4912 	  but we started a bad tradition by calling it MySQL from the start
4913 	  and we are now stuck with it.
4914 	*/
4915 	if (my_strcasecmp(system_charset_info, argv[1],"mysql"))
4916 	  load_default_groups[load_default_groups_sz-2]= argv[1];
4917         start_mode= 1;
4918         Service.Init(argv[1], mysql_service);
4919         return 0;
4920       }
4921     }
4922     else if (argc == 3) /* install or remove any optional service */
4923     {
4924       if (!default_service_handling(argv, argv[2], argv[2], file_path, "",
4925                                     NULL))
4926 	return 0;
4927       if (Service.IsService(argv[2]))
4928       {
4929 	/*
4930 	  mysqld was started as
4931 	  mysqld --defaults-file=my_path\my.ini service-name
4932 	*/
4933 	use_opt_args=1;
4934 	opt_argc= 2;				// Skip service-name
4935 	opt_argv=argv;
4936 	start_mode= 1;
4937 	if (my_strcasecmp(system_charset_info, argv[2],"mysql"))
4938 	  load_default_groups[load_default_groups_sz-2]= argv[2];
4939 	Service.Init(argv[2], mysql_service);
4940 	return 0;
4941       }
4942     }
4943     else if (argc == 4 || argc == 5)
4944     {
4945       /*
4946         This may seem strange, because we handle --local-service while
4947         preserving 4.1's behavior of allowing any one other argument that is
4948         passed to the service on startup. (The assumption is that this is
4949         --defaults-file=file, but that was not enforced in 4.1, so we don't
4950         enforce it here.)
4951       */
4952       const char *extra_opt= NullS;
4953       const char *account_name = NullS;
4954       int index;
4955       for (index = 3; index < argc; index++)
4956       {
4957         if (!strcmp(argv[index], "--local-service"))
4958           account_name= "NT AUTHORITY\\LocalService";
4959         else
4960           extra_opt= argv[index];
4961       }
4962 
4963       if (argc == 4 || account_name)
4964         if (!default_service_handling(argv, argv[2], argv[2], file_path,
4965                                       extra_opt, account_name))
4966           return 0;
4967     }
4968     else if (argc == 1 && Service.IsService(MYSQL_SERVICENAME))
4969     {
4970       /* start the default service */
4971       start_mode= 1;
4972       Service.Init(MYSQL_SERVICENAME, mysql_service);
4973       return 0;
4974     }
4975   }
4976   /* Start as standalone server */
4977   Service.my_argc=argc;
4978   Service.my_argv=argv;
4979   mysql_service(NULL);
4980   return 0;
4981 }
4982 #endif
4983 
4984 
4985 /**
4986   Execute all commands from a file. Used by the mysql_install_db script to
4987   create MySQL privilege tables without having to start a full MySQL server.
4988 */
4989 
bootstrap(MYSQL_FILE * file)4990 static void bootstrap(MYSQL_FILE *file)
4991 {
4992   DBUG_ENTER("bootstrap");
4993 
4994   THD *thd= new THD;
4995   thd->bootstrap=1;
4996   my_net_init(&thd->net,(st_vio*) 0);
4997   thd->max_client_packet_length= thd->net.max_packet;
4998   thd->security_ctx->master_access= ~(ulong)0;
4999   thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
5000   thread_count++;
5001   in_bootstrap= TRUE;
5002 
5003   bootstrap_file=file;
5004 #ifndef EMBEDDED_LIBRARY			// TODO:  Enable this
5005   int error;
5006   if ((error= mysql_thread_create(key_thread_bootstrap,
5007                                   &thd->real_id, &connection_attrib,
5008                                   handle_bootstrap,
5009                                   (void*) thd)))
5010   {
5011     sql_print_warning("Can't create thread to handle bootstrap (errno= %d)",
5012                       error);
5013     bootstrap_error=-1;
5014     DBUG_VOID_RETURN;
5015   }
5016   /* Wait for thread to die */
5017   mysql_mutex_lock(&LOCK_thread_count);
5018   while (in_bootstrap)
5019   {
5020     mysql_cond_wait(&COND_thread_count, &LOCK_thread_count);
5021     DBUG_PRINT("quit",("One thread died (count=%u)",thread_count));
5022   }
5023   mysql_mutex_unlock(&LOCK_thread_count);
5024 #else
5025   thd->mysql= 0;
5026   do_handle_bootstrap(thd);
5027 #endif
5028 
5029   DBUG_VOID_RETURN;
5030 }
5031 
5032 
read_init_file(char * file_name)5033 static bool read_init_file(char *file_name)
5034 {
5035   MYSQL_FILE *file;
5036   DBUG_ENTER("read_init_file");
5037   DBUG_PRINT("enter",("name: %s",file_name));
5038   if (!(file= mysql_file_fopen(key_file_init, file_name,
5039                                O_RDONLY, MYF(MY_WME))))
5040     DBUG_RETURN(TRUE);
5041   bootstrap(file);
5042   mysql_file_fclose(file, MYF(MY_WME));
5043   DBUG_RETURN(FALSE);
5044 }
5045 
5046 
5047 /**
5048   Increment number of created threads
5049 */
inc_thread_created(void)5050 void inc_thread_created(void)
5051 {
5052   mysql_mutex_lock(&LOCK_thread_created);
5053   thread_created++;
5054   mysql_mutex_unlock(&LOCK_thread_created);
5055 }
5056 
5057 #ifndef EMBEDDED_LIBRARY
5058 
5059 /*
5060    Simple scheduler that use the main thread to handle the request
5061 
5062    NOTES
5063      This is only used for debugging, when starting mysqld with
5064      --thread-handling=no-threads or --one-thread
5065 
5066      When we enter this function, LOCK_thread_count is hold!
5067 */
5068 
handle_connection_in_main_thread(THD * thd)5069 void handle_connection_in_main_thread(THD *thd)
5070 {
5071   mysql_mutex_assert_owner(&LOCK_thread_count);
5072   thread_cache_size=0;			// Safety
5073   threads.append(thd);
5074   mysql_mutex_unlock(&LOCK_thread_count);
5075   thd->start_utime= my_micro_time();
5076   do_handle_one_connection(thd);
5077 }
5078 
5079 
5080 /*
5081   Scheduler that uses one thread per connection
5082 */
5083 
create_thread_to_handle_connection(THD * thd)5084 void create_thread_to_handle_connection(THD *thd)
5085 {
5086   if (cached_thread_count > wake_thread)
5087   {
5088     /* Get thread from cache */
5089     thread_cache.push_back(thd);
5090     wake_thread++;
5091     mysql_cond_signal(&COND_thread_cache);
5092   }
5093   else
5094   {
5095     char error_message_buff[MYSQL_ERRMSG_SIZE];
5096     /* Create new thread to handle connection */
5097     int error;
5098     thread_created++;
5099     threads.append(thd);
5100     DBUG_PRINT("info",(("creating thread %lu"), thd->thread_id));
5101     thd->prior_thr_create_utime= thd->start_utime= my_micro_time();
5102     if ((error= mysql_thread_create(key_thread_one_connection,
5103                                     &thd->real_id, &connection_attrib,
5104                                     handle_one_connection,
5105                                     (void*) thd)))
5106     {
5107       /* purecov: begin inspected */
5108       DBUG_PRINT("error",
5109                  ("Can't create thread to handle request (error %d)",
5110                   error));
5111 
5112       thread_count--;
5113       thd->killed= THD::KILL_CONNECTION;			// Safety
5114       mysql_mutex_unlock(&LOCK_thread_count);
5115 
5116       mysql_mutex_lock(&LOCK_connection_count);
5117       --connection_count;
5118       mysql_mutex_unlock(&LOCK_connection_count);
5119 
5120       statistic_increment(aborted_connects,&LOCK_status);
5121       /* Can't use my_error() since store_globals has not been called. */
5122       my_snprintf(error_message_buff, sizeof(error_message_buff),
5123                   ER_THD(thd, ER_CANT_CREATE_THREAD), error);
5124       net_send_error(thd, ER_CANT_CREATE_THREAD, error_message_buff, NULL);
5125       close_connection(thd);
5126       mysql_mutex_lock(&LOCK_thd_remove);
5127       mysql_mutex_lock(&LOCK_thread_count);
5128       delete thd;
5129       mysql_mutex_unlock(&LOCK_thread_count);
5130       mysql_mutex_unlock(&LOCK_thd_remove);
5131       return;
5132       /* purecov: end */
5133     }
5134   }
5135   mysql_mutex_unlock(&LOCK_thread_count);
5136   DBUG_PRINT("info",("Thread created"));
5137 }
5138 
5139 
5140 /**
5141   Create new thread to handle incoming connection.
5142 
5143     This function will create new thread to handle the incoming
5144     connection.  If there are idle cached threads one will be used.
5145     'thd' will be pushed into 'threads'.
5146 
5147     In single-threaded mode (\#define ONE_THREAD) connection will be
5148     handled inside this function.
5149 
5150   @param[in,out] thd    Thread handle of future thread.
5151 */
5152 
create_new_thread(THD * thd)5153 static void create_new_thread(THD *thd)
5154 {
5155   DBUG_ENTER("create_new_thread");
5156 
5157   /*
5158     Don't allow too many connections. We roughly check here that we allow
5159     only (max_connections + 1) connections.
5160   */
5161 
5162   mysql_mutex_lock(&LOCK_connection_count);
5163 
5164   if (connection_count >= max_connections + 1 || abort_loop)
5165   {
5166     mysql_mutex_unlock(&LOCK_connection_count);
5167 
5168     DBUG_PRINT("error",("Too many connections"));
5169     close_connection(thd, ER_CON_COUNT_ERROR);
5170     delete thd;
5171     DBUG_VOID_RETURN;
5172   }
5173 
5174   ++connection_count;
5175 
5176   if (connection_count > max_used_connections)
5177     max_used_connections= connection_count;
5178 
5179   mysql_mutex_unlock(&LOCK_connection_count);
5180 
5181   /* Start a new thread to handle connection. */
5182 
5183   mysql_mutex_lock(&LOCK_thread_count);
5184 
5185   /*
5186     The initialization of thread_id is done in create_embedded_thd() for
5187     the embedded library.
5188     TODO: refactor this to avoid code duplication there
5189   */
5190   thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
5191 
5192   thread_count++;
5193 
5194   MYSQL_CALLBACK(thread_scheduler, add_connection, (thd));
5195 
5196   DBUG_VOID_RETURN;
5197 }
5198 #endif /* EMBEDDED_LIBRARY */
5199 
5200 
5201 #ifdef SIGNALS_DONT_BREAK_READ
kill_broken_server()5202 inline void kill_broken_server()
5203 {
5204   /* hack to get around signals ignored in syscalls for problem OS's */
5205   if (unix_sock == INVALID_SOCKET ||
5206       (!opt_disable_networking && ip_sock == INVALID_SOCKET))
5207   {
5208     select_thread_in_use = 0;
5209     /* The following call will never return */
5210     kill_server((void*) MYSQL_KILL_SIGNAL);
5211   }
5212 }
5213 #define MAYBE_BROKEN_SYSCALL kill_broken_server();
5214 #else
5215 #define MAYBE_BROKEN_SYSCALL
5216 #endif
5217 
5218 	/* Handle new connections and spawn new process to handle them */
5219 
5220 #ifndef EMBEDDED_LIBRARY
5221 
handle_connections_sockets()5222 void handle_connections_sockets()
5223 {
5224   my_socket UNINIT_VAR(sock), UNINIT_VAR(new_sock);
5225   uint error_count=0;
5226   THD *thd;
5227   struct sockaddr_storage cAddr;
5228   int ip_flags=0,socket_flags=0,flags=0,retval;
5229   st_vio *vio_tmp;
5230 #ifdef HAVE_POLL
5231   int socket_count= 0;
5232   struct pollfd fds[2]; // for ip_sock and unix_sock
5233 #else
5234   fd_set readFDs,clientFDs;
5235   uint max_used_connection= (uint) (max(ip_sock,unix_sock)+1);
5236 #endif
5237 
5238   DBUG_ENTER("handle_connections_sockets");
5239 
5240   (void) ip_flags;
5241   (void) socket_flags;
5242 
5243 #ifndef HAVE_POLL
5244   FD_ZERO(&clientFDs);
5245 #endif
5246 
5247   if (ip_sock != INVALID_SOCKET)
5248   {
5249 #ifdef HAVE_POLL
5250     fds[socket_count].fd= ip_sock;
5251     fds[socket_count].events= POLLIN;
5252     socket_count++;
5253 #else
5254     FD_SET(ip_sock,&clientFDs);
5255 #endif
5256 #ifdef HAVE_FCNTL
5257     ip_flags = fcntl(ip_sock, F_GETFL, 0);
5258 #endif
5259   }
5260 #ifdef HAVE_SYS_UN_H
5261 #ifdef HAVE_POLL
5262   fds[socket_count].fd= unix_sock;
5263   fds[socket_count].events= POLLIN;
5264   socket_count++;
5265 #else
5266   FD_SET(unix_sock,&clientFDs);
5267 #endif
5268 #ifdef HAVE_FCNTL
5269   socket_flags=fcntl(unix_sock, F_GETFL, 0);
5270 #endif
5271 #endif
5272 
5273   DBUG_PRINT("general",("Waiting for connections."));
5274   MAYBE_BROKEN_SYSCALL;
5275   while (!abort_loop)
5276   {
5277 #ifdef HAVE_POLL
5278     retval= poll(fds, socket_count, -1);
5279 #else
5280     readFDs=clientFDs;
5281 
5282     retval= select((int) max_used_connection,&readFDs,0,0,0);
5283 #endif
5284 
5285     if (retval < 0)
5286     {
5287       if (socket_errno != SOCKET_EINTR)
5288       {
5289 	if (!select_errors++ && !abort_loop)	/* purecov: inspected */
5290 	  sql_print_error("mysqld: Got error %d from select",socket_errno); /* purecov: inspected */
5291       }
5292       MAYBE_BROKEN_SYSCALL
5293       continue;
5294     }
5295 
5296     if (abort_loop)
5297     {
5298       MAYBE_BROKEN_SYSCALL;
5299       break;
5300     }
5301 
5302     /* Is this a new connection request ? */
5303 #ifdef HAVE_POLL
5304     for (int i= 0; i < socket_count; ++i)
5305     {
5306       if (fds[i].revents & POLLIN)
5307       {
5308         sock= fds[i].fd;
5309 #ifdef HAVE_FCNTL
5310         flags= fcntl(sock, F_GETFL, 0);
5311 #else
5312         flags= 0;
5313 #endif // HAVE_FCNTL
5314         break;
5315       }
5316     }
5317 #else  // HAVE_POLL
5318 #ifdef HAVE_SYS_UN_H
5319     if (FD_ISSET(unix_sock,&readFDs))
5320     {
5321       sock = unix_sock;
5322       flags= socket_flags;
5323     }
5324     else
5325 #endif // HAVE_SYS_UN_H
5326     {
5327       sock = ip_sock;
5328       flags= ip_flags;
5329     }
5330 #endif // HAVE_POLL
5331 
5332 #if !defined(NO_FCNTL_NONBLOCK)
5333     if (!(test_flags & TEST_BLOCKING))
5334     {
5335 #if defined(O_NONBLOCK)
5336       fcntl(sock, F_SETFL, flags | O_NONBLOCK);
5337 #elif defined(O_NDELAY)
5338       fcntl(sock, F_SETFL, flags | O_NDELAY);
5339 #endif
5340     }
5341 #endif /* NO_FCNTL_NONBLOCK */
5342     for (uint retry=0; retry < MAX_ACCEPT_RETRY; retry++)
5343     {
5344       size_socket length= sizeof(struct sockaddr_storage);
5345       new_sock= accept(sock, (struct sockaddr *)(&cAddr),
5346                        &length);
5347       if (new_sock != INVALID_SOCKET ||
5348 	  (socket_errno != SOCKET_EINTR && socket_errno != SOCKET_EAGAIN))
5349 	break;
5350       MAYBE_BROKEN_SYSCALL;
5351 #if !defined(NO_FCNTL_NONBLOCK)
5352       if (!(test_flags & TEST_BLOCKING))
5353       {
5354 	if (retry == MAX_ACCEPT_RETRY - 1)
5355 	  fcntl(sock, F_SETFL, flags);		// Try without O_NONBLOCK
5356       }
5357 #endif
5358     }
5359 #if !defined(NO_FCNTL_NONBLOCK)
5360     if (!(test_flags & TEST_BLOCKING))
5361       fcntl(sock, F_SETFL, flags);
5362 #endif
5363     if (new_sock == INVALID_SOCKET)
5364     {
5365       if ((error_count++ & 255) == 0)		// This can happen often
5366 	sql_perror("Error in accept");
5367       MAYBE_BROKEN_SYSCALL;
5368       if (socket_errno == SOCKET_ENFILE || socket_errno == SOCKET_EMFILE)
5369 	sleep(1);				// Give other threads some time
5370       continue;
5371     }
5372 
5373 #ifdef HAVE_LIBWRAP
5374     {
5375       if (sock == ip_sock)
5376       {
5377 	struct request_info req;
5378 	signal(SIGCHLD, SIG_DFL);
5379 	request_init(&req, RQ_DAEMON, libwrapName, RQ_FILE, new_sock, NULL);
5380 	my_fromhost(&req);
5381 	if (!my_hosts_access(&req))
5382 	{
5383 	  /*
5384 	    This may be stupid but refuse() includes an exit(0)
5385 	    which we surely don't want...
5386 	    clean_exit() - same stupid thing ...
5387 	  */
5388 	  syslog(deny_severity, "refused connect from %s",
5389 		 my_eval_client(&req));
5390 
5391 	  /*
5392 	    C++ sucks (the gibberish in front just translates the supplied
5393 	    sink function pointer in the req structure from a void (*sink)();
5394 	    to a void(*sink)(int) if you omit the cast, the C++ compiler
5395 	    will cry...
5396 	  */
5397 	  if (req.sink)
5398 	    ((void (*)(int))req.sink)(req.fd);
5399 
5400 	  (void) mysql_socket_shutdown(new_sock, SHUT_RDWR);
5401 	  (void) closesocket(new_sock);
5402 	  continue;
5403 	}
5404       }
5405     }
5406 #endif /* HAVE_LIBWRAP */
5407 
5408     {
5409       size_socket dummyLen;
5410       struct sockaddr_storage dummy;
5411       dummyLen = sizeof(dummy);
5412       if (  getsockname(new_sock,(struct sockaddr *)&dummy,
5413                   (SOCKET_SIZE_TYPE *)&dummyLen) < 0  )
5414       {
5415 	sql_perror("Error on new connection socket");
5416 	(void) mysql_socket_shutdown(new_sock, SHUT_RDWR);
5417 	(void) closesocket(new_sock);
5418 	continue;
5419       }
5420     }
5421 
5422     /*
5423     ** Don't allow too many connections
5424     */
5425 
5426     if (!(thd= new THD))
5427     {
5428       (void) mysql_socket_shutdown(new_sock, SHUT_RDWR);
5429       (void) closesocket(new_sock);
5430       continue;
5431     }
5432     if (!(vio_tmp=vio_new(new_sock,
5433 			  sock == unix_sock ? VIO_TYPE_SOCKET :
5434 			  VIO_TYPE_TCPIP,
5435 			  sock == unix_sock ? VIO_LOCALHOST: 0)) ||
5436 	my_net_init(&thd->net,vio_tmp))
5437     {
5438       /*
5439         Only delete the temporary vio if we didn't already attach it to the
5440         NET object. The destructor in THD will delete any initialized net
5441         structure.
5442       */
5443       if (vio_tmp && thd->net.vio != vio_tmp)
5444         vio_delete(vio_tmp);
5445       else
5446       {
5447 	(void) mysql_socket_shutdown(new_sock, SHUT_RDWR);
5448 	(void) closesocket(new_sock);
5449       }
5450       delete thd;
5451       continue;
5452     }
5453     if (sock == unix_sock)
5454       thd->security_ctx->set_host((char*) my_localhost);
5455 
5456     create_new_thread(thd);
5457   }
5458   DBUG_VOID_RETURN;
5459 }
5460 
5461 
5462 #ifdef _WIN32
handle_connections_sockets_thread(void * arg)5463 pthread_handler_t handle_connections_sockets_thread(void *arg)
5464 {
5465   my_thread_init();
5466   handle_connections_sockets();
5467   decrement_handler_count();
5468   return 0;
5469 }
5470 
handle_connections_namedpipes(void * arg)5471 pthread_handler_t handle_connections_namedpipes(void *arg)
5472 {
5473   HANDLE hConnectedPipe;
5474   OVERLAPPED connectOverlapped= {0};
5475   THD *thd;
5476   my_thread_init();
5477   DBUG_ENTER("handle_connections_namedpipes");
5478   connectOverlapped.hEvent= CreateEvent(NULL, TRUE, FALSE, NULL);
5479   if (!connectOverlapped.hEvent)
5480   {
5481     sql_print_error("Can't create event, last error=%u", GetLastError());
5482     unireg_abort(1);
5483   }
5484   DBUG_PRINT("general",("Waiting for named pipe connections."));
5485   while (!abort_loop)
5486   {
5487     /* wait for named pipe connection */
5488     BOOL fConnected= ConnectNamedPipe(hPipe, &connectOverlapped);
5489     if (!fConnected && (GetLastError() == ERROR_IO_PENDING))
5490     {
5491         /*
5492           ERROR_IO_PENDING says async IO has started but not yet finished.
5493           GetOverlappedResult will wait for completion.
5494         */
5495         DWORD bytes;
5496         fConnected= GetOverlappedResult(hPipe, &connectOverlapped,&bytes, TRUE);
5497     }
5498     if (abort_loop)
5499       break;
5500     if (!fConnected)
5501       fConnected = GetLastError() == ERROR_PIPE_CONNECTED;
5502     if (!fConnected)
5503     {
5504       CloseHandle(hPipe);
5505       if ((hPipe= CreateNamedPipe(pipe_name,
5506                                   PIPE_ACCESS_DUPLEX |
5507                                   FILE_FLAG_OVERLAPPED,
5508                                   PIPE_TYPE_BYTE |
5509                                   PIPE_READMODE_BYTE |
5510                                   PIPE_WAIT,
5511                                   PIPE_UNLIMITED_INSTANCES,
5512                                   (int) global_system_variables.
5513                                   net_buffer_length,
5514                                   (int) global_system_variables.
5515                                   net_buffer_length,
5516                                   NMPWAIT_USE_DEFAULT_WAIT,
5517                                   &saPipeSecurity)) ==
5518 	  INVALID_HANDLE_VALUE)
5519       {
5520 	sql_perror("Can't create new named pipe!");
5521 	break;					// Abort
5522       }
5523     }
5524     hConnectedPipe = hPipe;
5525     /* create new pipe for new connection */
5526     if ((hPipe = CreateNamedPipe(pipe_name,
5527                  PIPE_ACCESS_DUPLEX |
5528                  FILE_FLAG_OVERLAPPED,
5529 				 PIPE_TYPE_BYTE |
5530 				 PIPE_READMODE_BYTE |
5531 				 PIPE_WAIT,
5532 				 PIPE_UNLIMITED_INSTANCES,
5533 				 (int) global_system_variables.net_buffer_length,
5534 				 (int) global_system_variables.net_buffer_length,
5535 				 NMPWAIT_USE_DEFAULT_WAIT,
5536 				 &saPipeSecurity)) ==
5537 	INVALID_HANDLE_VALUE)
5538     {
5539       sql_perror("Can't create new named pipe!");
5540       hPipe=hConnectedPipe;
5541       continue;					// We have to try again
5542     }
5543 
5544     if (!(thd = new THD))
5545     {
5546       DisconnectNamedPipe(hConnectedPipe);
5547       CloseHandle(hConnectedPipe);
5548       continue;
5549     }
5550     if (!(thd->net.vio= vio_new_win32pipe(hConnectedPipe)) ||
5551 	my_net_init(&thd->net, thd->net.vio))
5552     {
5553       close_connection(thd, ER_OUT_OF_RESOURCES);
5554       delete thd;
5555       continue;
5556     }
5557     /* Host is unknown */
5558     thd->security_ctx->set_host(my_strdup(my_localhost, MYF(0)));
5559     create_new_thread(thd);
5560   }
5561   CloseHandle(connectOverlapped.hEvent);
5562   DBUG_LEAVE;
5563   decrement_handler_count();
5564   return 0;
5565 }
5566 #endif /* _WIN32 */
5567 
5568 
5569 #ifdef HAVE_SMEM
5570 
5571 /**
5572   Thread of shared memory's service.
5573 
5574   @param arg                              Arguments of thread
5575 */
handle_connections_shared_memory(void * arg)5576 pthread_handler_t handle_connections_shared_memory(void *arg)
5577 {
5578   /* file-mapping object, use for create shared memory */
5579   HANDLE handle_connect_file_map= 0;
5580   char  *handle_connect_map= 0;                 // pointer on shared memory
5581   HANDLE event_connect_answer= 0;
5582   ulong smem_buffer_length= shared_memory_buffer_length + 4;
5583   ulong connect_number= 1;
5584   char *tmp= NULL;
5585   char *suffix_pos;
5586   char connect_number_char[22], *p;
5587   const char *errmsg= 0;
5588   SECURITY_ATTRIBUTES *sa_event= 0, *sa_mapping= 0;
5589   my_thread_init();
5590   DBUG_ENTER("handle_connections_shared_memorys");
5591   DBUG_PRINT("general",("Waiting for allocated shared memory."));
5592 
5593   /*
5594      get enough space base-name + '_' + longest suffix we might ever send
5595    */
5596   if (!(tmp= (char *)my_malloc(strlen(shared_memory_base_name) + 32L, MYF(MY_FAE))))
5597     goto error;
5598 
5599   if (my_security_attr_create(&sa_event, &errmsg,
5600                               GENERIC_ALL, SYNCHRONIZE | EVENT_MODIFY_STATE))
5601     goto error;
5602 
5603   if (my_security_attr_create(&sa_mapping, &errmsg,
5604                              GENERIC_ALL, FILE_MAP_READ | FILE_MAP_WRITE))
5605     goto error;
5606 
5607   /*
5608     The name of event and file-mapping events create agree next rule:
5609       shared_memory_base_name+unique_part
5610     Where:
5611       shared_memory_base_name is unique value for each server
5612       unique_part is unique value for each object (events and file-mapping)
5613   */
5614   suffix_pos= strxmov(tmp,shared_memory_base_name,"_",NullS);
5615   strmov(suffix_pos, "CONNECT_REQUEST");
5616   if ((smem_event_connect_request= CreateEvent(sa_event,
5617                                                FALSE, FALSE, tmp)) == 0)
5618   {
5619     errmsg= "Could not create request event";
5620     goto error;
5621   }
5622   strmov(suffix_pos, "CONNECT_ANSWER");
5623   if ((event_connect_answer= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
5624   {
5625     errmsg="Could not create answer event";
5626     goto error;
5627   }
5628   strmov(suffix_pos, "CONNECT_DATA");
5629   if ((handle_connect_file_map=
5630        CreateFileMapping(INVALID_HANDLE_VALUE, sa_mapping,
5631                          PAGE_READWRITE, 0, sizeof(connect_number), tmp)) == 0)
5632   {
5633     errmsg= "Could not create file mapping";
5634     goto error;
5635   }
5636   if ((handle_connect_map= (char *)MapViewOfFile(handle_connect_file_map,
5637 						  FILE_MAP_WRITE,0,0,
5638 						  sizeof(DWORD))) == 0)
5639   {
5640     errmsg= "Could not create shared memory service";
5641     goto error;
5642   }
5643 
5644   while (!abort_loop)
5645   {
5646     /* Wait a request from client */
5647     WaitForSingleObject(smem_event_connect_request,INFINITE);
5648 
5649     /*
5650        it can be after shutdown command
5651     */
5652     if (abort_loop)
5653       goto error;
5654 
5655     HANDLE handle_client_file_map= 0;
5656     char  *handle_client_map= 0;
5657     HANDLE event_client_wrote= 0;
5658     HANDLE event_client_read= 0;    // for transfer data server <-> client
5659     HANDLE event_server_wrote= 0;
5660     HANDLE event_server_read= 0;
5661     HANDLE event_conn_closed= 0;
5662     THD *thd= 0;
5663 
5664     p= int10_to_str(connect_number, connect_number_char, 10);
5665     /*
5666       The name of event and file-mapping events create agree next rule:
5667         shared_memory_base_name+unique_part+number_of_connection
5668         Where:
5669 	  shared_memory_base_name is uniquel value for each server
5670 	  unique_part is unique value for each object (events and file-mapping)
5671 	  number_of_connection is connection-number between server and client
5672     */
5673     suffix_pos= strxmov(tmp,shared_memory_base_name,"_",connect_number_char,
5674 			 "_",NullS);
5675     strmov(suffix_pos, "DATA");
5676     if ((handle_client_file_map=
5677          CreateFileMapping(INVALID_HANDLE_VALUE, sa_mapping,
5678                            PAGE_READWRITE, 0, smem_buffer_length, tmp)) == 0)
5679     {
5680       errmsg= "Could not create file mapping";
5681       goto errorconn;
5682     }
5683     if ((handle_client_map= (char*)MapViewOfFile(handle_client_file_map,
5684 						  FILE_MAP_WRITE,0,0,
5685 						  smem_buffer_length)) == 0)
5686     {
5687       errmsg= "Could not create memory map";
5688       goto errorconn;
5689     }
5690     strmov(suffix_pos, "CLIENT_WROTE");
5691     if ((event_client_wrote= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
5692     {
5693       errmsg= "Could not create client write event";
5694       goto errorconn;
5695     }
5696     strmov(suffix_pos, "CLIENT_READ");
5697     if ((event_client_read= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
5698     {
5699       errmsg= "Could not create client read event";
5700       goto errorconn;
5701     }
5702     strmov(suffix_pos, "SERVER_READ");
5703     if ((event_server_read= CreateEvent(sa_event, FALSE, FALSE, tmp)) == 0)
5704     {
5705       errmsg= "Could not create server read event";
5706       goto errorconn;
5707     }
5708     strmov(suffix_pos, "SERVER_WROTE");
5709     if ((event_server_wrote= CreateEvent(sa_event,
5710                                          FALSE, FALSE, tmp)) == 0)
5711     {
5712       errmsg= "Could not create server write event";
5713       goto errorconn;
5714     }
5715     strmov(suffix_pos, "CONNECTION_CLOSED");
5716     if ((event_conn_closed= CreateEvent(sa_event,
5717                                         TRUE, FALSE, tmp)) == 0)
5718     {
5719       errmsg= "Could not create closed connection event";
5720       goto errorconn;
5721     }
5722     if (abort_loop)
5723       goto errorconn;
5724     if (!(thd= new THD))
5725       goto errorconn;
5726     /* Send number of connection to client */
5727     int4store(handle_connect_map, connect_number);
5728     if (!SetEvent(event_connect_answer))
5729     {
5730       errmsg= "Could not send answer event";
5731       goto errorconn;
5732     }
5733     /* Set event that client should receive data */
5734     if (!SetEvent(event_client_read))
5735     {
5736       errmsg= "Could not set client to read mode";
5737       goto errorconn;
5738     }
5739     if (!(thd->net.vio= vio_new_win32shared_memory(handle_client_file_map,
5740                                                    handle_client_map,
5741                                                    event_client_wrote,
5742                                                    event_client_read,
5743                                                    event_server_wrote,
5744                                                    event_server_read,
5745                                                    event_conn_closed)) ||
5746                         my_net_init(&thd->net, thd->net.vio))
5747     {
5748       close_connection(thd, ER_OUT_OF_RESOURCES);
5749       errmsg= 0;
5750       goto errorconn;
5751     }
5752     thd->security_ctx->set_host(my_strdup(my_localhost, MYF(0))); /* Host is unknown */
5753     create_new_thread(thd);
5754     connect_number++;
5755     continue;
5756 
5757 errorconn:
5758     /* Could not form connection;  Free used handlers/memort and retry */
5759     if (errmsg)
5760     {
5761       char buff[180];
5762       strxmov(buff, "Can't create shared memory connection: ", errmsg, ".",
5763 	      NullS);
5764       sql_perror(buff);
5765     }
5766     if (handle_client_file_map)
5767       CloseHandle(handle_client_file_map);
5768     if (handle_client_map)
5769       UnmapViewOfFile(handle_client_map);
5770     if (event_server_wrote)
5771       CloseHandle(event_server_wrote);
5772     if (event_server_read)
5773       CloseHandle(event_server_read);
5774     if (event_client_wrote)
5775       CloseHandle(event_client_wrote);
5776     if (event_client_read)
5777       CloseHandle(event_client_read);
5778     if (event_conn_closed)
5779       CloseHandle(event_conn_closed);
5780     delete thd;
5781   }
5782 
5783   /* End shared memory handling */
5784 error:
5785   if (tmp)
5786     my_free(tmp);
5787 
5788   if (errmsg)
5789   {
5790     char buff[180];
5791     strxmov(buff, "Can't create shared memory service: ", errmsg, ".", NullS);
5792     sql_perror(buff);
5793   }
5794   my_security_attr_free(sa_event);
5795   my_security_attr_free(sa_mapping);
5796   if (handle_connect_map)	UnmapViewOfFile(handle_connect_map);
5797   if (handle_connect_file_map)	CloseHandle(handle_connect_file_map);
5798   if (event_connect_answer)	CloseHandle(event_connect_answer);
5799   if (smem_event_connect_request) CloseHandle(smem_event_connect_request);
5800   DBUG_LEAVE;
5801   decrement_handler_count();
5802   return 0;
5803 }
5804 #endif /* HAVE_SMEM */
5805 #endif /* EMBEDDED_LIBRARY */
5806 
5807 
5808 /****************************************************************************
5809   Handle start options
5810 ******************************************************************************/
5811 
5812 DYNAMIC_ARRAY all_options;
5813 
5814 /**
5815   System variables are automatically command-line options (few
5816   exceptions are documented in sys_var.h), so don't need
5817   to be listed here.
5818 */
5819 
5820 struct my_option my_long_options[]=
5821 {
5822   {"help", '?', "Display this help and exit.",
5823    &opt_help, &opt_help, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
5824    0, 0},
5825 #ifdef HAVE_REPLICATION
5826   {"abort-slave-event-count", 0,
5827    "Option used by mysql-test for debugging and testing of replication.",
5828    &abort_slave_event_count,  &abort_slave_event_count,
5829    0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
5830 #endif /* HAVE_REPLICATION */
5831   {"allow-suspicious-udfs", 0,
5832    "Allows use of UDFs consisting of only one symbol xxx() "
5833    "without corresponding xxx_init() or xxx_deinit(). That also means "
5834    "that one can load any function from any library, for example exit() "
5835    "from libc.so",
5836    &opt_allow_suspicious_udfs, &opt_allow_suspicious_udfs,
5837    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
5838   {"ansi", 'a', "Use ANSI SQL syntax instead of MySQL syntax. This mode "
5839    "will also set transaction isolation level 'serializable'.", 0, 0, 0,
5840    GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
5841   /*
5842     Because Sys_var_bit does not support command-line options, we need to
5843     explicitely add one for --autocommit
5844   */
5845   {"autocommit", 0, "Set default value for autocommit (0 or 1)",
5846    &opt_autocommit, &opt_autocommit, 0,
5847    GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, NULL},
5848   {"bind-address", OPT_BIND_ADDRESS, "IP address to bind to.",
5849    &my_bind_addr_str, &my_bind_addr_str, 0, GET_STR,
5850    REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
5851   {"binlog-do-db", OPT_BINLOG_DO_DB,
5852    "Tells the master it should log updates for the specified database, "
5853    "and exclude all others not explicitly mentioned.",
5854    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
5855   {"binlog-ignore-db", OPT_BINLOG_IGNORE_DB,
5856    "Tells the master that updates to the given database should not be logged to the binary log.",
5857    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
5858   {"binlog-row-event-max-size", 0,
5859    "The maximum size of a row-based binary log event in bytes. Rows will be "
5860    "grouped into events smaller than this size if possible. "
5861    "The value has to be a multiple of 256.",
5862    &opt_binlog_rows_event_max_size, &opt_binlog_rows_event_max_size,
5863    0, GET_ULONG, REQUIRED_ARG,
5864    /* def_value */ 1024, /* min_value */  256, /* max_value */ ULONG_MAX,
5865    /* sub_size */     0, /* block_size */ 256,
5866    /* app_type */ 0
5867   },
5868 #ifndef DISABLE_GRANT_OPTIONS
5869   {"bootstrap", OPT_BOOTSTRAP, "Used by mysql installation scripts.", 0, 0, 0,
5870    GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
5871 #endif
5872   {"character-set-client-handshake", 0,
5873    "Don't ignore client side character set value sent during handshake.",
5874    &opt_character_set_client_handshake,
5875    &opt_character_set_client_handshake,
5876     0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
5877   {"character-set-filesystem", 0,
5878    "Set the filesystem character set.",
5879    &character_set_filesystem_name,
5880    &character_set_filesystem_name,
5881    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
5882   {"character-set-server", 'C', "Set the default character set.",
5883    &default_character_set_name, &default_character_set_name,
5884    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
5885   {"chroot", 'r', "Chroot mysqld daemon during startup.",
5886    &mysqld_chroot, &mysqld_chroot, 0, GET_STR, REQUIRED_ARG,
5887    0, 0, 0, 0, 0, 0},
5888   {"collation-server", 0, "Set the default collation.",
5889    &default_collation_name, &default_collation_name,
5890    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
5891   {"console", OPT_CONSOLE, "Write error output on screen; don't remove the console window on windows.",
5892    &opt_console, &opt_console, 0, GET_BOOL, NO_ARG, 0, 0, 0,
5893    0, 0, 0},
5894   {"core-file", OPT_WANT_CORE, "Write core on errors.", 0, 0, 0, GET_NO_ARG,
5895    NO_ARG, 0, 0, 0, 0, 0, 0},
5896   /* default-storage-engine should have "MyISAM" as def_value. Instead
5897      of initializing it here it is done in init_common_variables() due
5898      to a compiler bug in Sun Studio compiler. */
5899   {"default-storage-engine", 0, "The default storage engine for new tables",
5900    &default_storage_engine, 0, 0, GET_STR, REQUIRED_ARG,
5901    0, 0, 0, 0, 0, 0 },
5902   {"default-time-zone", 0, "Set the default time zone.",
5903    &default_tz_name, &default_tz_name,
5904    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
5905 #ifdef HAVE_OPENSSL
5906   {"des-key-file", 0,
5907    "Load keys for des_encrypt() and des_encrypt from given file.",
5908    &des_key_file, &des_key_file, 0, GET_STR, REQUIRED_ARG,
5909    0, 0, 0, 0, 0, 0},
5910 #endif /* HAVE_OPENSSL */
5911 #ifdef HAVE_REPLICATION
5912   {"disconnect-slave-event-count", 0,
5913    "Option used by mysql-test for debugging and testing of replication.",
5914    &disconnect_slave_event_count, &disconnect_slave_event_count,
5915    0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
5916 #endif /* HAVE_REPLICATION */
5917   {"exit-info", 'T', "Used for debugging. Use at your own risk.", 0, 0, 0,
5918    GET_LONG, OPT_ARG, 0, 0, 0, 0, 0, 0},
5919 
5920   {"external-locking", 0, "Use system (external) locking (disabled by "
5921    "default).  With this option enabled you can run myisamchk to test "
5922    "(not repair) tables while the MySQL server is running. Disable with "
5923    "--skip-external-locking.", &opt_external_locking, &opt_external_locking,
5924    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
5925   /* We must always support the next option to make scripts like mysqltest
5926      easier to do */
5927   {"gdb", 0,
5928    "Set up signals usable for debugging.",
5929    &opt_debugging, &opt_debugging,
5930    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
5931 #ifdef HAVE_LARGE_PAGE_OPTION
5932   {"super-large-pages", 0, "Enable support for super large pages.",
5933    &opt_super_large_pages, &opt_super_large_pages, 0,
5934    GET_BOOL, OPT_ARG, 0, 0, 1, 0, 1, 0},
5935 #endif
5936   {"language", 'L',
5937    "Client error messages in given language. May be given as a full path. "
5938    "Deprecated. Use --lc-messages-dir instead.",
5939    &lc_messages_dir_ptr, &lc_messages_dir_ptr, 0,
5940    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
5941   {"lc-messages", 0,
5942    "Set the language used for the error messages.",
5943    &lc_messages, &lc_messages, 0, GET_STR, REQUIRED_ARG,
5944    0, 0, 0, 0, 0, 0 },
5945   {"lc-time-names", 0,
5946    "Set the language used for the month names and the days of the week.",
5947    &lc_time_names_name, &lc_time_names_name,
5948    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
5949   {"log", 'l', "Log connections and queries to file (deprecated option, use "
5950    "--general-log/--general-log-file instead).", &opt_logname, &opt_logname,
5951    0, GET_STR_ALLOC, OPT_ARG, 0, 0, 0, 0, 0, 0},
5952   {"log-bin", OPT_BIN_LOG,
5953    "Log update queries in binary format. Optional (but strongly recommended "
5954    "to avoid replication problems if server's hostname changes) argument "
5955    "should be the chosen location for the binary log files.",
5956    &opt_bin_logname, &opt_bin_logname, 0, GET_STR_ALLOC,
5957    OPT_ARG, 0, 0, 0, 0, 0, 0},
5958   {"log-bin-index", 0,
5959    "File that holds the names for last binary log files.",
5960    &opt_binlog_index_name, &opt_binlog_index_name, 0, GET_STR,
5961    REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
5962   {"log-isam", OPT_ISAM_LOG, "Log all MyISAM changes to file.",
5963    &myisam_log_filename, &myisam_log_filename, 0, GET_STR,
5964    OPT_ARG, 0, 0, 0, 0, 0, 0},
5965   {"log-short-format", 0,
5966    "Don't log extra information to update and slow-query logs.",
5967    &opt_short_log_format, &opt_short_log_format,
5968    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
5969   {"log-slow-admin-statements", 0,
5970    "Log slow OPTIMIZE, ANALYZE, ALTER and other administrative statements to "
5971    "the slow log if it is open.", &opt_log_slow_admin_statements,
5972    &opt_log_slow_admin_statements, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
5973  {"log-slow-slave-statements", 0,
5974   "Log slow statements executed by slave thread to the slow log if it is open.",
5975   &opt_log_slow_slave_statements, &opt_log_slow_slave_statements,
5976   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
5977   {"log-slow-queries", OPT_SLOW_QUERY_LOG,
5978    "Log slow queries to a table or log file. Defaults logging to table "
5979    "mysql.slow_log or hostname-slow.log if --log-output=file is used. "
5980    "Must be enabled to activate other slow log options. "
5981    "Deprecated option, use --slow-query-log/--slow-query-log-file instead.",
5982    &opt_slow_logname, &opt_slow_logname, 0, GET_STR_ALLOC, OPT_ARG,
5983    0, 0, 0, 0, 0, 0},
5984   {"log-tc", 0,
5985    "Path to transaction coordinator log (used for transactions that affect "
5986    "more than one storage engine, when binary log is disabled).",
5987    &opt_tc_log_file, &opt_tc_log_file, 0, GET_STR,
5988    REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
5989 #ifdef HAVE_MMAP
5990   {"log-tc-size", 0, "Size of transaction coordinator log.",
5991    &opt_tc_log_size, &opt_tc_log_size, 0, GET_ULONG,
5992    REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, ULONG_MAX, 0,
5993    TC_LOG_PAGE_SIZE, 0},
5994 #endif
5995   {"master-info-file", 0,
5996    "The location and name of the file that remembers the master and where "
5997    "the I/O replication thread is in the master's binlogs.",
5998    &master_info_file, &master_info_file, 0, GET_STR,
5999    REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6000   {"master-retry-count", 0,
6001    "The number of tries the slave will make to connect to the master before giving up.",
6002    &master_retry_count, &master_retry_count, 0, GET_ULONG,
6003    REQUIRED_ARG, 3600*24, 0, 0, 0, 0, 0},
6004 #ifdef HAVE_REPLICATION
6005   {"init-rpl-role", 0, "Set the replication role.",
6006    &rpl_status, &rpl_status, &rpl_role_typelib,
6007    GET_ENUM, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6008   {"max-binlog-dump-events", 0,
6009    "Option used by mysql-test for debugging and testing of replication.",
6010    &max_binlog_dump_events, &max_binlog_dump_events, 0,
6011    GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6012 #endif /* HAVE_REPLICATION */
6013   {"memlock", 0, "Lock mysqld in memory.", &locked_in_memory,
6014    &locked_in_memory, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6015   {"one-thread", OPT_ONE_THREAD,
6016    "(Deprecated): Only use one thread (for debugging under Linux). Use "
6017    "thread-handling=no-threads instead.",
6018    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
6019   {"old-style-user-limits", 0,
6020    "Enable old-style user limits (before 5.0.3, user resources were counted "
6021    "per each user+host vs. per account).",
6022    &opt_old_style_user_limits, &opt_old_style_user_limits,
6023    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6024   {"port-open-timeout", 0,
6025    "Maximum time in seconds to wait for the port to become free. "
6026    "(Default: No wait).", &mysqld_port_timeout, &mysqld_port_timeout, 0,
6027    GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6028   {"replicate-do-db", OPT_REPLICATE_DO_DB,
6029    "Tells the slave thread to restrict replication to the specified database. "
6030    "To specify more than one database, use the directive multiple times, "
6031    "once for each database. Note that this will only work if you do not use "
6032    "cross-database queries such as UPDATE some_db.some_table SET foo='bar' "
6033    "while having selected a different or no database. If you need cross "
6034    "database updates to work, make sure you have 3.23.28 or later, and use "
6035    "replicate-wild-do-table=db_name.%.",
6036    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6037   {"replicate-do-table", OPT_REPLICATE_DO_TABLE,
6038    "Tells the slave thread to restrict replication to the specified table. "
6039    "To specify more than one table, use the directive multiple times, once "
6040    "for each table. This will work for cross-database updates, in contrast "
6041    "to replicate-do-db.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6042   {"replicate-ignore-db", OPT_REPLICATE_IGNORE_DB,
6043    "Tells the slave thread to not replicate to the specified database. To "
6044    "specify more than one database to ignore, use the directive multiple "
6045    "times, once for each database. This option will not work if you use "
6046    "cross database updates. If you need cross database updates to work, "
6047    "make sure you have 3.23.28 or later, and use replicate-wild-ignore-"
6048    "table=db_name.%. ", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6049   {"replicate-ignore-table", OPT_REPLICATE_IGNORE_TABLE,
6050    "Tells the slave thread to not replicate to the specified table. To specify "
6051    "more than one table to ignore, use the directive multiple times, once for "
6052    "each table. This will work for cross-database updates, in contrast to "
6053    "replicate-ignore-db.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6054   {"replicate-rewrite-db", OPT_REPLICATE_REWRITE_DB,
6055    "Updates to a database with a different name than the original. Example: "
6056    "replicate-rewrite-db=master_db_name->slave_db_name.",
6057    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6058 #ifdef HAVE_REPLICATION
6059   {"replicate-same-server-id", 0,
6060    "In replication, if set to 1, do not skip events having our server id. "
6061    "Default value is 0 (to break infinite loops in circular replication). "
6062    "Can't be set to 1 if --log-slave-updates is used.",
6063    &replicate_same_server_id, &replicate_same_server_id,
6064    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6065 #endif
6066   {"replicate-wild-do-table", OPT_REPLICATE_WILD_DO_TABLE,
6067    "Tells the slave thread to restrict replication to the tables that match "
6068    "the specified wildcard pattern. To specify more than one table, use the "
6069    "directive multiple times, once for each table. This will work for cross-"
6070    "database updates. Example: replicate-wild-do-table=foo%.bar% will "
6071    "replicate only updates to tables in all databases that start with foo "
6072    "and whose table names start with bar.",
6073    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6074   {"replicate-wild-ignore-table", OPT_REPLICATE_WILD_IGNORE_TABLE,
6075    "Tells the slave thread to not replicate to the tables that match the "
6076    "given wildcard pattern. To specify more than one table to ignore, use "
6077    "the directive multiple times, once for each table. This will work for "
6078    "cross-database updates. Example: replicate-wild-ignore-table=foo%.bar% "
6079    "will not do updates to tables in databases that start with foo and whose "
6080    "table names start with bar.",
6081    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6082   {"safe-mode", OPT_SAFE, "Skip some optimize stages (for testing). Deprecated.",
6083    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
6084   {"safe-user-create", 0,
6085    "Don't allow new user creation by the user who has no write privileges to the mysql.user table.",
6086    &opt_safe_user_create, &opt_safe_user_create, 0, GET_BOOL,
6087    NO_ARG, 0, 0, 0, 0, 0, 0},
6088   {"show-slave-auth-info", 0,
6089    "Show user and password in SHOW SLAVE HOSTS on this master.",
6090    &opt_show_slave_auth_info, &opt_show_slave_auth_info, 0,
6091    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6092 #ifndef DISABLE_GRANT_OPTIONS
6093   {"skip-grant-tables", 0,
6094    "Start without grant tables. This gives all users FULL ACCESS to all tables.",
6095    &opt_noacl, &opt_noacl, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
6096    0},
6097 #endif
6098   {"skip-host-cache", OPT_SKIP_HOST_CACHE, "Don't cache host names.", 0, 0, 0,
6099    GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
6100   {"skip-new", OPT_SKIP_NEW, "Don't use new, possibly wrong routines.",
6101    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
6102   {"skip-slave-start", 0,
6103    "If set, slave is not autostarted.", &opt_skip_slave_start,
6104    &opt_skip_slave_start, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6105   {"skip-stack-trace", OPT_SKIP_STACK_TRACE,
6106    "Don't print a stack trace on failure.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
6107    0, 0, 0, 0},
6108   {"skip-thread-priority", OPT_SKIP_PRIOR,
6109    "Don't give threads different priorities. This option is deprecated "
6110    "because it has no effect; the implied behavior is already the default.",
6111    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
6112 #if defined(_WIN32) && !defined(EMBEDDED_LIBRARY)
6113   {"slow-start-timeout", 0,
6114    "Maximum number of milliseconds that the service control manager should wait "
6115    "before trying to kill the windows service during startup"
6116    "(Default: 15000).", &slow_start_timeout, &slow_start_timeout, 0,
6117    GET_ULONG, REQUIRED_ARG, 15000, 0, 0, 0, 0, 0},
6118 #endif
6119 #ifdef HAVE_REPLICATION
6120   {"sporadic-binlog-dump-fail", 0,
6121    "Option used by mysql-test for debugging and testing of replication.",
6122    &opt_sporadic_binlog_dump_fail,
6123    &opt_sporadic_binlog_dump_fail, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
6124    0},
6125 #endif /* HAVE_REPLICATION */
6126 #ifdef HAVE_OPENSSL
6127   {"ssl", 0,
6128    "Enable SSL for connection (automatically enabled with other flags).",
6129    &opt_use_ssl, &opt_use_ssl, 0, GET_BOOL, OPT_ARG, 0, 0, 0,
6130    0, 0, 0},
6131 #endif
6132 #ifdef __WIN__
6133   {"standalone", 0,
6134   "Dummy option to start as a standalone program (NT).", 0, 0, 0, GET_NO_ARG,
6135    NO_ARG, 0, 0, 0, 0, 0, 0},
6136 #endif
6137   {"symbolic-links", 's', "Enable symbolic link support.",
6138    &my_use_symdir, &my_use_symdir, 0, GET_BOOL, NO_ARG,
6139    /*
6140      The system call realpath() produces warnings under valgrind and
6141      purify. These are not suppressed: instead we disable symlinks
6142      option if compiled with valgrind support.
6143    */
6144    IF_PURIFY(0,1), 0, 0, 0, 0, 0},
6145   {"sysdate-is-now", 0,
6146    "Non-default option to alias SYSDATE() to NOW() to make it safe-replicable. "
6147    "Since 5.0, SYSDATE() returns a `dynamic' value different for different "
6148    "invocations, even within the same statement.",
6149    &global_system_variables.sysdate_is_now,
6150    0, 0, GET_BOOL, NO_ARG, 0, 0, 1, 0, 1, 0},
6151   {"tc-heuristic-recover", 0,
6152    "Decision to use in heuristic recover process. Possible values are COMMIT "
6153    "or ROLLBACK.", &tc_heuristic_recover, &tc_heuristic_recover,
6154    &tc_heuristic_recover_typelib, GET_ENUM, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6155 #if defined(ENABLED_DEBUG_SYNC)
6156   {"debug-sync-timeout", OPT_DEBUG_SYNC_TIMEOUT,
6157    "Enable the debug sync facility "
6158    "and optionally specify a default wait timeout in seconds. "
6159    "A zero value keeps the facility disabled.",
6160    &opt_debug_sync_timeout, 0,
6161    0, GET_UINT, OPT_ARG, 0, 0, UINT_MAX, 0, 0, 0},
6162 #endif /* defined(ENABLED_DEBUG_SYNC) */
6163   {"temp-pool", 0,
6164 #if (ENABLE_TEMP_POOL)
6165    "Using this option will cause most temporary files created to use a small "
6166    "set of names, rather than a unique name for each new file.",
6167 #else
6168    "This option is ignored on this OS.",
6169 #endif
6170    &use_temp_pool, &use_temp_pool, 0, GET_BOOL, NO_ARG, 1,
6171    0, 0, 0, 0, 0},
6172   {"transaction-isolation", 0,
6173    "Default transaction isolation level.",
6174    &global_system_variables.tx_isolation,
6175    &global_system_variables.tx_isolation, &tx_isolation_typelib,
6176    GET_ENUM, REQUIRED_ARG, ISO_REPEATABLE_READ, 0, 0, 0, 0, 0},
6177   {"user", 'u', "Run mysqld daemon as user.", 0, 0, 0, GET_STR, REQUIRED_ARG,
6178    0, 0, 0, 0, 0, 0},
6179   {"verbose", 'v', "Used with --help option for detailed help.",
6180    &opt_verbose, &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
6181   {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
6182    NO_ARG, 0, 0, 0, 0, 0, 0},
6183   {"plugin-load", 0,
6184    "Optional semicolon-separated list of plugins to load, where each plugin is "
6185    "identified as name=library, where name is the plugin name and library "
6186    "is the plugin library in plugin_dir.",
6187    &opt_plugin_load, &opt_plugin_load, 0,
6188    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
6189   {"table_cache", 0, "Deprecated; use --table-open-cache instead.",
6190    &table_cache_size, &table_cache_size, 0, GET_ULONG,
6191    REQUIRED_ARG, TABLE_OPEN_CACHE_DEFAULT, 1, 512*1024L, 0, 1, 0},
6192   {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
6193 };
6194 
6195 
show_queries(THD * thd,SHOW_VAR * var,char * buff)6196 static int show_queries(THD *thd, SHOW_VAR *var, char *buff)
6197 {
6198   var->type= SHOW_LONGLONG;
6199   var->value= (char *)&thd->query_id;
6200   return 0;
6201 }
6202 
6203 
show_net_compression(THD * thd,SHOW_VAR * var,char * buff)6204 static int show_net_compression(THD *thd, SHOW_VAR *var, char *buff)
6205 {
6206   var->type= SHOW_MY_BOOL;
6207   var->value= (char *)&thd->net.compress;
6208   return 0;
6209 }
6210 
show_starttime(THD * thd,SHOW_VAR * var,char * buff)6211 static int show_starttime(THD *thd, SHOW_VAR *var, char *buff)
6212 {
6213   var->type= SHOW_LONG;
6214   var->value= buff;
6215   *((long *)buff)= (long) (thd->query_start() - server_start_time);
6216   return 0;
6217 }
6218 
6219 #ifdef ENABLED_PROFILING
show_flushstatustime(THD * thd,SHOW_VAR * var,char * buff)6220 static int show_flushstatustime(THD *thd, SHOW_VAR *var, char *buff)
6221 {
6222   var->type= SHOW_LONG;
6223   var->value= buff;
6224   *((long *)buff)= (long) (thd->query_start() - flush_status_time);
6225   return 0;
6226 }
6227 #endif
6228 
6229 #ifdef HAVE_REPLICATION
show_rpl_status(THD * thd,SHOW_VAR * var,char * buff)6230 static int show_rpl_status(THD *thd, SHOW_VAR *var, char *buff)
6231 {
6232   var->type= SHOW_CHAR;
6233   var->value= const_cast<char*>(rpl_status_type[(int)rpl_status]);
6234   return 0;
6235 }
6236 
show_slave_running(THD * thd,SHOW_VAR * var,char * buff)6237 static int show_slave_running(THD *thd, SHOW_VAR *var, char *buff)
6238 {
6239   var->type= SHOW_MY_BOOL;
6240   mysql_mutex_lock(&LOCK_active_mi);
6241   var->value= buff;
6242   *((my_bool *)buff)= (my_bool) (active_mi &&
6243                                  active_mi->slave_running == MYSQL_SLAVE_RUN_CONNECT &&
6244                                  active_mi->rli.slave_running);
6245   mysql_mutex_unlock(&LOCK_active_mi);
6246   return 0;
6247 }
6248 
show_slave_retried_trans(THD * thd,SHOW_VAR * var,char * buff)6249 static int show_slave_retried_trans(THD *thd, SHOW_VAR *var, char *buff)
6250 {
6251   /*
6252     TODO: with multimaster, have one such counter per line in
6253     SHOW SLAVE STATUS, and have the sum over all lines here.
6254   */
6255   mysql_mutex_lock(&LOCK_active_mi);
6256   if (active_mi)
6257   {
6258     var->type= SHOW_LONG;
6259     var->value= buff;
6260     mysql_mutex_lock(&active_mi->rli.data_lock);
6261     *((long *)buff)= (long)active_mi->rli.retried_trans;
6262     mysql_mutex_unlock(&active_mi->rli.data_lock);
6263   }
6264   else
6265     var->type= SHOW_UNDEF;
6266   mysql_mutex_unlock(&LOCK_active_mi);
6267   return 0;
6268 }
6269 
show_slave_received_heartbeats(THD * thd,SHOW_VAR * var,char * buff)6270 static int show_slave_received_heartbeats(THD *thd, SHOW_VAR *var, char *buff)
6271 {
6272   mysql_mutex_lock(&LOCK_active_mi);
6273   if (active_mi)
6274   {
6275     var->type= SHOW_LONGLONG;
6276     var->value= buff;
6277     mysql_mutex_lock(&active_mi->rli.data_lock);
6278     *((longlong *)buff)= active_mi->received_heartbeats;
6279     mysql_mutex_unlock(&active_mi->rli.data_lock);
6280   }
6281   else
6282     var->type= SHOW_UNDEF;
6283   mysql_mutex_unlock(&LOCK_active_mi);
6284   return 0;
6285 }
6286 
show_heartbeat_period(THD * thd,SHOW_VAR * var,char * buff)6287 static int show_heartbeat_period(THD *thd, SHOW_VAR *var, char *buff)
6288 {
6289   mysql_mutex_lock(&LOCK_active_mi);
6290   if (active_mi)
6291   {
6292     var->type= SHOW_CHAR;
6293     var->value= buff;
6294     sprintf(buff, "%.3f", active_mi->heartbeat_period);
6295   }
6296   else
6297     var->type= SHOW_UNDEF;
6298   mysql_mutex_unlock(&LOCK_active_mi);
6299   return 0;
6300 }
6301 
6302 
6303 #endif /* HAVE_REPLICATION */
6304 
show_open_tables(THD * thd,SHOW_VAR * var,char * buff)6305 static int show_open_tables(THD *thd, SHOW_VAR *var, char *buff)
6306 {
6307   var->type= SHOW_LONG;
6308   var->value= buff;
6309   *((long *)buff)= (long)cached_open_tables();
6310   return 0;
6311 }
6312 
show_prepared_stmt_count(THD * thd,SHOW_VAR * var,char * buff)6313 static int show_prepared_stmt_count(THD *thd, SHOW_VAR *var, char *buff)
6314 {
6315   var->type= SHOW_LONG;
6316   var->value= buff;
6317   mysql_mutex_lock(&LOCK_prepared_stmt_count);
6318   *((long *)buff)= (long)prepared_stmt_count;
6319   mysql_mutex_unlock(&LOCK_prepared_stmt_count);
6320   return 0;
6321 }
6322 
show_table_definitions(THD * thd,SHOW_VAR * var,char * buff)6323 static int show_table_definitions(THD *thd, SHOW_VAR *var, char *buff)
6324 {
6325   var->type= SHOW_LONG;
6326   var->value= buff;
6327   *((long *)buff)= (long)cached_table_definitions();
6328   return 0;
6329 }
6330 
6331 #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
6332 /* Functions relying on CTX */
show_ssl_ctx_sess_accept(THD * thd,SHOW_VAR * var,char * buff)6333 static int show_ssl_ctx_sess_accept(THD *thd, SHOW_VAR *var, char *buff)
6334 {
6335   var->type= SHOW_LONG;
6336   var->value= buff;
6337   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
6338                      SSL_CTX_sess_accept(ssl_acceptor_fd->ssl_context));
6339   return 0;
6340 }
6341 
show_ssl_ctx_sess_accept_good(THD * thd,SHOW_VAR * var,char * buff)6342 static int show_ssl_ctx_sess_accept_good(THD *thd, SHOW_VAR *var, char *buff)
6343 {
6344   var->type= SHOW_LONG;
6345   var->value= buff;
6346   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
6347                      SSL_CTX_sess_accept_good(ssl_acceptor_fd->ssl_context));
6348   return 0;
6349 }
6350 
show_ssl_ctx_sess_connect_good(THD * thd,SHOW_VAR * var,char * buff)6351 static int show_ssl_ctx_sess_connect_good(THD *thd, SHOW_VAR *var, char *buff)
6352 {
6353   var->type= SHOW_LONG;
6354   var->value= buff;
6355   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
6356                      SSL_CTX_sess_connect_good(ssl_acceptor_fd->ssl_context));
6357   return 0;
6358 }
6359 
show_ssl_ctx_sess_accept_renegotiate(THD * thd,SHOW_VAR * var,char * buff)6360 static int show_ssl_ctx_sess_accept_renegotiate(THD *thd, SHOW_VAR *var, char *buff)
6361 {
6362   var->type= SHOW_LONG;
6363   var->value= buff;
6364   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
6365                      SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context));
6366   return 0;
6367 }
6368 
show_ssl_ctx_sess_connect_renegotiate(THD * thd,SHOW_VAR * var,char * buff)6369 static int show_ssl_ctx_sess_connect_renegotiate(THD *thd, SHOW_VAR *var, char *buff)
6370 {
6371   var->type= SHOW_LONG;
6372   var->value= buff;
6373   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
6374                      SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd->ssl_context));
6375   return 0;
6376 }
6377 
show_ssl_ctx_sess_cb_hits(THD * thd,SHOW_VAR * var,char * buff)6378 static int show_ssl_ctx_sess_cb_hits(THD *thd, SHOW_VAR *var, char *buff)
6379 {
6380   var->type= SHOW_LONG;
6381   var->value= buff;
6382   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
6383                      SSL_CTX_sess_cb_hits(ssl_acceptor_fd->ssl_context));
6384   return 0;
6385 }
6386 
show_ssl_ctx_sess_hits(THD * thd,SHOW_VAR * var,char * buff)6387 static int show_ssl_ctx_sess_hits(THD *thd, SHOW_VAR *var, char *buff)
6388 {
6389   var->type= SHOW_LONG;
6390   var->value= buff;
6391   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
6392                      SSL_CTX_sess_hits(ssl_acceptor_fd->ssl_context));
6393   return 0;
6394 }
6395 
show_ssl_ctx_sess_cache_full(THD * thd,SHOW_VAR * var,char * buff)6396 static int show_ssl_ctx_sess_cache_full(THD *thd, SHOW_VAR *var, char *buff)
6397 {
6398   var->type= SHOW_LONG;
6399   var->value= buff;
6400   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
6401                      SSL_CTX_sess_cache_full(ssl_acceptor_fd->ssl_context));
6402   return 0;
6403 }
6404 
show_ssl_ctx_sess_misses(THD * thd,SHOW_VAR * var,char * buff)6405 static int show_ssl_ctx_sess_misses(THD *thd, SHOW_VAR *var, char *buff)
6406 {
6407   var->type= SHOW_LONG;
6408   var->value= buff;
6409   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
6410                      SSL_CTX_sess_misses(ssl_acceptor_fd->ssl_context));
6411   return 0;
6412 }
6413 
show_ssl_ctx_sess_timeouts(THD * thd,SHOW_VAR * var,char * buff)6414 static int show_ssl_ctx_sess_timeouts(THD *thd, SHOW_VAR *var, char *buff)
6415 {
6416   var->type= SHOW_LONG;
6417   var->value= buff;
6418   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
6419                      SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context));
6420   return 0;
6421 }
6422 
show_ssl_ctx_sess_number(THD * thd,SHOW_VAR * var,char * buff)6423 static int show_ssl_ctx_sess_number(THD *thd, SHOW_VAR *var, char *buff)
6424 {
6425   var->type= SHOW_LONG;
6426   var->value= buff;
6427   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
6428                      SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context));
6429   return 0;
6430 }
6431 
show_ssl_ctx_sess_connect(THD * thd,SHOW_VAR * var,char * buff)6432 static int show_ssl_ctx_sess_connect(THD *thd, SHOW_VAR *var, char *buff)
6433 {
6434   var->type= SHOW_LONG;
6435   var->value= buff;
6436   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
6437                      SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context));
6438   return 0;
6439 }
6440 
show_ssl_ctx_sess_get_cache_size(THD * thd,SHOW_VAR * var,char * buff)6441 static int show_ssl_ctx_sess_get_cache_size(THD *thd, SHOW_VAR *var, char *buff)
6442 {
6443   var->type= SHOW_LONG;
6444   var->value= buff;
6445   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
6446                      SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context));
6447   return 0;
6448 }
6449 
show_ssl_ctx_get_verify_mode(THD * thd,SHOW_VAR * var,char * buff)6450 static int show_ssl_ctx_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff)
6451 {
6452   var->type= SHOW_LONG;
6453   var->value= buff;
6454   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
6455                      SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context));
6456   return 0;
6457 }
6458 
show_ssl_ctx_get_verify_depth(THD * thd,SHOW_VAR * var,char * buff)6459 static int show_ssl_ctx_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff)
6460 {
6461   var->type= SHOW_LONG;
6462   var->value= buff;
6463   *((long *)buff)= (!ssl_acceptor_fd ? 0 :
6464                      SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context));
6465   return 0;
6466 }
6467 
show_ssl_ctx_get_session_cache_mode(THD * thd,SHOW_VAR * var,char * buff)6468 static int show_ssl_ctx_get_session_cache_mode(THD *thd, SHOW_VAR *var, char *buff)
6469 {
6470   var->type= SHOW_CHAR;
6471   if (!ssl_acceptor_fd)
6472     var->value= const_cast<char*>("NONE");
6473   else
6474     switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context))
6475     {
6476     case SSL_SESS_CACHE_OFF:
6477       var->value= const_cast<char*>("OFF"); break;
6478     case SSL_SESS_CACHE_CLIENT:
6479       var->value= const_cast<char*>("CLIENT"); break;
6480     case SSL_SESS_CACHE_SERVER:
6481       var->value= const_cast<char*>("SERVER"); break;
6482     case SSL_SESS_CACHE_BOTH:
6483       var->value= const_cast<char*>("BOTH"); break;
6484     case SSL_SESS_CACHE_NO_AUTO_CLEAR:
6485       var->value= const_cast<char*>("NO_AUTO_CLEAR"); break;
6486     case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP:
6487       var->value= const_cast<char*>("NO_INTERNAL_LOOKUP"); break;
6488     default:
6489       var->value= const_cast<char*>("Unknown"); break;
6490     }
6491   return 0;
6492 }
6493 
6494 /*
6495    Functions relying on SSL
6496    Note: In the show_ssl_* functions, we need to check if we have a
6497          valid vio-object since this isn't always true, specifically
6498          when session_status or global_status is requested from
6499          inside an Event.
6500  */
show_ssl_get_version(THD * thd,SHOW_VAR * var,char * buff)6501 static int show_ssl_get_version(THD *thd, SHOW_VAR *var, char *buff)
6502 {
6503   var->type= SHOW_CHAR;
6504   if( thd->vio_ok() && thd->net.vio->ssl_arg )
6505     var->value= const_cast<char*>(SSL_get_version((SSL*) thd->net.vio->ssl_arg));
6506   else
6507     var->value= (char *)"";
6508   return 0;
6509 }
6510 
show_ssl_session_reused(THD * thd,SHOW_VAR * var,char * buff)6511 static int show_ssl_session_reused(THD *thd, SHOW_VAR *var, char *buff)
6512 {
6513   var->type= SHOW_LONG;
6514   var->value= buff;
6515   if( thd->vio_ok() && thd->net.vio->ssl_arg )
6516     *((long *)buff)= (long)SSL_session_reused((SSL*) thd->net.vio->ssl_arg);
6517   else
6518     *((long *)buff)= 0;
6519   return 0;
6520 }
6521 
show_ssl_get_default_timeout(THD * thd,SHOW_VAR * var,char * buff)6522 static int show_ssl_get_default_timeout(THD *thd, SHOW_VAR *var, char *buff)
6523 {
6524   var->type= SHOW_LONG;
6525   var->value= buff;
6526   if( thd->vio_ok() && thd->net.vio->ssl_arg )
6527     *((long *)buff)= (long)SSL_get_default_timeout((SSL*)thd->net.vio->ssl_arg);
6528   else
6529     *((long *)buff)= 0;
6530   return 0;
6531 }
6532 
show_ssl_get_verify_mode(THD * thd,SHOW_VAR * var,char * buff)6533 static int show_ssl_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff)
6534 {
6535   var->type= SHOW_LONG;
6536   var->value= buff;
6537   if( thd->net.vio && thd->net.vio->ssl_arg )
6538     *((long *)buff)= (long)SSL_get_verify_mode((SSL*)thd->net.vio->ssl_arg);
6539   else
6540     *((long *)buff)= 0;
6541   return 0;
6542 }
6543 
show_ssl_get_verify_depth(THD * thd,SHOW_VAR * var,char * buff)6544 static int show_ssl_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff)
6545 {
6546   var->type= SHOW_LONG;
6547   var->value= buff;
6548   if( thd->vio_ok() && thd->net.vio->ssl_arg )
6549     *((long *)buff)= (long)SSL_get_verify_depth((SSL*)thd->net.vio->ssl_arg);
6550   else
6551     *((long *)buff)= 0;
6552   return 0;
6553 }
6554 
show_ssl_get_cipher(THD * thd,SHOW_VAR * var,char * buff)6555 static int show_ssl_get_cipher(THD *thd, SHOW_VAR *var, char *buff)
6556 {
6557   var->type= SHOW_CHAR;
6558   if( thd->vio_ok() && thd->net.vio->ssl_arg )
6559     var->value= const_cast<char*>(SSL_get_cipher((SSL*) thd->net.vio->ssl_arg));
6560   else
6561     var->value= (char *)"";
6562   return 0;
6563 }
6564 
show_ssl_get_cipher_list(THD * thd,SHOW_VAR * var,char * buff)6565 static int show_ssl_get_cipher_list(THD *thd, SHOW_VAR *var, char *buff)
6566 {
6567   var->type= SHOW_CHAR;
6568   var->value= buff;
6569   if (thd->vio_ok() && thd->net.vio->ssl_arg)
6570   {
6571     int i;
6572     const char *p;
6573     char *end= buff + SHOW_VAR_FUNC_BUFF_SIZE;
6574     for (i=0; (p= SSL_get_cipher_list((SSL*) thd->net.vio->ssl_arg,i)) &&
6575                buff < end; i++)
6576     {
6577       buff= strnmov(buff, p, end-buff-1);
6578       *buff++= ':';
6579     }
6580     if (i)
6581       buff--;
6582   }
6583   *buff=0;
6584   return 0;
6585 }
6586 
6587 #endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */
6588 
6589 
6590 /*
6591   Variables shown by SHOW STATUS in alphabetical order
6592 */
6593 
6594 SHOW_VAR status_vars[]= {
6595   {"Aborted_clients",          (char*) &aborted_threads,        SHOW_LONG},
6596   {"Aborted_connects",         (char*) &aborted_connects,       SHOW_LONG},
6597   {"Binlog_cache_disk_use",    (char*) &binlog_cache_disk_use,  SHOW_LONG},
6598   {"Binlog_cache_use",         (char*) &binlog_cache_use,       SHOW_LONG},
6599   {"Binlog_stmt_cache_disk_use",(char*) &binlog_stmt_cache_disk_use,  SHOW_LONG},
6600   {"Binlog_stmt_cache_use",    (char*) &binlog_stmt_cache_use,       SHOW_LONG},
6601   {"Bytes_received",           (char*) offsetof(STATUS_VAR, bytes_received), SHOW_LONGLONG_STATUS},
6602   {"Bytes_sent",               (char*) offsetof(STATUS_VAR, bytes_sent), SHOW_LONGLONG_STATUS},
6603   {"Com",                      (char*) com_status_vars, SHOW_ARRAY},
6604   {"Compression",              (char*) &show_net_compression, SHOW_FUNC},
6605   {"Connections",              (char*) &thread_id,              SHOW_LONG_NOFLUSH},
6606   {"Created_tmp_disk_tables",  (char*) offsetof(STATUS_VAR, created_tmp_disk_tables), SHOW_LONG_STATUS},
6607   {"Created_tmp_files",	       (char*) &my_tmp_file_created,	SHOW_LONG},
6608   {"Created_tmp_tables",       (char*) offsetof(STATUS_VAR, created_tmp_tables), SHOW_LONG_STATUS},
6609   {"Delayed_errors",           (char*) &delayed_insert_errors,  SHOW_LONG},
6610   {"Delayed_insert_threads",   (char*) &delayed_insert_threads, SHOW_LONG_NOFLUSH},
6611   {"Delayed_writes",           (char*) &delayed_insert_writes,  SHOW_LONG},
6612   {"Flush_commands",           (char*) &refresh_version,        SHOW_LONG_NOFLUSH},
6613   {"Handler_commit",           (char*) offsetof(STATUS_VAR, ha_commit_count), SHOW_LONG_STATUS},
6614   {"Handler_delete",           (char*) offsetof(STATUS_VAR, ha_delete_count), SHOW_LONG_STATUS},
6615   {"Handler_discover",         (char*) offsetof(STATUS_VAR, ha_discover_count), SHOW_LONG_STATUS},
6616   {"Handler_prepare",          (char*) offsetof(STATUS_VAR, ha_prepare_count),  SHOW_LONG_STATUS},
6617   {"Handler_read_first",       (char*) offsetof(STATUS_VAR, ha_read_first_count), SHOW_LONG_STATUS},
6618   {"Handler_read_key",         (char*) offsetof(STATUS_VAR, ha_read_key_count), SHOW_LONG_STATUS},
6619   {"Handler_read_last",        (char*) offsetof(STATUS_VAR, ha_read_last_count), SHOW_LONG_STATUS},
6620   {"Handler_read_next",        (char*) offsetof(STATUS_VAR, ha_read_next_count), SHOW_LONG_STATUS},
6621   {"Handler_read_prev",        (char*) offsetof(STATUS_VAR, ha_read_prev_count), SHOW_LONG_STATUS},
6622   {"Handler_read_rnd",         (char*) offsetof(STATUS_VAR, ha_read_rnd_count), SHOW_LONG_STATUS},
6623   {"Handler_read_rnd_next",    (char*) offsetof(STATUS_VAR, ha_read_rnd_next_count), SHOW_LONG_STATUS},
6624   {"Handler_rollback",         (char*) offsetof(STATUS_VAR, ha_rollback_count), SHOW_LONG_STATUS},
6625   {"Handler_savepoint",        (char*) offsetof(STATUS_VAR, ha_savepoint_count), SHOW_LONG_STATUS},
6626   {"Handler_savepoint_rollback",(char*) offsetof(STATUS_VAR, ha_savepoint_rollback_count), SHOW_LONG_STATUS},
6627   {"Handler_update",           (char*) offsetof(STATUS_VAR, ha_update_count), SHOW_LONG_STATUS},
6628   {"Handler_write",            (char*) offsetof(STATUS_VAR, ha_write_count), SHOW_LONG_STATUS},
6629   {"Key_blocks_not_flushed",   (char*) offsetof(KEY_CACHE, global_blocks_changed), SHOW_KEY_CACHE_LONG},
6630   {"Key_blocks_unused",        (char*) offsetof(KEY_CACHE, blocks_unused), SHOW_KEY_CACHE_LONG},
6631   {"Key_blocks_used",          (char*) offsetof(KEY_CACHE, blocks_used), SHOW_KEY_CACHE_LONG},
6632   {"Key_read_requests",        (char*) offsetof(KEY_CACHE, global_cache_r_requests), SHOW_KEY_CACHE_LONGLONG},
6633   {"Key_reads",                (char*) offsetof(KEY_CACHE, global_cache_read), SHOW_KEY_CACHE_LONGLONG},
6634   {"Key_write_requests",       (char*) offsetof(KEY_CACHE, global_cache_w_requests), SHOW_KEY_CACHE_LONGLONG},
6635   {"Key_writes",               (char*) offsetof(KEY_CACHE, global_cache_write), SHOW_KEY_CACHE_LONGLONG},
6636   {"Last_query_cost",          (char*) offsetof(STATUS_VAR, last_query_cost), SHOW_DOUBLE_STATUS},
6637   {"Max_used_connections",     (char*) &max_used_connections,  SHOW_LONG},
6638   {"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use,    SHOW_LONG_NOFLUSH},
6639   {"Open_files",               (char*) &my_file_opened,         SHOW_LONG_NOFLUSH},
6640   {"Open_streams",             (char*) &my_stream_opened,       SHOW_LONG_NOFLUSH},
6641   {"Open_table_definitions",   (char*) &show_table_definitions, SHOW_FUNC},
6642   {"Open_tables",              (char*) &show_open_tables,       SHOW_FUNC},
6643   {"Opened_files",             (char*) &my_file_total_opened, SHOW_LONG_NOFLUSH},
6644   {"Opened_tables",            (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONG_STATUS},
6645   {"Opened_table_definitions", (char*) offsetof(STATUS_VAR, opened_shares), SHOW_LONG_STATUS},
6646   {"Prepared_stmt_count",      (char*) &show_prepared_stmt_count, SHOW_FUNC},
6647 #ifdef HAVE_QUERY_CACHE
6648   {"Qcache_free_blocks",       (char*) &query_cache.free_memory_blocks, SHOW_LONG_NOFLUSH},
6649   {"Qcache_free_memory",       (char*) &query_cache.free_memory, SHOW_LONG_NOFLUSH},
6650   {"Qcache_hits",              (char*) &query_cache.hits,       SHOW_LONG},
6651   {"Qcache_inserts",           (char*) &query_cache.inserts,    SHOW_LONG},
6652   {"Qcache_lowmem_prunes",     (char*) &query_cache.lowmem_prunes, SHOW_LONG},
6653   {"Qcache_not_cached",        (char*) &query_cache.refused,    SHOW_LONG},
6654   {"Qcache_queries_in_cache",  (char*) &query_cache.queries_in_cache, SHOW_LONG_NOFLUSH},
6655   {"Qcache_total_blocks",      (char*) &query_cache.total_blocks, SHOW_LONG_NOFLUSH},
6656 #endif /*HAVE_QUERY_CACHE*/
6657   {"Queries",                  (char*) &show_queries,            SHOW_FUNC},
6658   {"Questions",                (char*) offsetof(STATUS_VAR, questions), SHOW_LONG_STATUS},
6659 #ifdef HAVE_REPLICATION
6660   {"Rpl_status",               (char*) &show_rpl_status,          SHOW_FUNC},
6661 #endif
6662   {"Select_full_join",         (char*) offsetof(STATUS_VAR, select_full_join_count), SHOW_LONG_STATUS},
6663   {"Select_full_range_join",   (char*) offsetof(STATUS_VAR, select_full_range_join_count), SHOW_LONG_STATUS},
6664   {"Select_range",             (char*) offsetof(STATUS_VAR, select_range_count), SHOW_LONG_STATUS},
6665   {"Select_range_check",       (char*) offsetof(STATUS_VAR, select_range_check_count), SHOW_LONG_STATUS},
6666   {"Select_scan",	       (char*) offsetof(STATUS_VAR, select_scan_count), SHOW_LONG_STATUS},
6667   {"Slave_open_temp_tables",   (char*) &slave_open_temp_tables, SHOW_LONG},
6668 #ifdef HAVE_REPLICATION
6669   {"Slave_retried_transactions",(char*) &show_slave_retried_trans, SHOW_FUNC},
6670   {"Slave_heartbeat_period",   (char*) &show_heartbeat_period, SHOW_FUNC},
6671   {"Slave_received_heartbeats",(char*) &show_slave_received_heartbeats, SHOW_FUNC},
6672   {"Slave_running",            (char*) &show_slave_running,     SHOW_FUNC},
6673 #endif
6674   {"Slow_launch_threads",      (char*) &slow_launch_threads,    SHOW_LONG},
6675   {"Slow_queries",             (char*) offsetof(STATUS_VAR, long_query_count), SHOW_LONG_STATUS},
6676   {"Sort_merge_passes",	       (char*) offsetof(STATUS_VAR, filesort_merge_passes), SHOW_LONG_STATUS},
6677   {"Sort_range",	       (char*) offsetof(STATUS_VAR, filesort_range_count), SHOW_LONG_STATUS},
6678   {"Sort_rows",		       (char*) offsetof(STATUS_VAR, filesort_rows), SHOW_LONG_STATUS},
6679   {"Sort_scan",		       (char*) offsetof(STATUS_VAR, filesort_scan_count), SHOW_LONG_STATUS},
6680 #ifdef HAVE_OPENSSL
6681 #ifndef EMBEDDED_LIBRARY
6682   {"Ssl_accept_renegotiates",  (char*) &show_ssl_ctx_sess_accept_renegotiate, SHOW_FUNC},
6683   {"Ssl_accepts",              (char*) &show_ssl_ctx_sess_accept, SHOW_FUNC},
6684   {"Ssl_callback_cache_hits",  (char*) &show_ssl_ctx_sess_cb_hits, SHOW_FUNC},
6685   {"Ssl_cipher",               (char*) &show_ssl_get_cipher, SHOW_FUNC},
6686   {"Ssl_cipher_list",          (char*) &show_ssl_get_cipher_list, SHOW_FUNC},
6687   {"Ssl_client_connects",      (char*) &show_ssl_ctx_sess_connect, SHOW_FUNC},
6688   {"Ssl_connect_renegotiates", (char*) &show_ssl_ctx_sess_connect_renegotiate, SHOW_FUNC},
6689   {"Ssl_ctx_verify_depth",     (char*) &show_ssl_ctx_get_verify_depth, SHOW_FUNC},
6690   {"Ssl_ctx_verify_mode",      (char*) &show_ssl_ctx_get_verify_mode, SHOW_FUNC},
6691   {"Ssl_default_timeout",      (char*) &show_ssl_get_default_timeout, SHOW_FUNC},
6692   {"Ssl_finished_accepts",     (char*) &show_ssl_ctx_sess_accept_good, SHOW_FUNC},
6693   {"Ssl_finished_connects",    (char*) &show_ssl_ctx_sess_connect_good, SHOW_FUNC},
6694   {"Ssl_session_cache_hits",   (char*) &show_ssl_ctx_sess_hits, SHOW_FUNC},
6695   {"Ssl_session_cache_misses", (char*) &show_ssl_ctx_sess_misses, SHOW_FUNC},
6696   {"Ssl_session_cache_mode",   (char*) &show_ssl_ctx_get_session_cache_mode, SHOW_FUNC},
6697   {"Ssl_session_cache_overflows", (char*) &show_ssl_ctx_sess_cache_full, SHOW_FUNC},
6698   {"Ssl_session_cache_size",   (char*) &show_ssl_ctx_sess_get_cache_size, SHOW_FUNC},
6699   {"Ssl_session_cache_timeouts", (char*) &show_ssl_ctx_sess_timeouts, SHOW_FUNC},
6700   {"Ssl_sessions_reused",      (char*) &show_ssl_session_reused, SHOW_FUNC},
6701   {"Ssl_used_session_cache_entries",(char*) &show_ssl_ctx_sess_number, SHOW_FUNC},
6702   {"Ssl_verify_depth",         (char*) &show_ssl_get_verify_depth, SHOW_FUNC},
6703   {"Ssl_verify_mode",          (char*) &show_ssl_get_verify_mode, SHOW_FUNC},
6704   {"Ssl_version",              (char*) &show_ssl_get_version, SHOW_FUNC},
6705 #endif
6706 #endif /* HAVE_OPENSSL */
6707   {"Table_locks_immediate",    (char*) &locks_immediate,        SHOW_LONG},
6708   {"Table_locks_waited",       (char*) &locks_waited,           SHOW_LONG},
6709 #ifdef HAVE_MMAP
6710   {"Tc_log_max_pages_used",    (char*) &tc_log_max_pages_used,  SHOW_LONG},
6711   {"Tc_log_page_size",         (char*) &tc_log_page_size,       SHOW_LONG},
6712   {"Tc_log_page_waits",        (char*) &tc_log_page_waits,      SHOW_LONG},
6713 #endif
6714   {"Threads_cached",           (char*) &cached_thread_count,    SHOW_LONG_NOFLUSH},
6715   {"Threads_connected",        (char*) &connection_count,       SHOW_INT},
6716   {"Threads_created",	       (char*) &thread_created,		SHOW_LONG_NOFLUSH},
6717   {"Threads_running",          (char*) &thread_running,         SHOW_INT},
6718   {"Uptime",                   (char*) &show_starttime,         SHOW_FUNC},
6719 #ifdef ENABLED_PROFILING
6720   {"Uptime_since_flush_status",(char*) &show_flushstatustime,   SHOW_FUNC},
6721 #endif
6722   {NullS, NullS, SHOW_LONG}
6723 };
6724 
add_terminator(DYNAMIC_ARRAY * options)6725 bool add_terminator(DYNAMIC_ARRAY *options)
6726 {
6727   my_option empty_element= {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0};
6728   return insert_dynamic(options, (uchar *)&empty_element);
6729 }
6730 
6731 #ifndef EMBEDDED_LIBRARY
print_version(void)6732 static void print_version(void)
6733 {
6734   set_server_version();
6735 
6736   printf("%s  Ver %s for %s on %s (%s)\n",my_progname,
6737 	 server_version,SYSTEM_TYPE,MACHINE_TYPE, MYSQL_COMPILATION_COMMENT);
6738 }
6739 
6740 /** Compares two options' names, treats - and _ the same */
option_cmp(my_option * a,my_option * b)6741 static int option_cmp(my_option *a, my_option *b)
6742 {
6743   const char *sa= a->name;
6744   const char *sb= b->name;
6745   for (; *sa || *sb; sa++, sb++)
6746   {
6747     if (*sa < *sb)
6748     {
6749       if (*sa == '-' && *sb == '_')
6750         continue;
6751       else
6752         return -1;
6753     }
6754     if (*sa > *sb)
6755     {
6756       if (*sa == '_' && *sb == '-')
6757         continue;
6758       else
6759         return 1;
6760     }
6761   }
6762   DBUG_ASSERT(a->name == b->name);
6763   return 0;
6764 }
6765 
print_help()6766 static void print_help()
6767 {
6768   MEM_ROOT mem_root;
6769   init_alloc_root(&mem_root, 4096, 4096);
6770 
6771   pop_dynamic(&all_options);
6772   sys_var_add_options(&all_options, sys_var::PARSE_EARLY);
6773   add_plugin_options(&all_options, &mem_root);
6774   sort_dynamic(&all_options, (qsort_cmp) option_cmp);
6775   add_terminator(&all_options);
6776 
6777   my_print_help((my_option*) all_options.buffer);
6778   my_print_variables((my_option*) all_options.buffer);
6779 
6780   free_root(&mem_root, MYF(0));
6781   delete_dynamic(&all_options);
6782 }
6783 
usage(void)6784 static void usage(void)
6785 {
6786   DBUG_ENTER("usage");
6787   if (!(default_charset_info= get_charset_by_csname(default_character_set_name,
6788 					           MY_CS_PRIMARY,
6789 						   MYF(MY_WME))))
6790     exit(1);
6791   if (!default_collation_name)
6792     default_collation_name= (char*) default_charset_info->name;
6793   print_version();
6794   puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
6795   puts("Starts the MySQL database server.\n");
6796   printf("Usage: %s [OPTIONS]\n", my_progname);
6797   if (!opt_verbose)
6798     puts("\nFor more help options (several pages), use mysqld --verbose --help.");
6799   else
6800   {
6801 #ifdef __WIN__
6802   puts("NT and Win32 specific options:\n\
6803   --install                     Install the default service (NT).\n\
6804   --install-manual              Install the default service started manually (NT).\n\
6805   --install service_name        Install an optional service (NT).\n\
6806   --install-manual service_name Install an optional service started manually (NT).\n\
6807   --remove                      Remove the default service from the service list (NT).\n\
6808   --remove service_name         Remove the service_name from the service list (NT).\n\
6809   --enable-named-pipe           Only to be used for the default server (NT).\n\
6810   --standalone                  Dummy option to start as a standalone server (NT).\
6811 ");
6812   puts("");
6813 #endif
6814   print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
6815   puts("");
6816   set_ports();
6817 
6818   /* Print out all the options including plugin supplied options */
6819   print_help();
6820 
6821   if (! plugins_are_initialized)
6822   {
6823     puts("\n\
6824 Plugins have parameters that are not reflected in this list\n\
6825 because execution stopped before plugins were initialized.");
6826   }
6827 
6828   puts("\n\
6829 To see what values a running MySQL server is using, type\n\
6830 'mysqladmin variables' instead of 'mysqld --verbose --help'.");
6831   }
6832   DBUG_VOID_RETURN;
6833 }
6834 #endif /*!EMBEDDED_LIBRARY*/
6835 
6836 /**
6837   Initialize MySQL global variables to default values.
6838 
6839   @note
6840     The reason to set a lot of global variables to zero is to allow one to
6841     restart the embedded server with a clean environment
6842     It's also needed on some exotic platforms where global variables are
6843     not set to 0 when a program starts.
6844 
6845     We don't need to set variables refered to in my_long_options
6846     as these are initialized by my_getopt.
6847 */
6848 
mysql_init_variables(void)6849 static int mysql_init_variables(void)
6850 {
6851   /* Things reset to zero */
6852   opt_skip_slave_start= opt_reckless_slave = 0;
6853   mysql_home[0]= pidfile_name[0]= log_error_file[0]= 0;
6854   myisam_test_invalid_symlink= test_if_data_home_dir;
6855   opt_log= opt_slow_log= 0;
6856   opt_bin_log= 0;
6857   opt_disable_networking= opt_skip_show_db=0;
6858   opt_skip_name_resolve= 0;
6859   opt_ignore_builtin_innodb= 0;
6860   opt_logname= opt_update_logname= opt_binlog_index_name= opt_slow_logname= 0;
6861   opt_tc_log_file= (char *)"tc.log";      // no hostname in tc_log file name !
6862   opt_secure_auth= 0;
6863   opt_bootstrap= opt_myisam_log= 0;
6864   mqh_used= 0;
6865   kill_in_progress= 0;
6866   cleanup_done= 0;
6867   server_id_supplied= 0;
6868   test_flags= select_errors= dropping_tables= ha_open_options=0;
6869   thread_count= thread_running= kill_cached_threads= wake_thread=0;
6870   slave_open_temp_tables= 0;
6871   cached_thread_count= 0;
6872   opt_endinfo= using_udf_functions= 0;
6873   opt_using_transactions= 0;
6874   abort_loop= select_thread_in_use= signal_thread_in_use= 0;
6875   ready_to_exit= shutdown_in_progress= grant_option= 0;
6876   aborted_threads= aborted_connects= 0;
6877   delayed_insert_threads= delayed_insert_writes= delayed_rows_in_use= 0;
6878   delayed_insert_errors= thread_created= 0;
6879   specialflag= 0;
6880   binlog_cache_use=  binlog_cache_disk_use= 0;
6881   max_used_connections= slow_launch_threads = 0;
6882   mysqld_user= mysqld_chroot= opt_init_file= opt_bin_logname = 0;
6883   prepared_stmt_count= 0;
6884   mysqld_unix_port= opt_mysql_tmpdir= my_bind_addr_str= NullS;
6885   bzero((uchar*) &mysql_tmpdir_list, sizeof(mysql_tmpdir_list));
6886   bzero((char *) &global_status_var, sizeof(global_status_var));
6887   opt_large_pages= 0;
6888   opt_super_large_pages= 0;
6889 #if defined(ENABLED_DEBUG_SYNC)
6890   opt_debug_sync_timeout= 0;
6891 #endif /* defined(ENABLED_DEBUG_SYNC) */
6892   key_map_full.set_all();
6893 
6894   /* Character sets */
6895   system_charset_info= &my_charset_utf8_general_ci;
6896   files_charset_info= &my_charset_utf8_general_ci;
6897   national_charset_info= &my_charset_utf8_general_ci;
6898   table_alias_charset= &my_charset_bin;
6899   character_set_filesystem= &my_charset_bin;
6900 
6901   opt_specialflag= SPECIAL_ENGLISH;
6902   unix_sock= ip_sock= INVALID_SOCKET;
6903   mysql_home_ptr= mysql_home;
6904   pidfile_name_ptr= pidfile_name;
6905   log_error_file_ptr= log_error_file;
6906   lc_messages_dir_ptr= lc_messages_dir;
6907   protocol_version= PROTOCOL_VERSION;
6908   what_to_log= ~ (1L << (uint) COM_TIME);
6909   refresh_version= 1L;	/* Increments on each reload */
6910   global_query_id= thread_id= 1L;
6911   my_atomic_rwlock_init(&global_query_id_lock);
6912   my_atomic_rwlock_init(&thread_running_lock);
6913   strmov(server_version, MYSQL_SERVER_VERSION);
6914   threads.empty();
6915   thread_cache.empty();
6916   key_caches.empty();
6917   if (!(dflt_key_cache= get_or_create_key_cache(default_key_cache_base.str,
6918                                                 default_key_cache_base.length)))
6919   {
6920     sql_print_error("Cannot allocate the keycache");
6921     return 1;
6922   }
6923   /* set key_cache_hash.default_value = dflt_key_cache */
6924   multi_keycache_init();
6925 
6926   /* Set directory paths */
6927   mysql_real_data_home_len=
6928     strmake(mysql_real_data_home, get_relative_path(MYSQL_DATADIR),
6929             sizeof(mysql_real_data_home)-1) - mysql_real_data_home;
6930   /* Replication parameters */
6931   master_info_file= (char*) "master.info",
6932     relay_log_info_file= (char*) "relay-log.info";
6933   report_user= report_password = report_host= 0;	/* TO BE DELETED */
6934   opt_relay_logname= opt_relaylog_index_name= 0;
6935 
6936   /* Variables in libraries */
6937   charsets_dir= 0;
6938   default_character_set_name= (char*) MYSQL_DEFAULT_CHARSET_NAME;
6939   default_collation_name= compiled_default_collation_name;
6940   character_set_filesystem_name= (char*) "binary";
6941   lc_messages= (char*) "en_US";
6942   lc_time_names_name= (char*) "en_US";
6943 
6944   /* Variables that depends on compile options */
6945 #ifndef DBUG_OFF
6946   default_dbug_option=IF_WIN("d:t:i:O,\\mysqld.trace",
6947 			     "d:t:i:o,/tmp/mysqld.trace");
6948 #endif
6949   opt_error_log= IF_WIN(1,0);
6950 #ifdef ENABLED_PROFILING
6951     have_profiling = SHOW_OPTION_YES;
6952 #else
6953     have_profiling = SHOW_OPTION_NO;
6954 #endif
6955 
6956 #ifdef HAVE_OPENSSL
6957   have_ssl=SHOW_OPTION_YES;
6958 #else
6959   have_ssl=SHOW_OPTION_NO;
6960 #endif
6961 #ifdef HAVE_BROKEN_REALPATH
6962   have_symlink=SHOW_OPTION_NO;
6963 #else
6964   have_symlink=SHOW_OPTION_YES;
6965 #endif
6966 #ifdef HAVE_DLOPEN
6967   have_dlopen=SHOW_OPTION_YES;
6968 #else
6969   have_dlopen=SHOW_OPTION_NO;
6970 #endif
6971 #ifdef HAVE_QUERY_CACHE
6972   have_query_cache=SHOW_OPTION_YES;
6973 #else
6974   have_query_cache=SHOW_OPTION_NO;
6975 #endif
6976 #ifdef HAVE_SPATIAL
6977   have_geometry=SHOW_OPTION_YES;
6978 #else
6979   have_geometry=SHOW_OPTION_NO;
6980 #endif
6981 #ifdef HAVE_RTREE_KEYS
6982   have_rtree_keys=SHOW_OPTION_YES;
6983 #else
6984   have_rtree_keys=SHOW_OPTION_NO;
6985 #endif
6986 #ifdef HAVE_CRYPT
6987   have_crypt=SHOW_OPTION_YES;
6988 #else
6989   have_crypt=SHOW_OPTION_NO;
6990 #endif
6991 #ifdef HAVE_COMPRESS
6992   have_compress= SHOW_OPTION_YES;
6993 #else
6994   have_compress= SHOW_OPTION_NO;
6995 #endif
6996 #ifdef HAVE_LIBWRAP
6997   libwrapName= NullS;
6998 #endif
6999 #ifdef HAVE_OPENSSL
7000   des_key_file = 0;
7001 #ifndef EMBEDDED_LIBRARY
7002   ssl_acceptor_fd= 0;
7003 #endif /* ! EMBEDDED_LIBRARY */
7004 #endif /* HAVE_OPENSSL */
7005 #ifdef HAVE_SMEM
7006   shared_memory_base_name= default_shared_memory_base_name;
7007 #endif
7008 
7009 #if defined(__WIN__)
7010   /* Allow Win32 users to move MySQL anywhere */
7011   {
7012     char prg_dev[LIBLEN];
7013     char executing_path_name[LIBLEN];
7014     if (!test_if_hard_path(my_progname))
7015     {
7016       // we don't want to use GetModuleFileName inside of my_path since
7017       // my_path is a generic path dereferencing function and here we care
7018       // only about the executing binary.
7019       GetModuleFileName(NULL, executing_path_name, sizeof(executing_path_name));
7020       my_path(prg_dev, executing_path_name, NULL);
7021     }
7022     else
7023       my_path(prg_dev, my_progname, "mysql/bin");
7024     strcat(prg_dev,"/../");			// Remove 'bin' to get base dir
7025     cleanup_dirname(mysql_home,prg_dev);
7026   }
7027 #else
7028   const char *tmpenv;
7029   if (!(tmpenv = getenv("MY_BASEDIR_VERSION")))
7030     tmpenv = DEFAULT_MYSQL_HOME;
7031   (void) strmake(mysql_home, tmpenv, sizeof(mysql_home)-1);
7032 #endif
7033   return 0;
7034 }
7035 
7036 my_bool
mysqld_get_one_option(int optid,const struct my_option * opt,char * argument)7037 mysqld_get_one_option(int optid,
7038                       const struct my_option *opt __attribute__((unused)),
7039                       char *argument)
7040 {
7041   switch(optid) {
7042   case '#':
7043 #ifndef DBUG_OFF
7044     DBUG_SET_INITIAL(argument ? argument : default_dbug_option);
7045 #endif
7046     opt_endinfo=1;				/* unireg: memory allocation */
7047     break;
7048   case 'a':
7049     global_system_variables.sql_mode= MODE_ANSI;
7050     global_system_variables.tx_isolation= ISO_SERIALIZABLE;
7051     break;
7052   case 'b':
7053     strmake(mysql_home,argument,sizeof(mysql_home)-1);
7054     break;
7055   case 'C':
7056     if (default_collation_name == compiled_default_collation_name)
7057       default_collation_name= 0;
7058     break;
7059   case 'l':
7060     WARN_DEPRECATED(NULL, 7, 0, "--log", "'--general-log'/'--general-log-file'");
7061     opt_log=1;
7062     break;
7063   case 'h':
7064     strmake(mysql_real_data_home,argument, sizeof(mysql_real_data_home)-1);
7065     /* Correct pointer set by my_getopt (for embedded library) */
7066     mysql_real_data_home_ptr= mysql_real_data_home;
7067     break;
7068   case 'u':
7069     if (!mysqld_user || !strcmp(mysqld_user, argument))
7070       mysqld_user= argument;
7071     else
7072       sql_print_warning("Ignoring user change to '%s' because the user was set to '%s' earlier on the command line\n", argument, mysqld_user);
7073     break;
7074   case 'L':
7075     strmake(lc_messages_dir, argument, sizeof(lc_messages_dir)-1);
7076     lc_messages_dir_ptr= lc_messages_dir;
7077     break;
7078   case OPT_BINLOG_FORMAT:
7079     binlog_format_used= true;
7080     break;
7081 #include <sslopt-case.h>
7082 #ifndef EMBEDDED_LIBRARY
7083   case 'V':
7084     print_version();
7085     exit(0);
7086 #endif /*EMBEDDED_LIBRARY*/
7087   case 'W':
7088     if (!argument)
7089       global_system_variables.log_warnings++;
7090     else if (argument == disabled_my_option)
7091       global_system_variables.log_warnings= 0L;
7092     else
7093       global_system_variables.log_warnings= atoi(argument);
7094     break;
7095   case 'T':
7096     test_flags= argument ? (uint) atoi(argument) : 0;
7097     opt_endinfo=1;
7098     break;
7099   case OPT_THREAD_CONCURRENCY:
7100     WARN_DEPRECATED_NO_REPLACEMENT(NULL, "THREAD_CONCURRENCY");
7101     break;
7102   case (int) OPT_ISAM_LOG:
7103     opt_myisam_log=1;
7104     break;
7105   case (int) OPT_BIN_LOG:
7106     opt_bin_log= test(argument != disabled_my_option);
7107     break;
7108 #ifdef HAVE_REPLICATION
7109   case (int)OPT_REPLICATE_IGNORE_DB:
7110   {
7111     rpl_filter->add_ignore_db(argument);
7112     break;
7113   }
7114   case (int)OPT_REPLICATE_DO_DB:
7115   {
7116     rpl_filter->add_do_db(argument);
7117     break;
7118   }
7119   case (int)OPT_REPLICATE_REWRITE_DB:
7120   {
7121     char* key = argument,*p, *val;
7122 
7123     if (!(p= strstr(argument, "->")))
7124     {
7125       sql_print_error("Bad syntax in replicate-rewrite-db - missing '->'!\n");
7126       return 1;
7127     }
7128     val= p--;
7129     while (my_isspace(mysqld_charset, *p) && p > argument)
7130       *p-- = 0;
7131     if (p == argument)
7132     {
7133       sql_print_error("Bad syntax in replicate-rewrite-db - empty FROM db!\n");
7134       return 1;
7135     }
7136     *val= 0;
7137     val+= 2;
7138     while (*val && my_isspace(mysqld_charset, *val))
7139       val++;
7140     if (!*val)
7141     {
7142       sql_print_error("Bad syntax in replicate-rewrite-db - empty TO db!\n");
7143       return 1;
7144     }
7145 
7146     rpl_filter->add_db_rewrite(key, val);
7147     break;
7148   }
7149 
7150   case (int)OPT_BINLOG_IGNORE_DB:
7151   {
7152     binlog_filter->add_ignore_db(argument);
7153     break;
7154   }
7155   case (int)OPT_BINLOG_DO_DB:
7156   {
7157     binlog_filter->add_do_db(argument);
7158     break;
7159   }
7160   case (int)OPT_REPLICATE_DO_TABLE:
7161   {
7162     if (rpl_filter->add_do_table(argument))
7163     {
7164       sql_print_error("Could not add do table rule '%s'!\n", argument);
7165       return 1;
7166     }
7167     break;
7168   }
7169   case (int)OPT_REPLICATE_WILD_DO_TABLE:
7170   {
7171     if (rpl_filter->add_wild_do_table(argument))
7172     {
7173       sql_print_error("Could not add do table rule '%s'!\n", argument);
7174       return 1;
7175     }
7176     break;
7177   }
7178   case (int)OPT_REPLICATE_WILD_IGNORE_TABLE:
7179   {
7180     if (rpl_filter->add_wild_ignore_table(argument))
7181     {
7182       sql_print_error("Could not add ignore table rule '%s'!\n", argument);
7183       return 1;
7184     }
7185     break;
7186   }
7187   case (int)OPT_REPLICATE_IGNORE_TABLE:
7188   {
7189     if (rpl_filter->add_ignore_table(argument))
7190     {
7191       sql_print_error("Could not add ignore table rule '%s'!\n", argument);
7192       return 1;
7193     }
7194     break;
7195   }
7196 #endif /* HAVE_REPLICATION */
7197   case (int) OPT_SLOW_QUERY_LOG:
7198     WARN_DEPRECATED(NULL, 7, 0, "--log-slow-queries", "'--slow-query-log'/'--slow-query-log-file'");
7199     opt_slow_log= 1;
7200     break;
7201   case (int) OPT_SKIP_NEW:
7202     opt_specialflag|= SPECIAL_NO_NEW_FUNC;
7203     delay_key_write_options= DELAY_KEY_WRITE_NONE;
7204     myisam_concurrent_insert=0;
7205     myisam_recover_options= HA_RECOVER_OFF;
7206     sp_automatic_privileges=0;
7207     my_use_symdir=0;
7208     ha_open_options&= ~(HA_OPEN_ABORT_IF_CRASHED | HA_OPEN_DELAY_KEY_WRITE);
7209 #ifdef HAVE_QUERY_CACHE
7210     query_cache_size=0;
7211 #endif
7212     break;
7213   case (int) OPT_SAFE:
7214     opt_specialflag|= SPECIAL_SAFE_MODE;
7215     delay_key_write_options= DELAY_KEY_WRITE_NONE;
7216     myisam_recover_options= HA_RECOVER_DEFAULT;
7217     ha_open_options&= ~(HA_OPEN_DELAY_KEY_WRITE);
7218     sql_print_warning("The syntax '--safe-mode' is deprecated and will be "
7219                       "removed in a future release.");
7220     break;
7221   case (int) OPT_SKIP_PRIOR:
7222     opt_specialflag|= SPECIAL_NO_PRIOR;
7223     sql_print_warning("The --skip-thread-priority startup option is deprecated "
7224                       "and will be removed in MySQL 7.0. This option has no effect "
7225                       "as the implied behavior is already the default.");
7226     break;
7227   case (int) OPT_SKIP_HOST_CACHE:
7228     opt_specialflag|= SPECIAL_NO_HOST_CACHE;
7229     break;
7230   case (int) OPT_SKIP_RESOLVE:
7231     opt_skip_name_resolve= 1;
7232     opt_specialflag|=SPECIAL_NO_RESOLVE;
7233     break;
7234   case (int) OPT_WANT_CORE:
7235     test_flags |= TEST_CORE_ON_SIGNAL;
7236     break;
7237   case (int) OPT_SKIP_STACK_TRACE:
7238     test_flags|=TEST_NO_STACKTRACE;
7239     break;
7240   case OPT_CONSOLE:
7241     if (opt_console)
7242       opt_error_log= 0;			// Force logs to stdout
7243     break;
7244   case OPT_BOOTSTRAP:
7245     opt_noacl=opt_bootstrap=1;
7246     break;
7247   case OPT_SERVER_ID:
7248     server_id_supplied = 1;
7249     break;
7250   case OPT_ONE_THREAD:
7251     thread_handling= SCHEDULER_ONE_THREAD_PER_CONNECTION;
7252     break;
7253   case OPT_LOWER_CASE_TABLE_NAMES:
7254     lower_case_table_names_used= 1;
7255     break;
7256 #if defined(ENABLED_DEBUG_SYNC)
7257   case OPT_DEBUG_SYNC_TIMEOUT:
7258     /*
7259       Debug Sync Facility. See debug_sync.cc.
7260       Default timeout for WAIT_FOR action.
7261       Default value is zero (facility disabled).
7262       If option is given without an argument, supply a non-zero value.
7263     */
7264     if (!argument)
7265     {
7266       /* purecov: begin tested */
7267       opt_debug_sync_timeout= DEBUG_SYNC_DEFAULT_WAIT_TIMEOUT;
7268       /* purecov: end */
7269     }
7270     break;
7271 #endif /* defined(ENABLED_DEBUG_SYNC) */
7272   case OPT_ENGINE_CONDITION_PUSHDOWN:
7273     /*
7274       The last of --engine-condition-pushdown and --optimizer_switch on
7275       command line wins (see get_options().
7276     */
7277     if (global_system_variables.engine_condition_pushdown)
7278       global_system_variables.optimizer_switch|=
7279         OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN;
7280     else
7281       global_system_variables.optimizer_switch&=
7282         ~OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN;
7283     break;
7284   case OPT_LOG_ERROR:
7285     /*
7286       "No --log-error" == "write errors to stderr",
7287       "--log-error without argument" == "write errors to a file".
7288     */
7289     if (argument == NULL) /* no argument */
7290       log_error_file_ptr= const_cast<char*>("");
7291     break;
7292   case OPT_MAX_LONG_DATA_SIZE:
7293     max_long_data_size_used= true;
7294     WARN_DEPRECATED(NULL, 5, 6, "--max_long_data_size", "'--max_allowed_packet'");
7295     break;
7296   }
7297   return 0;
7298 }
7299 
7300 
7301 /** Handle arguments for multiple key caches. */
7302 
7303 C_MODE_START
7304 
7305 static void*
mysql_getopt_value(const char * keyname,uint key_length,const struct my_option * option,int * error)7306 mysql_getopt_value(const char *keyname, uint key_length,
7307 		   const struct my_option *option, int *error)
7308 {
7309   if (error)
7310     *error= 0;
7311   switch (option->id) {
7312   case OPT_KEY_BUFFER_SIZE:
7313   case OPT_KEY_CACHE_BLOCK_SIZE:
7314   case OPT_KEY_CACHE_DIVISION_LIMIT:
7315   case OPT_KEY_CACHE_AGE_THRESHOLD:
7316   {
7317     KEY_CACHE *key_cache;
7318     if (!(key_cache= get_or_create_key_cache(keyname, key_length)))
7319     {
7320       if (error)
7321         *error= EXIT_OUT_OF_MEMORY;
7322       return 0;
7323     }
7324     switch (option->id) {
7325     case OPT_KEY_BUFFER_SIZE:
7326       return &key_cache->param_buff_size;
7327     case OPT_KEY_CACHE_BLOCK_SIZE:
7328       return &key_cache->param_block_size;
7329     case OPT_KEY_CACHE_DIVISION_LIMIT:
7330       return &key_cache->param_division_limit;
7331     case OPT_KEY_CACHE_AGE_THRESHOLD:
7332       return &key_cache->param_age_threshold;
7333     }
7334   }
7335   }
7336   return option->value;
7337 }
7338 
option_error_reporter(enum loglevel level,const char * format,...)7339 static void option_error_reporter(enum loglevel level, const char *format, ...)
7340 {
7341   va_list args;
7342   va_start(args, format);
7343 
7344   /* Don't print warnings for --loose options during bootstrap */
7345   if (level == ERROR_LEVEL || !opt_bootstrap ||
7346       global_system_variables.log_warnings)
7347   {
7348     vprint_msg_to_log(level, format, args);
7349   }
7350   va_end(args);
7351 }
7352 
7353 C_MODE_END
7354 
7355 /**
7356   Get server options from the command line,
7357   and perform related server initializations.
7358   @param [in, out] argc_ptr       command line options (count)
7359   @param [in, out] argv_ptr       command line options (values)
7360   @return 0 on success
7361 
7362   @todo
7363   - FIXME add EXIT_TOO_MANY_ARGUMENTS to "mysys_err.h" and return that code?
7364 */
get_options(int * argc_ptr,char *** argv_ptr)7365 static int get_options(int *argc_ptr, char ***argv_ptr)
7366 {
7367   int ho_error;
7368 
7369   my_getopt_register_get_addr(mysql_getopt_value);
7370   my_getopt_error_reporter= option_error_reporter;
7371 
7372   /* prepare all_options array */
7373   my_init_dynamic_array(&all_options, sizeof(my_option),
7374                         array_elements(my_long_options),
7375                         array_elements(my_long_options)/4);
7376   for (my_option *opt= my_long_options;
7377        opt < my_long_options + array_elements(my_long_options) - 1;
7378        opt++)
7379     insert_dynamic(&all_options, (uchar*) opt);
7380   sys_var_add_options(&all_options, sys_var::PARSE_NORMAL);
7381   add_terminator(&all_options);
7382 
7383   /* Skip unknown options so that they may be processed later by plugins */
7384   my_getopt_skip_unknown= TRUE;
7385 
7386   if ((ho_error= handle_options(argc_ptr, argv_ptr, (my_option*)(all_options.buffer),
7387                                 mysqld_get_one_option)))
7388     return ho_error;
7389 
7390   if (!opt_help)
7391     delete_dynamic(&all_options);
7392 
7393   /* Add back the program name handle_options removes */
7394   (*argc_ptr)++;
7395   (*argv_ptr)--;
7396 
7397   /*
7398     Options have been parsed. Now some of them need additional special
7399     handling, like custom value checking, checking of incompatibilites
7400     between options, setting of multiple variables, etc.
7401     Do them here.
7402   */
7403 
7404   if ((opt_log_slow_admin_statements || opt_log_queries_not_using_indexes ||
7405        opt_log_slow_slave_statements) &&
7406       !opt_slow_log)
7407     sql_print_warning("options --log-slow-admin-statements, --log-queries-not-using-indexes and --log-slow-slave-statements have no effect if --log_slow_queries is not set");
7408   if (global_system_variables.net_buffer_length >
7409       global_system_variables.max_allowed_packet)
7410   {
7411     sql_print_warning("net_buffer_length (%lu) is set to be larger "
7412                       "than max_allowed_packet (%lu). Please rectify.",
7413                       global_system_variables.net_buffer_length,
7414                       global_system_variables.max_allowed_packet);
7415   }
7416 
7417   if (log_error_file_ptr != disabled_my_option)
7418     opt_error_log= 1;
7419   else
7420     log_error_file_ptr= const_cast<char*>("");
7421 
7422   opt_init_connect.length=strlen(opt_init_connect.str);
7423   opt_init_slave.length=strlen(opt_init_slave.str);
7424 
7425   if (global_system_variables.low_priority_updates)
7426     thr_upgraded_concurrent_insert_lock= TL_WRITE_LOW_PRIORITY;
7427 
7428   if (ft_boolean_check_syntax_string((uchar*) ft_boolean_syntax))
7429   {
7430     sql_print_error("Invalid ft-boolean-syntax string: %s\n",
7431                     ft_boolean_syntax);
7432     return 1;
7433   }
7434 
7435   if (opt_disable_networking)
7436     mysqld_port= 0;
7437 
7438   if (opt_skip_show_db)
7439     opt_specialflag|= SPECIAL_SKIP_SHOW_DB;
7440 
7441   if (myisam_flush)
7442     flush_time= 0;
7443 
7444 #ifdef HAVE_REPLICATION
7445   if (opt_slave_skip_errors)
7446     init_slave_skip_errors(opt_slave_skip_errors);
7447 #endif
7448 
7449   if (global_system_variables.max_join_size == HA_POS_ERROR)
7450     global_system_variables.option_bits|= OPTION_BIG_SELECTS;
7451   else
7452     global_system_variables.option_bits&= ~OPTION_BIG_SELECTS;
7453 
7454   // Synchronize @@global.autocommit on --autocommit
7455   const ulonglong turn_bit_on= opt_autocommit ?
7456     OPTION_AUTOCOMMIT : OPTION_NOT_AUTOCOMMIT;
7457   global_system_variables.option_bits=
7458     (global_system_variables.option_bits &
7459      ~(OPTION_NOT_AUTOCOMMIT | OPTION_AUTOCOMMIT)) | turn_bit_on;
7460 
7461   global_system_variables.sql_mode=
7462     expand_sql_mode(global_system_variables.sql_mode);
7463 #if defined(HAVE_BROKEN_REALPATH)
7464   my_use_symdir=0;
7465   my_disable_symlinks=1;
7466   have_symlink=SHOW_OPTION_NO;
7467 #else
7468   if (!my_use_symdir)
7469   {
7470     my_disable_symlinks=1;
7471     have_symlink=SHOW_OPTION_DISABLED;
7472   }
7473 #endif
7474   if (opt_debugging)
7475   {
7476     /* Allow break with SIGINT, no core or stack trace */
7477     test_flags|= TEST_SIGINT | TEST_NO_STACKTRACE;
7478     test_flags&= ~TEST_CORE_ON_SIGNAL;
7479   }
7480   /* Set global MyISAM variables from delay_key_write_options */
7481   fix_delay_key_write(0, 0, OPT_GLOBAL);
7482 
7483 #ifndef EMBEDDED_LIBRARY
7484   if (mysqld_chroot)
7485     set_root(mysqld_chroot);
7486 #else
7487   thread_handling = SCHEDULER_NO_THREADS;
7488   max_allowed_packet= global_system_variables.max_allowed_packet;
7489   net_buffer_length= global_system_variables.net_buffer_length;
7490 #endif
7491   if (fix_paths())
7492     return 1;
7493 
7494   /*
7495     Set some global variables from the global_system_variables
7496     In most cases the global variables will not be used
7497   */
7498   my_disable_locking= myisam_single_user= test(opt_external_locking == 0);
7499   my_default_record_cache_size=global_system_variables.read_buff_size;
7500 
7501   global_system_variables.long_query_time= (ulonglong)
7502     (global_system_variables.long_query_time_double * 1e6);
7503 
7504   if (opt_short_log_format)
7505     opt_specialflag|= SPECIAL_SHORT_LOG_FORMAT;
7506 
7507   if (init_global_datetime_format(MYSQL_TIMESTAMP_DATE,
7508                                   &global_date_format) ||
7509       init_global_datetime_format(MYSQL_TIMESTAMP_TIME,
7510                                   &global_time_format) ||
7511       init_global_datetime_format(MYSQL_TIMESTAMP_DATETIME,
7512                                   &global_datetime_format))
7513     return 1;
7514 
7515 #ifdef EMBEDDED_LIBRARY
7516   one_thread_scheduler();
7517 #else
7518   if (thread_handling <= SCHEDULER_ONE_THREAD_PER_CONNECTION)
7519     one_thread_per_connection_scheduler();
7520   else                  /* thread_handling == SCHEDULER_NO_THREADS) */
7521     one_thread_scheduler();
7522 #endif
7523 
7524   global_system_variables.engine_condition_pushdown=
7525     test(global_system_variables.optimizer_switch &
7526          OPTIMIZER_SWITCH_ENGINE_CONDITION_PUSHDOWN);
7527 
7528   opt_readonly= read_only;
7529 
7530   /*
7531     If max_long_data_size is not specified explicitly use
7532     value of max_allowed_packet.
7533   */
7534   if (!max_long_data_size_used)
7535     max_long_data_size= global_system_variables.max_allowed_packet;
7536 
7537   return 0;
7538 }
7539 
7540 
7541 /*
7542   Create version name for running mysqld version
7543   We automaticly add suffixes -debug, -embedded and -log to the version
7544   name to make the version more descriptive.
7545   (MYSQL_SERVER_SUFFIX is set by the compilation environment)
7546 */
7547 
set_server_version(void)7548 static void set_server_version(void)
7549 {
7550   char *end= strxmov(server_version, MYSQL_SERVER_VERSION,
7551                      MYSQL_SERVER_SUFFIX_STR, NullS);
7552 #ifdef EMBEDDED_LIBRARY
7553   end= strmov(end, "-embedded");
7554 #endif
7555 #ifndef DBUG_OFF
7556   if (!strstr(MYSQL_SERVER_SUFFIX_STR, "-debug"))
7557     end= strmov(end, "-debug");
7558 #endif
7559   if (opt_log || opt_slow_log || opt_bin_log)
7560     strmov(end, "-log");                        // This may slow down system
7561 }
7562 
7563 
get_relative_path(const char * path)7564 static char *get_relative_path(const char *path)
7565 {
7566   if (test_if_hard_path(path) &&
7567       is_prefix(path,DEFAULT_MYSQL_HOME) &&
7568       strcmp(DEFAULT_MYSQL_HOME,FN_ROOTDIR))
7569   {
7570     path+=(uint) strlen(DEFAULT_MYSQL_HOME);
7571     while (*path == FN_LIBCHAR || *path == FN_LIBCHAR2)
7572       path++;
7573   }
7574   return (char*) path;
7575 }
7576 
7577 
7578 /**
7579   Fix filename and replace extension where 'dir' is relative to
7580   mysql_real_data_home.
7581   @return
7582     1 if len(path) > FN_REFLEN
7583 */
7584 
7585 bool
fn_format_relative_to_data_home(char * to,const char * name,const char * dir,const char * extension)7586 fn_format_relative_to_data_home(char * to, const char *name,
7587 				const char *dir, const char *extension)
7588 {
7589   char tmp_path[FN_REFLEN];
7590   if (!test_if_hard_path(dir))
7591   {
7592     strxnmov(tmp_path,sizeof(tmp_path)-1, mysql_real_data_home,
7593 	     dir, NullS);
7594     dir=tmp_path;
7595   }
7596   return !fn_format(to, name, dir, extension,
7597 		    MY_APPEND_EXT | MY_UNPACK_FILENAME | MY_SAFE_PATH);
7598 }
7599 
7600 
7601 /**
7602   Test a file path to determine if the path is compatible with the secure file
7603   path restriction.
7604 
7605   @param path null terminated character string
7606 
7607   @return
7608     @retval TRUE The path is secure
7609     @retval FALSE The path isn't secure
7610 */
7611 
is_secure_file_path(char * path)7612 bool is_secure_file_path(char *path)
7613 {
7614   char buff1[FN_REFLEN], buff2[FN_REFLEN];
7615   size_t opt_secure_file_priv_len;
7616   /*
7617     All paths are secure if opt_secure_file_priv is 0
7618   */
7619   if (!opt_secure_file_priv[0])
7620     return TRUE;
7621 
7622   opt_secure_file_priv_len= strlen(opt_secure_file_priv);
7623 
7624   if (strlen(path) >= FN_REFLEN)
7625     return FALSE;
7626 
7627   if (!my_strcasecmp(system_charset_info, opt_secure_file_priv, "NULL"))
7628     return FALSE;
7629 
7630   if (my_realpath(buff1, path, 0))
7631   {
7632     /*
7633       The supplied file path might have been a file and not a directory.
7634     */
7635     int length= (int)dirname_length(path);
7636     if (length >= FN_REFLEN)
7637       return FALSE;
7638     memcpy(buff2, path, length);
7639     buff2[length]= '\0';
7640     if (length == 0 || my_realpath(buff1, buff2, 0))
7641       return FALSE;
7642   }
7643   convert_dirname(buff2, buff1, NullS);
7644   if (!lower_case_file_system)
7645   {
7646     if (strncmp(opt_secure_file_priv, buff2, opt_secure_file_priv_len))
7647       return FALSE;
7648   }
7649   else
7650   {
7651     if (files_charset_info->coll->strnncoll(files_charset_info,
7652                                             (uchar *) buff2, strlen(buff2),
7653                                             (uchar *) opt_secure_file_priv,
7654                                             opt_secure_file_priv_len,
7655                                             TRUE))
7656       return FALSE;
7657   }
7658   return TRUE;
7659 }
7660 
7661 
7662 /**
7663   check_secure_file_priv_path : Checks path specified through
7664   --secure-file-priv and raises warning in following cases:
7665   1. If path is empty string or NULL and mysqld is not running
7666      with --bootstrap mode.
7667   2. If path can access data directory
7668   3. If path points to a directory which is accessible by
7669      all OS users (non-Windows build only)
7670 
7671   It throws error in following cases:
7672 
7673   1. If path normalization fails
7674   2. If it can not get stats of the directory
7675 
7676   @params NONE
7677 
7678   Assumptions :
7679   1. Data directory path has been normalized
7680   2. opt_secure_file_priv has been normalized unless it is set
7681      to "NULL".
7682 
7683   @returns Status of validation
7684     @retval true : Validation is successful with/without warnings
7685     @retval false : Validation failed. Error is raised.
7686 */
7687 
check_secure_file_priv_path()7688 bool check_secure_file_priv_path()
7689 {
7690   char datadir_buffer[FN_REFLEN+1]={0};
7691   char plugindir_buffer[FN_REFLEN+1]={0};
7692   char whichdir[20]= {0};
7693   size_t opt_plugindir_len= 0;
7694   size_t opt_datadir_len= 0;
7695   size_t opt_secure_file_priv_len= 0;
7696   bool warn= false;
7697   bool case_insensitive_fs;
7698 #ifndef _WIN32
7699   MY_STAT dir_stat;
7700 #endif
7701 
7702   if (!opt_secure_file_priv[0])
7703   {
7704     if (opt_bootstrap)
7705     {
7706       /*
7707         Do not impose --secure-file-priv restriction
7708         in --bootstrap mode
7709       */
7710       sql_print_information("Ignoring --secure-file-priv value as server is "
7711                             "running with --bootstrap.");
7712     }
7713     else
7714     {
7715       sql_print_warning("Insecure configuration for --secure-file-priv: "
7716                         "Current value does not restrict location of generated "
7717                         "files. Consider setting it to a valid, "
7718                         "non-empty path.");
7719     }
7720     return true;
7721   }
7722 
7723   /*
7724     Setting --secure-file-priv to NULL would disable
7725     reading/writing from/to file
7726   */
7727   if(!my_strcasecmp(system_charset_info, opt_secure_file_priv, "NULL"))
7728   {
7729     sql_print_information("--secure-file-priv is set to NULL. "
7730                           "Operations related to importing and exporting "
7731                           "data are disabled");
7732     return true;
7733   }
7734 
7735   /*
7736     Check if --secure-file-priv can access data directory
7737   */
7738   opt_secure_file_priv_len= strlen(opt_secure_file_priv);
7739 
7740   /*
7741     Adds dir seperator at the end.
7742     This is required in subsequent comparison
7743   */
7744   convert_dirname(datadir_buffer, mysql_unpacked_real_data_home, NullS);
7745   opt_datadir_len= strlen(datadir_buffer);
7746 
7747   case_insensitive_fs=
7748     (test_if_case_insensitive(datadir_buffer) == 1);
7749 
7750   if (!case_insensitive_fs)
7751   {
7752     if (!strncmp(datadir_buffer, opt_secure_file_priv,
7753           opt_datadir_len < opt_secure_file_priv_len ?
7754           opt_datadir_len : opt_secure_file_priv_len))
7755     {
7756       warn= true;
7757       strcpy(whichdir, "Data directory");
7758     }
7759   }
7760   else
7761   {
7762     if (!files_charset_info->coll->strnncoll(files_charset_info,
7763           (uchar *) datadir_buffer,
7764           opt_datadir_len,
7765           (uchar *) opt_secure_file_priv,
7766           opt_secure_file_priv_len,
7767           TRUE))
7768     {
7769       warn= true;
7770       strcpy(whichdir, "Data directory");
7771     }
7772   }
7773 
7774   /*
7775     Don't bother comparing --secure-file-priv with --plugin-dir
7776     if we already have a match against --datadir or
7777     --plugin-dir is not pointing to a valid directory.
7778   */
7779   if (!warn && !my_realpath(plugindir_buffer, opt_plugin_dir, 0))
7780   {
7781     convert_dirname(plugindir_buffer, plugindir_buffer, NullS);
7782     opt_plugindir_len= strlen(plugindir_buffer);
7783 
7784     if (!case_insensitive_fs)
7785     {
7786       if (!strncmp(plugindir_buffer, opt_secure_file_priv,
7787           opt_plugindir_len < opt_secure_file_priv_len ?
7788           opt_plugindir_len : opt_secure_file_priv_len))
7789       {
7790         warn= true;
7791         strcpy(whichdir, "Plugin directory");
7792       }
7793     }
7794     else
7795     {
7796       if (!files_charset_info->coll->strnncoll(files_charset_info,
7797           (uchar *) plugindir_buffer,
7798           opt_plugindir_len,
7799           (uchar *) opt_secure_file_priv,
7800           opt_secure_file_priv_len,
7801           TRUE))
7802       {
7803         warn= true;
7804         strcpy(whichdir, "Plugin directory");
7805       }
7806     }
7807   }
7808 
7809 
7810   if (warn)
7811     sql_print_warning("Insecure configuration for --secure-file-priv: "
7812                       "%s is accessible through "
7813                       "--secure-file-priv. Consider choosing a different "
7814                       "directory.", whichdir);
7815 
7816 #ifndef _WIN32
7817   /*
7818      Check for --secure-file-priv directory's permission
7819   */
7820   if (!(my_stat(opt_secure_file_priv, &dir_stat, MYF(0))))
7821   {
7822     sql_print_error("Failed to get stat for directory pointed out "
7823                     "by --secure-file-priv");
7824     return false;
7825   }
7826 
7827   if (dir_stat.st_mode & S_IRWXO)
7828     sql_print_warning("Insecure configuration for --secure-file-priv: "
7829                       "Location is accessible to all OS users. "
7830                       "Consider choosing a different directory.");
7831 #endif
7832   return true;
7833 }
7834 
7835 
fix_paths(void)7836 static int fix_paths(void)
7837 {
7838   char buff[FN_REFLEN],*pos;
7839   bool secure_file_priv_nonempty= false;
7840   convert_dirname(mysql_home,mysql_home,NullS);
7841   /* Resolve symlinks to allow 'mysql_home' to be a relative symlink */
7842   my_realpath(mysql_home,mysql_home,MYF(0));
7843   /* Ensure that mysql_home ends in FN_LIBCHAR */
7844   pos=strend(mysql_home);
7845   if (pos[-1] != FN_LIBCHAR)
7846   {
7847     pos[0]= FN_LIBCHAR;
7848     pos[1]= 0;
7849   }
7850   convert_dirname(lc_messages_dir, lc_messages_dir, NullS);
7851   convert_dirname(mysql_real_data_home,mysql_real_data_home,NullS);
7852   (void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir
7853   (void) my_load_path(mysql_real_data_home,mysql_real_data_home,mysql_home);
7854   (void) my_load_path(pidfile_name, pidfile_name_ptr, mysql_real_data_home);
7855 
7856   convert_dirname(opt_plugin_dir, opt_plugin_dir_ptr ? opt_plugin_dir_ptr :
7857                                   get_relative_path(PLUGINDIR), NullS);
7858   (void) my_load_path(opt_plugin_dir, opt_plugin_dir, mysql_home);
7859   opt_plugin_dir_ptr= opt_plugin_dir;
7860 
7861   my_realpath(mysql_unpacked_real_data_home, mysql_real_data_home, MYF(0));
7862   mysql_unpacked_real_data_home_len=
7863     (int) strlen(mysql_unpacked_real_data_home);
7864   if (mysql_unpacked_real_data_home[mysql_unpacked_real_data_home_len-1] == FN_LIBCHAR)
7865     --mysql_unpacked_real_data_home_len;
7866 
7867   char *sharedir=get_relative_path(SHAREDIR);
7868   if (test_if_hard_path(sharedir))
7869     strmake(buff,sharedir,sizeof(buff)-1);		/* purecov: tested */
7870   else
7871     strxnmov(buff,sizeof(buff)-1,mysql_home,sharedir,NullS);
7872   convert_dirname(buff,buff,NullS);
7873   (void) my_load_path(lc_messages_dir, lc_messages_dir, buff);
7874 
7875   /* If --character-sets-dir isn't given, use shared library dir */
7876   if (charsets_dir)
7877     strmake(mysql_charsets_dir, charsets_dir, sizeof(mysql_charsets_dir)-1);
7878   else
7879     strxnmov(mysql_charsets_dir, sizeof(mysql_charsets_dir)-1, buff,
7880 	     CHARSET_DIR, NullS);
7881   (void) my_load_path(mysql_charsets_dir, mysql_charsets_dir, buff);
7882   convert_dirname(mysql_charsets_dir, mysql_charsets_dir, NullS);
7883   charsets_dir=mysql_charsets_dir;
7884 
7885   if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir))
7886     return 1;
7887   if (!opt_mysql_tmpdir)
7888     opt_mysql_tmpdir= mysql_tmpdir;
7889 #ifdef HAVE_REPLICATION
7890   if (!slave_load_tmpdir)
7891     slave_load_tmpdir= mysql_tmpdir;
7892 #endif /* HAVE_REPLICATION */
7893   /*
7894     Convert the secure-file-priv option to system format, allowing
7895     a quick strcmp to check if read or write is in an allowed dir
7896    */
7897   if (opt_bootstrap)
7898     opt_secure_file_priv= EMPTY_STR.str;
7899   secure_file_priv_nonempty= opt_secure_file_priv[0] ? true : false;
7900 
7901   if (secure_file_priv_nonempty && strlen(opt_secure_file_priv) > FN_REFLEN)
7902   {
7903     sql_print_warning("Value for --secure-file-priv is longer than maximum "
7904                       "limit of %d", FN_REFLEN-1);
7905     return 1;
7906   }
7907 
7908   memset(buff, 0, sizeof(buff));
7909   if (secure_file_priv_nonempty &&
7910       my_strcasecmp(system_charset_info, opt_secure_file_priv, "NULL"))
7911   {
7912     int retval= my_realpath(buff, opt_secure_file_priv, MYF(MY_WME));
7913     if (!retval)
7914     {
7915       convert_dirname(secure_file_real_path, buff, NullS);
7916 #ifdef WIN32
7917       MY_DIR *dir= my_dir(secure_file_real_path, MYF(MY_DONT_SORT+MY_WME));
7918       if (!dir)
7919       {
7920         retval= 1;
7921       }
7922       else
7923       {
7924         my_dirend(dir);
7925       }
7926 #endif
7927     }
7928 
7929     if (retval)
7930     {
7931       char err_buffer[FN_REFLEN];
7932       my_snprintf(err_buffer, FN_REFLEN-1,
7933                   "Failed to access directory for --secure-file-priv."
7934                   " Please make sure that directory exists and is "
7935                   "accessible by MySQL Server. Supplied value : %s",
7936                   opt_secure_file_priv);
7937       err_buffer[FN_REFLEN-1]='\0';
7938       sql_print_error("%s", err_buffer);
7939       return 1;
7940     }
7941     opt_secure_file_priv= secure_file_real_path;
7942   }
7943 
7944   if (!check_secure_file_priv_path())
7945     return 1;
7946 
7947   return 0;
7948 }
7949 
7950 /**
7951   Check if file system used for databases is case insensitive.
7952 
7953   @param dir_name			Directory to test
7954 
7955   @retval
7956     -1  Don't know (Test failed)
7957   @retval
7958     0   File system is case sensitive
7959   @retval
7960     1   File system is case insensitive
7961 */
7962 
test_if_case_insensitive(const char * dir_name)7963 static int test_if_case_insensitive(const char *dir_name)
7964 {
7965   int result= 0;
7966   File file;
7967   char buff[FN_REFLEN], buff2[FN_REFLEN];
7968   MY_STAT stat_info;
7969   DBUG_ENTER("test_if_case_insensitive");
7970 
7971   fn_format(buff, glob_hostname, dir_name, ".lower-test",
7972 	    MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR);
7973   fn_format(buff2, glob_hostname, dir_name, ".LOWER-TEST",
7974 	    MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR);
7975   mysql_file_delete(key_file_casetest, buff2, MYF(0));
7976   if ((file= mysql_file_create(key_file_casetest,
7977                                buff, 0666, O_RDWR, MYF(0))) < 0)
7978   {
7979     sql_print_warning("Can't create test file %s", buff);
7980     DBUG_RETURN(-1);
7981   }
7982   mysql_file_close(file, MYF(0));
7983   if (mysql_file_stat(key_file_casetest, buff2, &stat_info, MYF(0)))
7984     result= 1;					// Can access file
7985   mysql_file_delete(key_file_casetest, buff, MYF(MY_WME));
7986   DBUG_PRINT("exit", ("result: %d", result));
7987   DBUG_RETURN(result);
7988 }
7989 
7990 
7991 #ifndef EMBEDDED_LIBRARY
7992 
7993 /**
7994   Create file to store pid number.
7995 */
create_pid_file()7996 static void create_pid_file()
7997 {
7998   File file;
7999   bool check_parent_path= 1, is_path_accessible= 1;
8000   char pid_filepath[FN_REFLEN], *pos= NULL;
8001   /* Copy pid file name to get pid file path */
8002   strcpy(pid_filepath, pidfile_name);
8003 
8004   /* Iterate through the entire path to check if even one of the sub-dirs
8005      is world-writable */
8006   while (check_parent_path && (pos= strrchr(pid_filepath, FN_LIBCHAR))
8007          && (pos != pid_filepath)) /* shouldn't check root */
8008   {
8009     *pos= '\0';  /* Trim the inner-most dir */
8010     switch (is_file_or_dir_world_writable(pid_filepath))
8011     {
8012       case -2:
8013         is_path_accessible= 0;
8014         break;
8015       case -1:
8016         sql_perror("Can't start server: can't check PID filepath");
8017         exit(1);
8018       case 1:
8019         sql_print_warning("Insecure configuration for --pid-file: Location "
8020                           "'%s' in the path is accessible to all OS users. "
8021                           "Consider choosing a different directory.",
8022                           pid_filepath);
8023         check_parent_path= 0;
8024         break;
8025       case 0:
8026         continue; /* Keep checking the parent dir */
8027     }
8028   }
8029   if (!is_path_accessible)
8030   {
8031     sql_print_warning("Few location(s) are inaccessible while checking PID filepath.");
8032   }
8033   if ((file= mysql_file_create(key_file_pid, pidfile_name, 0664,
8034                                O_WRONLY | O_TRUNC, MYF(MY_WME))) >= 0)
8035   {
8036     char buff[MAX_BIGINT_WIDTH + 1], *end;
8037     end= int10_to_str((long) getpid(), buff, 10);
8038     *end++= '\n';
8039     if (!mysql_file_write(file, (uchar*) buff, (uint) (end-buff),
8040                           MYF(MY_WME | MY_NABP)))
8041     {
8042       mysql_file_close(file, MYF(0));
8043       pid_file_created= true;
8044       return;
8045     }
8046     mysql_file_close(file, MYF(0));
8047   }
8048   sql_perror("Can't start server: can't create PID file");
8049   exit(1);
8050 }
8051 #endif /* EMBEDDED_LIBRARY */
8052 
8053 
8054 /**
8055   Remove the process' pid file.
8056 
8057   @param  flags  file operation flags
8058 */
8059 
delete_pid_file(myf flags)8060 static void delete_pid_file(myf flags)
8061 {
8062 #ifndef EMBEDDED_LIBRARY
8063   File file;
8064   if (opt_bootstrap ||
8065       !pid_file_created ||
8066       !(file= mysql_file_open(key_file_pid, pidfile_name,
8067                               O_RDONLY, flags)))
8068     return;
8069 
8070   /* Make sure that the pid file was created by the same process. */
8071   uchar buff[MAX_BIGINT_WIDTH + 1];
8072   size_t error= mysql_file_read(file, buff, sizeof(buff), flags);
8073   mysql_file_close(file, flags);
8074   buff[sizeof(buff) - 1]= '\0';
8075   if (error != MY_FILE_ERROR &&
8076       atol((char *) buff) == (long) getpid())
8077   {
8078     mysql_file_delete(key_file_pid, pidfile_name, flags);
8079     pid_file_created= false;
8080   }
8081 #endif /* EMBEDDED_LIBRARY */
8082   return;
8083 }
8084 
8085 
8086 /** Clear most status variables. */
refresh_status(THD * thd)8087 void refresh_status(THD *thd)
8088 {
8089   mysql_mutex_lock(&LOCK_status);
8090 
8091   /* Add thread's status variabes to global status */
8092   add_to_status(&global_status_var, &thd->status_var);
8093 
8094   /* Reset thread's status variables */
8095   bzero((uchar*) &thd->status_var, sizeof(thd->status_var));
8096 
8097   /* Reset some global variables */
8098   reset_status_vars();
8099 
8100   /* Reset the counters of all key caches (default and named). */
8101   process_key_caches(reset_key_cache_counters);
8102   flush_status_time= time((time_t*) 0);
8103   mysql_mutex_unlock(&LOCK_status);
8104 
8105   /*
8106     Set max_used_connections to the number of currently open
8107     connections.  Lock LOCK_thread_count out of LOCK_status to avoid
8108     deadlocks.  Status reset becomes not atomic, but status data is
8109     not exact anyway.
8110   */
8111   mysql_mutex_lock(&LOCK_thread_count);
8112   max_used_connections= thread_count-delayed_insert_threads;
8113   mysql_mutex_unlock(&LOCK_thread_count);
8114 }
8115 
8116 
8117 /*****************************************************************************
8118   Instantiate variables for missing storage engines
8119   This section should go away soon
8120 *****************************************************************************/
8121 
8122 /*****************************************************************************
8123   Instantiate templates
8124 *****************************************************************************/
8125 
8126 #ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
8127 /* Used templates */
8128 template class I_List<THD>;
8129 template class I_List_iterator<THD>;
8130 template class I_List<i_string>;
8131 template class I_List<i_string_pair>;
8132 template class I_List<Statement>;
8133 template class I_List_iterator<Statement>;
8134 #endif
8135 
8136 #ifdef HAVE_PSI_INTERFACE
8137 #ifdef HAVE_MMAP
8138 PSI_mutex_key key_PAGE_lock, key_LOCK_sync, key_LOCK_active, key_LOCK_pool;
8139 #endif /* HAVE_MMAP */
8140 
8141 #ifdef HAVE_OPENSSL
8142 PSI_mutex_key key_LOCK_des_key_file;
8143 #endif /* HAVE_OPENSSL */
8144 
8145 PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_prep_xids,
8146   key_delayed_insert_mutex, key_hash_filo_lock, key_LOCK_active_mi,
8147   key_LOCK_connection_count, key_LOCK_crypt, key_LOCK_delayed_create,
8148   key_LOCK_delayed_insert, key_LOCK_delayed_status, key_LOCK_error_log,
8149   key_LOCK_gdl, key_LOCK_global_system_variables,
8150   key_LOCK_manager,
8151   key_LOCK_prepared_stmt_count,
8152   key_LOCK_rpl_status, key_LOCK_server_started, key_LOCK_status,
8153   key_LOCK_system_variables_hash, key_LOCK_table_share, key_LOCK_thd_data,
8154   key_LOCK_user_conn, key_LOCK_uuid_generator, key_LOG_LOCK_log,
8155   key_master_info_data_lock, key_master_info_run_lock,
8156   key_master_info_sleep_lock,
8157   key_mutex_slave_reporting_capability_err_lock, key_relay_log_info_data_lock,
8158   key_relay_log_info_log_space_lock, key_relay_log_info_run_lock,
8159   key_relay_log_info_sleep_lock,
8160   key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data,
8161   key_LOCK_error_messages, key_LOG_INFO_lock, key_LOCK_thread_count,
8162   key_PARTITION_LOCK_auto_inc;
8163 PSI_mutex_key key_LOCK_thd_remove;
8164 PSI_mutex_key key_RELAYLOG_LOCK_index;
8165 PSI_mutex_key key_LOCK_thread_created;
8166 
8167 static PSI_mutex_info all_server_mutexes[]=
8168 {
8169 #ifdef HAVE_MMAP
8170   { &key_PAGE_lock, "PAGE::lock", 0},
8171   { &key_LOCK_sync, "TC_LOG_MMAP::LOCK_sync", 0},
8172   { &key_LOCK_active, "TC_LOG_MMAP::LOCK_active", 0},
8173   { &key_LOCK_pool, "TC_LOG_MMAP::LOCK_pool", 0},
8174 #endif /* HAVE_MMAP */
8175 
8176 #ifdef HAVE_OPENSSL
8177   { &key_LOCK_des_key_file, "LOCK_des_key_file", PSI_FLAG_GLOBAL},
8178 #endif /* HAVE_OPENSSL */
8179 
8180   { &key_BINLOG_LOCK_index, "MYSQL_BIN_LOG::LOCK_index", 0},
8181   { &key_BINLOG_LOCK_prep_xids, "MYSQL_BIN_LOG::LOCK_prep_xids", 0},
8182   { &key_RELAYLOG_LOCK_index, "MYSQL_RELAY_LOG::LOCK_index", 0},
8183   { &key_delayed_insert_mutex, "Delayed_insert::mutex", 0},
8184   { &key_hash_filo_lock, "hash_filo::lock", 0},
8185   { &key_LOCK_active_mi, "LOCK_active_mi", PSI_FLAG_GLOBAL},
8186   { &key_LOCK_connection_count, "LOCK_connection_count", PSI_FLAG_GLOBAL},
8187   { &key_LOCK_crypt, "LOCK_crypt", PSI_FLAG_GLOBAL},
8188   { &key_LOCK_delayed_create, "LOCK_delayed_create", PSI_FLAG_GLOBAL},
8189   { &key_LOCK_delayed_insert, "LOCK_delayed_insert", PSI_FLAG_GLOBAL},
8190   { &key_LOCK_delayed_status, "LOCK_delayed_status", PSI_FLAG_GLOBAL},
8191   { &key_LOCK_error_log, "LOCK_error_log", PSI_FLAG_GLOBAL},
8192   { &key_LOCK_gdl, "LOCK_gdl", PSI_FLAG_GLOBAL},
8193   { &key_LOCK_global_system_variables, "LOCK_global_system_variables", PSI_FLAG_GLOBAL},
8194   { &key_LOCK_manager, "LOCK_manager", PSI_FLAG_GLOBAL},
8195   { &key_LOCK_prepared_stmt_count, "LOCK_prepared_stmt_count", PSI_FLAG_GLOBAL},
8196   { &key_LOCK_rpl_status, "LOCK_rpl_status", PSI_FLAG_GLOBAL},
8197   { &key_LOCK_server_started, "LOCK_server_started", PSI_FLAG_GLOBAL},
8198   { &key_LOCK_status, "LOCK_status", PSI_FLAG_GLOBAL},
8199   { &key_LOCK_system_variables_hash, "LOCK_system_variables_hash", PSI_FLAG_GLOBAL},
8200   { &key_LOCK_table_share, "LOCK_table_share", PSI_FLAG_GLOBAL},
8201   { &key_LOCK_thd_data, "THD::LOCK_thd_data", 0},
8202   { &key_LOCK_user_conn, "LOCK_user_conn", PSI_FLAG_GLOBAL},
8203   { &key_LOCK_uuid_generator, "LOCK_uuid_generator", PSI_FLAG_GLOBAL},
8204   { &key_LOG_LOCK_log, "LOG::LOCK_log", 0},
8205   { &key_master_info_data_lock, "Master_info::data_lock", 0},
8206   { &key_master_info_run_lock, "Master_info::run_lock", 0},
8207   { &key_master_info_sleep_lock, "Master_info::sleep_lock", 0},
8208   { &key_mutex_slave_reporting_capability_err_lock, "Slave_reporting_capability::err_lock", 0},
8209   { &key_relay_log_info_data_lock, "Relay_log_info::data_lock", 0},
8210   { &key_relay_log_info_log_space_lock, "Relay_log_info::log_space_lock", 0},
8211   { &key_relay_log_info_run_lock, "Relay_log_info::run_lock", 0},
8212   { &key_relay_log_info_sleep_lock, "Relay_log_info::sleep_lock", 0},
8213   { &key_structure_guard_mutex, "Query_cache::structure_guard_mutex", 0},
8214   { &key_TABLE_SHARE_LOCK_ha_data, "TABLE_SHARE::LOCK_ha_data", 0},
8215   { &key_LOCK_error_messages, "LOCK_error_messages", PSI_FLAG_GLOBAL},
8216   { &key_LOG_INFO_lock, "LOG_INFO::lock", 0},
8217   { &key_LOCK_thread_count, "LOCK_thread_count", PSI_FLAG_GLOBAL},
8218   { &key_PARTITION_LOCK_auto_inc, "HA_DATA_PARTITION::LOCK_auto_inc", 0},
8219   { &key_LOCK_thread_created, "LOCK_thread_created", PSI_FLAG_GLOBAL },
8220   { &key_LOCK_thd_remove, "LOCK_thd_remove", PSI_FLAG_GLOBAL}
8221 };
8222 
8223 PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger,
8224   key_rwlock_LOCK_sys_init_connect, key_rwlock_LOCK_sys_init_slave,
8225   key_rwlock_LOCK_system_variables_hash, key_rwlock_query_cache_query_lock;
8226 
8227 static PSI_rwlock_info all_server_rwlocks[]=
8228 {
8229 #if defined (HAVE_OPENSSL) && !defined(HAVE_YASSL)
8230   { &key_rwlock_openssl, "CRYPTO_dynlock_value::lock", 0},
8231 #endif
8232   { &key_rwlock_LOCK_grant, "LOCK_grant", PSI_FLAG_GLOBAL},
8233   { &key_rwlock_LOCK_logger, "LOGGER::LOCK_logger", 0},
8234   { &key_rwlock_LOCK_sys_init_connect, "LOCK_sys_init_connect", PSI_FLAG_GLOBAL},
8235   { &key_rwlock_LOCK_sys_init_slave, "LOCK_sys_init_slave", PSI_FLAG_GLOBAL},
8236   { &key_rwlock_LOCK_system_variables_hash, "LOCK_system_variables_hash", PSI_FLAG_GLOBAL},
8237   { &key_rwlock_query_cache_query_lock, "Query_cache_query::lock", 0}
8238 };
8239 
8240 #ifdef HAVE_MMAP
8241 PSI_cond_key key_PAGE_cond, key_COND_active, key_COND_pool;
8242 #endif /* HAVE_MMAP */
8243 
8244 PSI_cond_key key_BINLOG_COND_prep_xids, key_BINLOG_update_cond,
8245   key_COND_cache_status_changed, key_COND_manager,
8246   key_COND_rpl_status, key_COND_server_started,
8247   key_delayed_insert_cond, key_delayed_insert_cond_client,
8248   key_item_func_sleep_cond, key_master_info_data_cond,
8249   key_master_info_start_cond, key_master_info_stop_cond,
8250   key_master_info_sleep_cond,
8251   key_relay_log_info_data_cond, key_relay_log_info_log_space_cond,
8252   key_relay_log_info_start_cond, key_relay_log_info_stop_cond,
8253   key_relay_log_info_sleep_cond,
8254   key_TABLE_SHARE_cond, key_user_level_lock_cond,
8255   key_COND_thread_count, key_COND_thread_cache, key_COND_flush_thread_cache;
8256 PSI_cond_key key_RELAYLOG_update_cond;
8257 
8258 static PSI_cond_info all_server_conds[]=
8259 {
8260 #if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
8261   { &key_COND_handler_count, "COND_handler_count", PSI_FLAG_GLOBAL},
8262 #endif /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */
8263 #ifdef HAVE_MMAP
8264   { &key_PAGE_cond, "PAGE::cond", 0},
8265   { &key_COND_active, "TC_LOG_MMAP::COND_active", 0},
8266   { &key_COND_pool, "TC_LOG_MMAP::COND_pool", 0},
8267 #endif /* HAVE_MMAP */
8268   { &key_BINLOG_COND_prep_xids, "MYSQL_BIN_LOG::COND_prep_xids", 0},
8269   { &key_BINLOG_update_cond, "MYSQL_BIN_LOG::update_cond", 0},
8270   { &key_RELAYLOG_update_cond, "MYSQL_RELAY_LOG::update_cond", 0},
8271   { &key_COND_cache_status_changed, "Query_cache::COND_cache_status_changed", 0},
8272   { &key_COND_manager, "COND_manager", PSI_FLAG_GLOBAL},
8273   { &key_COND_rpl_status, "COND_rpl_status", PSI_FLAG_GLOBAL},
8274   { &key_COND_server_started, "COND_server_started", PSI_FLAG_GLOBAL},
8275   { &key_delayed_insert_cond, "Delayed_insert::cond", 0},
8276   { &key_delayed_insert_cond_client, "Delayed_insert::cond_client", 0},
8277   { &key_item_func_sleep_cond, "Item_func_sleep::cond", 0},
8278   { &key_master_info_data_cond, "Master_info::data_cond", 0},
8279   { &key_master_info_start_cond, "Master_info::start_cond", 0},
8280   { &key_master_info_stop_cond, "Master_info::stop_cond", 0},
8281   { &key_master_info_sleep_cond, "Master_info::sleep_cond", 0},
8282   { &key_relay_log_info_data_cond, "Relay_log_info::data_cond", 0},
8283   { &key_relay_log_info_log_space_cond, "Relay_log_info::log_space_cond", 0},
8284   { &key_relay_log_info_start_cond, "Relay_log_info::start_cond", 0},
8285   { &key_relay_log_info_stop_cond, "Relay_log_info::stop_cond", 0},
8286   { &key_relay_log_info_sleep_cond, "Relay_log_info::sleep_cond", 0},
8287   { &key_TABLE_SHARE_cond, "TABLE_SHARE::cond", 0},
8288   { &key_user_level_lock_cond, "User_level_lock::cond", 0},
8289   { &key_COND_thread_count, "COND_thread_count", PSI_FLAG_GLOBAL},
8290   { &key_COND_thread_cache, "COND_thread_cache", PSI_FLAG_GLOBAL},
8291   { &key_COND_flush_thread_cache, "COND_flush_thread_cache", PSI_FLAG_GLOBAL}
8292 };
8293 
8294 PSI_thread_key key_thread_bootstrap, key_thread_delayed_insert,
8295   key_thread_handle_manager, key_thread_main,
8296   key_thread_one_connection, key_thread_signal_hand;
8297 
8298 static PSI_thread_info all_server_threads[]=
8299 {
8300 #if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
8301   { &key_thread_handle_con_namedpipes, "con_named_pipes", PSI_FLAG_GLOBAL},
8302 #endif /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */
8303 
8304 #if defined(HAVE_SMEM) && !defined(EMBEDDED_LIBRARY)
8305   { &key_thread_handle_con_sharedmem, "con_shared_mem", PSI_FLAG_GLOBAL},
8306 #endif /* HAVE_SMEM && !EMBEDDED_LIBRARY */
8307 
8308 #if (defined(_WIN32) || defined(HAVE_SMEM)) && !defined(EMBEDDED_LIBRARY)
8309   { &key_thread_handle_con_sockets, "con_sockets", PSI_FLAG_GLOBAL},
8310 #endif /* _WIN32 || HAVE_SMEM && !EMBEDDED_LIBRARY */
8311 
8312 #ifdef __WIN__
8313   { &key_thread_handle_shutdown, "shutdown", PSI_FLAG_GLOBAL},
8314 #endif /* __WIN__ */
8315 
8316   { &key_thread_bootstrap, "bootstrap", PSI_FLAG_GLOBAL},
8317   { &key_thread_delayed_insert, "delayed_insert", 0},
8318   { &key_thread_handle_manager, "manager", PSI_FLAG_GLOBAL},
8319   { &key_thread_main, "main", PSI_FLAG_GLOBAL},
8320   { &key_thread_one_connection, "one_connection", 0},
8321   { &key_thread_signal_hand, "signal_handler", PSI_FLAG_GLOBAL}
8322 };
8323 
8324 #ifdef HAVE_MMAP
8325 PSI_file_key key_file_map;
8326 #endif /* HAVE_MMAP */
8327 
8328 PSI_file_key key_file_binlog, key_file_binlog_index, key_file_casetest,
8329   key_file_dbopt, key_file_des_key_file, key_file_ERRMSG, key_select_to_file,
8330   key_file_fileparser, key_file_frm, key_file_global_ddl_log, key_file_load,
8331   key_file_loadfile, key_file_log_event_data, key_file_log_event_info,
8332   key_file_master_info, key_file_misc, key_file_partition,
8333   key_file_pid, key_file_relay_log_info, key_file_send_file, key_file_tclog,
8334   key_file_trg, key_file_trn, key_file_init;
8335 PSI_file_key key_file_query_log, key_file_slow_log;
8336 PSI_file_key key_file_relaylog, key_file_relaylog_index;
8337 
8338 static PSI_file_info all_server_files[]=
8339 {
8340 #ifdef HAVE_MMAP
8341   { &key_file_map, "map", 0},
8342 #endif /* HAVE_MMAP */
8343   { &key_file_binlog, "binlog", 0},
8344   { &key_file_binlog_index, "binlog_index", 0},
8345   { &key_file_relaylog, "relaylog", 0},
8346   { &key_file_relaylog_index, "relaylog_index", 0},
8347   { &key_file_casetest, "casetest", 0},
8348   { &key_file_dbopt, "dbopt", 0},
8349   { &key_file_des_key_file, "des_key_file", 0},
8350   { &key_file_ERRMSG, "ERRMSG", 0},
8351   { &key_select_to_file, "select_to_file", 0},
8352   { &key_file_fileparser, "file_parser", 0},
8353   { &key_file_frm, "FRM", 0},
8354   { &key_file_global_ddl_log, "global_ddl_log", 0},
8355   { &key_file_load, "load", 0},
8356   { &key_file_loadfile, "LOAD_FILE", 0},
8357   { &key_file_log_event_data, "log_event_data", 0},
8358   { &key_file_log_event_info, "log_event_info", 0},
8359   { &key_file_master_info, "master_info", 0},
8360   { &key_file_misc, "misc", 0},
8361   { &key_file_partition, "partition", 0},
8362   { &key_file_pid, "pid", 0},
8363   { &key_file_query_log, "query_log", 0},
8364   { &key_file_relay_log_info, "relay_log_info", 0},
8365   { &key_file_send_file, "send_file", 0},
8366   { &key_file_slow_log, "slow_log", 0},
8367   { &key_file_tclog, "tclog", 0},
8368   { &key_file_trg, "trigger_name", 0},
8369   { &key_file_trn, "trigger", 0},
8370   { &key_file_init, "init", 0}
8371 };
8372 
8373 /**
8374   Initialise all the performance schema instrumentation points
8375   used by the server.
8376 */
init_server_psi_keys(void)8377 void init_server_psi_keys(void)
8378 {
8379   const char* category= "sql";
8380   int count;
8381 
8382   if (PSI_server == NULL)
8383     return;
8384 
8385   count= array_elements(all_server_mutexes);
8386   PSI_server->register_mutex(category, all_server_mutexes, count);
8387 
8388   count= array_elements(all_server_rwlocks);
8389   PSI_server->register_rwlock(category, all_server_rwlocks, count);
8390 
8391   count= array_elements(all_server_conds);
8392   PSI_server->register_cond(category, all_server_conds, count);
8393 
8394   count= array_elements(all_server_threads);
8395   PSI_server->register_thread(category, all_server_threads, count);
8396 
8397   count= array_elements(all_server_files);
8398   PSI_server->register_file(category, all_server_files, count);
8399 }
8400 
8401 #endif /* HAVE_PSI_INTERFACE */
8402 
8403