1 /* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
2 
3   This program is free software; you can redistribute it and/or modify
4   it under the terms of the GNU General Public License, version 2.0,
5   as published by the Free Software Foundation.
6 
7   This program is also distributed with certain software (including
8   but not limited to OpenSSL) that is licensed under separate terms,
9   as designated in a particular file or component or in included license
10   documentation.  The authors of MySQL hereby grant you an additional
11   permission to link the program and your derivative works with the
12   separately licensed software that they have included with MySQL.
13 
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License, version 2.0, for more details.
18 
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 /**
24   @file sql/mysqld.cc
25   MySQL server daemon.
26 */
27 
28 /* clang-format off */
29 /**
30   @mainpage Welcome
31 
32   Welcome to the MySQL source code documentation.
33 
34   This documentation covers primarily the MySQL server,
35   for the @c mysqld process.
36 
37   Other programs, like the MySQL Router, are also documented,
38   see the @ref PAGE_SERVER_TOOLS section.
39 
40   The order chosen to present the content is to start with low level components,
41   and build upon previous sections, so that code is presented in a logical order.
42 
43   For some sections, a full article (Doxygen 'page') presents the component in detail.
44 
45   For other sections, only links are provided, as a starting point into the component.
46 
47   For the user manual, see http://dev.mysql.com/doc/refman/8.0/en/
48 
49   For the internals manual, see https://dev.mysql.com/doc/internals/en/index.html
50 
51   This documentation is published for each release, starting with MySQL 8.0.
52 
53   The present document corresponds to:
54 
55   Document generated on: ${DOXYGEN_GENERATION_DATE},
56   branch: ${DOXYGEN_GENERATION_BRANCH},
57   revision: ${DOXYGEN_GENERATION_REVISION}
58 
59   For the latest available version, see https://dev.mysql.com/doc/dev/mysql-server/latest/
60 
61   For other versions, see https://dev.mysql.com/doc/index-archive.html
62 */
63 
64 /**
65   @page PAGE_GET_STARTED Getting Started
66 
67   - @ref start_source
68   - @subpage PAGE_CODING_GUIDELINES
69   - @ref start_debug
70 
71   @section start_source Build from source
72 
73   See https://dev.mysql.com/doc/refman/8.0/en/source-installation.html
74 
75   @section start_debug Debugging
76 
77   The easiest way to install a server, and attach a debugger to it,
78   is to start the mysql-test-run (MTR) tool with debugging options
79 
80   @verbatim
81   cd mysql-test
82   ./mtr --ddd main.parser
83   @endverbatim
84 
85   The following functions are good candidates for breakpoints:
86   - #my_message_sql
87   - #dispatch_command
88 
89   Replace 'main.parser' with another test script, or write your own, to debug a specific area.
90 */
91 
92 /**
93   @page PAGE_CODING_GUIDELINES Coding Guidelines
94 
95   This section shows the guidelines that MySQL developers
96   follow when writing new code.
97 
98   New MySQL code uses the Google C++ coding style
99   (https://google.github.io/styleguide/cppguide.html), with one
100   exception:
101 
102   - Member variable names: Do not use foo_. Instead, use
103     m_foo (non-static) or s_foo (static).
104 
105   Old projects and modifications to old code use an older MySQL-specific
106   style for the time being. Since 8.0, MySQL style uses the same formatting
107   rules as Google coding style (e.g., brace placement, indentation, line
108   lengths, etc.), but differs in a few important aspects:
109 
110   - Class names: Do not use MyClass. Instead, use My_class.
111 
112   - Function names: Use snake_case().
113 
114   - Comment Style: Use either the // or <em>/</em>* *<em>/</em> syntax. // is
115     much more common but both syntaxes are permitted for the time being.
116 
117   - Doxygen comments: Use <em>/</em>** ... *<em>/</em> syntax and not ///.
118 
119   - Doxygen commands: Use '@' and not '\' for doxygen commands.
120 
121   - You may see structs starting with st_ and being typedef-ed to some
122     UPPERCASE (e.g. typedef struct st_foo { ... } FOO). However,
123     this is legacy from when the codebase contained C. Do not make such new
124     typedefs nor structs with st_ prefixes, and feel free to remove those that
125     already exist, except in public header files that are part of libmysql
126     (which need to be parseable as C99).
127 
128 
129   Code formatting is enforced by use of clang-format throughout the code
130   base. However, note that formatting is only one part of coding style;
131   you are required to take care of non-formatting issues yourself, such as
132   following naming conventions, having clear ownership of code or minimizing
133   the use of macros. See the Google coding style guide for the entire list.
134 
135   Consistent style is important for us, because everyone must know what to
136   expect. Knowing our rules, you'll find it easier to read our code, and when
137   you decide to contribute (which we hope you'll consider!) we'll find it
138   easier to read and review your code.
139 
140   - @subpage GENERAL_DEVELOPMENT_GUIDELINES
141   - @subpage CPP_CODING_GUIDELINES_FOR_NDB_SE
142   - @subpage DBUG_TAGS
143 
144 */
145 
146 /**
147   @page PAGE_INFRASTRUCTURE Infrastructure
148 
149   @section infra_basic Basic classes and templates
150 
151   @subsection infra_basic_container Container
152 
153   See #DYNAMIC_ARRAY, #List, #I_P_List, #LF_HASH.
154 
155   @subsection infra_basic_syncho Synchronization
156 
157   See #native_mutex_t, #native_rw_lock_t, #native_cond_t.
158 
159   @subsection infra_basic_fileio File IO
160 
161   See #my_open, #my_dir.
162 
163   @section infra_server_blocks Server building blocs
164 
165   @subsection infra_server_blocks_vio Virtual Input Output
166 
167   See #Vio, #vio_init.
168 
169   @section deployment Deployment
170 
171   @subsection deploy_install Installation
172 
173   See #opt_initialize, #bootstrap::run_bootstrap_thread.
174 
175   @subsection deploy_startup Startup
176 
177   See #mysqld_main.
178 
179   @subsection deploy_shutdown Shutdown
180 
181   See #handle_fatal_signal, #signal_hand.
182 
183   @subsection deploy_upgrade Upgrade
184 
185   See #Mysql::Tools::Upgrade::Program.
186 
187 */
188 
189 /**
190   @page PAGE_PROTOCOL Client/Server Protocol
191 
192   @section protocol_overview Overview
193 
194   The MySQL protocol is used between MySQL Clients and a MySQL Server.
195   It is implemented by:
196     - Connectors (Connector/C, Connector/J, and so forth)
197     - MySQL Proxy
198     - Communication between master and slave replication servers
199 
200   The protocol supports these features:
201     - Transparent encryption using SSL
202     - Transparent compression
203     - A @ref page_protocol_connection_phase where capabilities and
204       authentication data are exchanged
205     - A @ref page_protocol_command_phase which accepts commands
206       from the client and executes them
207 
208   Further reading:
209     - @subpage page_protocol_basics
210     - @subpage page_protocol_connection_lifecycle
211 */
212 
213 
214 /** @page mysqlx_protocol X %Protocol
215 
216 @par Topics in this section:
217 
218 - @subpage mysqlx_protocol_lifecycle
219 - @subpage mysqlx_protocol_authentication
220 - @subpage mysqlx_protocol_messages
221 - @subpage mysqlx_protocol_expectations
222 - @subpage mysqlx_protocol_notices
223 - @subpage mysqlx_protocol_xplugin
224 - @subpage mysqlx_protocol_use_cases
225 - @subpage mysqlx_protocol_implementation
226 - @subpage mysqlx_protocol_comparison
227 
228 
229 The X %Protocol is implemented by the X Plugin and the following
230 MySQL clients support the protocol:
231 
232 -  MYSQLXSHELL
233 
234 -  MySQL for Visual Studio 2.0.2 or higher
235 
236 -  MySQL Connector/J 6.0.2 or higher
237 
238 -  MySQL Connector/Net 7.0.2 or higher
239 
240 -  MySQL Connector/Node.js
241 
242 @section xprotocol_community_connector How to build a Community Connector
243 
244 MySQL provides a set of official MySQL Connectors for several popular
245 development frameworks and languages like Node.js, .Net, Python, Java, C,
246 C++ and more. At the same time, we also encourage community developers to
247 create native connectors for their favorite languages. To improve the process
248 and encourage creating a community connector going forward, and allow for more
249 rapid new feature support within the MySQL communications protocol, we created
250 a new protocol called the MySQL X Protocol.
251 
252 The new X Protocol leverages current industry standards. One of those standards
253 in use is protobuf (more formally know as Google Protobuffers).
254 The .proto formatted files provide the complete message definitions of the
255 X Protocol. Another feature of protobuf is the automatic code generation based
256 on those .proto files across a variety of languages for use in community
257 developed connectors for MySQL.
258 
259 These language specific generated files can be used with no restrictions under
260 your own terms.
261 
262 The X Protocol use of .proto makes our protocol design clear and concise,
263 no longer requiring the efforts previously required – no longer will you need
264 to directly analyze our message format. In addition to the layout of
265 the message format, the .proto also defines and documents message sequence
266 and flow between the connectors and the MySQL server. The information defined
267 in the .proto file makes it easy to implement X protocol support in connector
268 code. As those who have written a MySQL connector know, coding the protocol
269 is only a small part of the effort required.
270 
271 Finally, you can focus on the big task of creating a MySQL community
272 connector - designing apis, coding, testing, selecting your license, packaging,
273 documentation. And, promoting and speaking about your work.
274 
275 @section xprotocol_mysqlxshell_example X Protocol example
276 
277 The following figure shows usage of the X %Protocol between MYSQLXSHELL and
278 MySQL Server 5.7.12 or higher with the X %Plugin enabled.
279 The object _X %Protocol_ on this figure represents rather some concept
280 than an implementation object. The aim is to show its role in the process
281 of information exchange between the client and the server.
282 
283 @startuml "X Protocol Overview"
284 actor "User"
285 box "MySQLx Shell"
286 participant "X DevAPI" as devapi
287 participant "X Protocol" as xclproto
288 end box
289 
290 box "MySQL Server"
291 participant "X Plugin" as xpl
292 participant "X Protocol" as xplproto
293 participant "Server" as serv
294 end box
295 
296 User -> devapi: Request
297 activate devapi
298 devapi -> xclproto: Encode request
299 activate xclproto
300 
301 xclproto --> devapi
302 deactivate xclproto
303 
304 devapi -> xpl: Receive request << Network (TCP) >>
305 activate xpl
306 
307 xpl -> xplproto: Decode request
308 activate xplproto
309 
310 xplproto --> xpl
311 deactivate xplproto
312 
313 xpl -> serv: Execute request
314 activate serv
315 
316 serv --> xpl
317 deactivate serv
318 
319 xpl --> devapi: << Network (TCP) >>
320 deactivate xpl
321 
322 devapi --> User
323 deactivate devapi
324 ...
325 @enduml
326 
327 The documentation is based on the source files such as:
328 
329 -  [``mysqlx.proto``](https://github.com/mysql/mysql-server/tree/5.7/rapid/plugin/x/protocol/mysqlx.proto)
330 -  [``mysqlx_connection.proto``](https://github.com/mysql/mysql-server/tree/5.7/rapid/plugin/x/protocol/mysqlx_connection.proto)
331 -  [``mysqlx_session.proto``](https://github.com/mysql/mysql-server/tree/5.7/rapid/plugin/x/protocol/mysqlx_session.proto>)
332 -  [``mysqlx_crud.proto``](https://github.com/mysql/mysql-server/tree/5.7/rapid/plugin/x/protocol/mysqlx_crud.proto>)
333 -  [``mysqlx_sql.proto``](https://github.com/mysql/mysql-server/tree/5.7/rapid/plugin/x/protocol/mysqlx_sql.proto>)
334 -  [``mysqlx_resultset.proto``](https://github.com/mysql/mysql-server/tree/5.7/rapid/plugin/x/protocol/mysqlx_resultset.proto>)
335 -  [``mysqlx_expr.proto``](https://github.com/mysql/mysql-server/tree/5.7/rapid/plugin/x/protocol/mysqlx_expr.proto>)
336 -  [``mysqlx_datatypes.proto``](https://github.com/mysql/mysql-server/tree/5.7/rapid/plugin/x/protocol/mysqlx_datatypes.proto>)
337 -  [``mysqlx_expect.proto``](https://github.com/mysql/mysql-server/tree/5.7/rapid/plugin/x/protocol/mysqlx_expect.proto>)
338 -  [``mysqlx_notice.proto``](https://github.com/mysql/mysql-server/tree/5.7/rapid/plugin/x/protocol/mysqlx_notice.proto>)
339 
340 */
341 
342 
343 /**
344   @page PAGE_SQL_EXECUTION SQL Query Execution
345 
346   @section sql_query_exec_parsing SQL Parsing
347 
348   The parser processes SQL strings and builds a tree representation of them.
349 
350   See @ref GROUP_PARSER.
351 
352   @subpage PAGE_SQL_Optimizer
353 
354   @subpage stored_programs
355 
356   @section sql_query_exec_prepared Prepared statements
357 
358   See #mysql_stmt_prepare
359 
360   @section func_stored_proc Stored procedures
361 
362   See #sp_head, #sp_instr.
363 
364   @section sql_query_exec_sql_functions SQL Functions
365 
366   See #Item_func
367 
368   @section sql_query_exec_error_handling Error handling
369 
370   See #my_message, #my_error
371 
372   @subpage PAGE_TXN
373 
374 */
375 
376 /**
377   @page PAGE_STORAGE Data Storage
378 
379   @section storage_innodb Innodb
380 
381   See #ha_innobase or read details about InnoDB internals:
382   - @subpage PAGE_INNODB_PFS
383   - @subpage PAGE_INNODB_REDO_LOG
384   - @subpage PAGE_INNODB_LOCK_SYS
385   - @subpage PAGE_INNODB_UTILS
386 
387   @section storage_temptable Temp table
388 
389   Before 8.0, temporary tables were handled by heap engine.
390   The heap engine had no feature to store bigger tables on disk.
391 
392   Since 8.0, there is a brand new temptable engine, which
393   is written from scratch using c++11. It has following advantages:
394   - it is able to store bigger tables on disk (in temporary files),
395   - it uses row format with variable size (can save memory for varchars),
396   - it is better designed (easier to maintain).
397 
398   @subpage PAGE_TEMPTABLE
399 
400 */
401 
402 
403 /**
404   @page PAGE_REPLICATION Replication
405 
406   @subpage PAGE_RPL_FIELD_METADATA
407 
408 */
409 
410 /**
411   @page PAGE_TXN Transactions
412 
413   See #trans_begin, #trans_commit, #trans_rollback.
414 */
415 
416 /**
417   @page PAGE_SECURITY Security
418 
419   @subpage AUTHORIZATION_PAGE
420 */
421 
422 
423 /**
424   @page PAGE_MONITORING Monitoring
425 
426   @subpage PAGE_PFS
427 */
428 
429 /**
430   @page PAGE_EXTENDING Extending MySQL
431 
432   Components
433   ----------
434 
435   MySQL 8.0 introduces support for extending the server through components.
436   Components can communicate with other components through service APIs.
437   And can provide implementations of service APIs for other components to use.
438   All components are equal and can communicate with all other components.
439   Service implementations can be found by name via a registry service handle
440   which is passed to the component initialization function.
441   There can be multiple service API implementations for a single service API.
442   One of them is the default implementation.
443   Service API are stateless by definition. If they need to handle state or
444   object instances they need to do so by using factory methods and instance
445   handles.
446 
447   To ease up transition to the component model the current server
448   functionality (server proper and plugins) is contained within
449   a dedicated built in server component. The server component currently
450   contains all of the functionality provided by the server and
451   classical server plugins.
452 
453   More components can be installed via the "INSTALL COMPONENT" SQL command.
454 
455   The component infrastructure is designed as a replacement for the classical
456   MySQL plugin system as it does not suffer from some of the limitations of it
457   and provides better isolation for the component code.
458 
459   See @subpage PAGE_COMPONENTS.
460 
461   Plugins and Services
462   --------------------
463 
464   As of MySQL 5.1 the server functionality can be extended through
465   installing (dynamically or statically linked) extra code modules
466   called plugins.
467 
468   The server defines a set of well known plugin APIs that the modules
469   can implement.
470 
471   To allow plugins to reuse server code the server exposes a pre-defined
472   set of functions to plugins called plugin services.
473 
474   See the following for more details:
475   - @subpage page_ext_plugins
476   - @subpage page_ext_plugin_services
477 
478 
479   User Defined Functions
480   ----------------------
481 
482   Native code user defined functions can be added to MySQL server using
483   the CREATE FUNCTION ... SONAME syntax.
484 
485   These can co-exit with @ref page_ext_plugins or reside in their own
486   separate binaries.
487 
488   To learn how to create these user defined functions see @subpage page_ext_udf
489 */
490 
491 
492 /**
493   @page PAGE_SERVER_TOOLS Server tools
494 
495   - @subpage PAGE_MYSQL_ROUTER
496 */
497 
498 
499 /**
500   @page PAGE_CLIENT_TOOLS Client tools
501 
502   See mysqldump.cc mysql.cc
503 */
504 
505 
506 /**
507   @page PAGE_TESTING_TOOLS Testing Tools
508 
509   - @subpage PAGE_MYSQL_TEST_RUN
510 */
511 
512 /**
513   @page PAGE_DEV_TOOLS Development Tools
514 
515   - @subpage PAGE_LOCK_ORDER
516 */
517 
518 /**
519   @page PAGE_CODE_PATHS Code paths
520 
521   This section details how the server executes some statements,
522   to illustrate how different parts work together.
523 
524   Note that this overall view might take some shortcuts,
525   hiding some details or taking liberties with the notations,
526   to present the whole code structure in a comprehensible way.
527 
528   - @subpage CODE_PATH_CREATE_TABLE
529 */
530 
531 /**
532   @page CODE_PATH_CREATE_TABLE CREATE TABLE
533 
534   @section CREATE_TABLE_PARSER Parser
535 
536   @startuml
537 
538   actor ddl as "CREATE TABLE Query"
539   participant server as "MySQL Server"
540   participant parser as "SQL Parser"
541   participant bison as "Bison Parser"
542   participant lexer as "Lexical Scanner"
543   participant pt as "Parse Tree Nodes"
544 
545   ddl -> server : DDL QUERY TEXT
546   server -> parser : THD::sql_parser()
547   == Bison parser ==
548   parser -> bison : MYSQLparse()
549   bison -> lexer : MYSQLlex()
550   bison <-- lexer : yylval, yylloc
551   bison -> pt : new
552   activate pt
553   parser <-- pt : Abstract Syntax Tree
554 
555   @enduml
556 
557   When a query is sent to the server,
558   the first step is to invoke the bison parser
559   to build an Abstract Syntax Tree to represent the query text.
560 
561   Assume the following statement:
562   @verbatim
563   CREATE TABLE test.t1 (a int) ENGINE = "INNODB";
564   @endverbatim
565 
566   In the bison grammar file, the rule implementing the CREATE TABLE
567   statement is @c create_table_stmt.
568 
569   The tree created is an object of class @ref PT_create_table_stmt.
570 
571   This parse tree node has several related nodes, such as:
572   - @ref PT_create_table_option and sub classes, for table options.
573   - @ref PT_table_element and sub classes, for the columns, indexes, etc.
574 
575   The collection of nodes returned after the bison parsing is known
576   as the "Abstract Syntax Tree" that represents a SQL query.
577 
578   @section CREATE_TABLE_CMD Sql command
579 
580   @startuml
581 
582   actor ddl as "CREATE TABLE Query"
583   participant server as "MySQL Server"
584   participant parser as "SQL Parser"
585   participant ast as "Abstract Syntax Tree"
586   participant cmd as "SQL Command"
587   participant ci as "HA_CREATE_INFO"
588   participant plugin as "MySQL plugin"
589 
590   ddl -> server : DDL QUERY TEXT
591   server -> parser : THD::sql_parser()
592   == Bison parser ==
593   == Build SQL command ==
594   parser -> ast : make_cmd()
595   ast -> ast : contextualize()
596   ast -> ci : build()
597   activate ci
598   ci -> plugin : ha_resolve_engine()
599   ci <-- plugin : storage engine handlerton
600   ast <-- ci : Parse Tree (contextualized)
601   ast -> cmd : build()
602   activate cmd
603   server <-- cmd : SQL Command
604 
605   @enduml
606 
607   Once the bison parser has finished parsing a query text,
608   the next step is to build a SQL command from the Abstract Syntax Tree.
609 
610   In the Abstract Syntax Tree, attributes like a storage engine name
611   ("INNODB") are represented as strings, taken from the query text.
612 
613   These attributes need to be converted to objects in the SQL context,
614   such as an @ref innodb_hton pointer to represent the INNODB storage engine.
615 
616   The process that performs these transformations is contextualize().
617 
618   The @ref Parse_tree_root class is an abstract factory, building @ref Sql_cmd
619   objects.
620 
621   For a CREATE TABLE statement, class @ref PT_create_table_stmt builds a
622   concrete @ref Sql_cmd_create_table object.
623 
624   @ref PT_create_table_stmt::make_cmd() in particular performs the following
625   actions:
626   - contextualize the parse tree for the CREATE TABLE statement.
627   - build a @ref HA_CREATE_INFO structure to represent the table DDL.
628   - resolve the storage engine name to an actual @ref handlerton pointer,
629     in @ref PT_create_table_engine_option::contextualize()
630 
631   @section CREATE_TABLE_RUNTIME Runtime execution
632 
633   @startuml
634 
635   actor ddl as "CREATE TABLE Query"
636   participant server as "MySQL Server"
637   participant cmd as "SQL Command"
638   participant rt as "Runtime"
639 
640   ddl -> server : DDL QUERY TEXT
641   == Bison parser ==
642   == Build SQL command ==
643   == Execute SQL command ==
644   server -> cmd : execute()
645   cmd -> rt : mysql_create_table()
646 
647   @enduml
648 
649   Execution of a CREATE TABLE statement invokes
650   @ref Sql_cmd_create_table::execute(),
651   which in turns calls:
652   - @ref mysql_create_table(),
653   - @ref mysql_create_table_no_lock(),
654   - @ref create_table_impl(),
655   - @ref rea_create_base_table().
656 
657   Execution of this code is the runtime implementation of the CREATE TABLE
658   statement, and eventually leads to:
659   - @ref dd::create_table(), to create the table in the Data Dictionary,
660   - @ref ha_create_table(), to create the table in the handlerton.
661 
662   Details about the dictionary and the storage engine are expanded
663   in the following two sections.
664 
665 
666   @section CREATE_TABLE_DD Data Dictionary
667 
668   @startuml
669 
670   actor ddl as "CREATE TABLE Query"
671   participant server as "MySQL Server"
672   participant rt as "Runtime"
673   participant dd as "Data Dictionary"
674   participant ddt as "Data Dictionary Table"
675   participant sdi as "Serialized Dictionary Information"
676   participant hton as "Handlerton"
677   participant se as "Storage Engine"
678   participant ts as "Tablespace"
679 
680   ddl -> server : DDL QUERY TEXT
681   == ... ==
682   server -> rt : ( execution code path )
683   == Data Dictionary ==
684   rt -> dd : dd::create_table()
685   dd -> ddt : build dd::Table()
686   activate ddt
687   rt <-- ddt : dd:Table instance
688   == Serialized Dictionary Information ==
689   rt -> dd : store()
690   dd -> sdi : dd::sdi::store()
691   sdi -> sdi : sdi_tablespace::store_tbl_sdi()
692   == Storage Engine (Tablespace) ==
693   sdi -> hton : handlerton::sdi()
694   hton -> se : ::sdi() implementation.
695   se -> ts : write metadata in tablespace
696 
697   @enduml
698 
699   In the data dictionary, creation of a new table calls:
700   - @ref dd::create_dd_user_table()
701   - @ref fill_dd_table_from_create_info()
702 
703   The data dictionary code parses the content of the HA_CREATE_INFO
704   input, and builds a @ref dd::Table object, to represent the table metadata.
705   Part of this metadata includes the storage engine name.
706 
707   The runtime code then calls @c store() to save this new metadata.
708 
709   To store a table metadata, the data dictionary code first serialize it
710   into an sdi format.
711 
712   The serialized object is then stored in persistence,
713   either in a tablespace or in a file:
714   - @ref sdi_tablespace::store_tbl_sdi()
715   - @ref sfi_file::store_tbl_sdi()
716 
717   When storing data into a tablespace, the storage engine handlerton is
718   invoked, so that the storage engine can ultimately store
719   the table metadata in the tablespace maintained by the storage engine.
720 
721   @section CREATE_TABLE_SE Storage Engine
722 
723   @startuml
724 
725   actor ddl as "CREATE TABLE Query"
726   participant server as "MySQL Server"
727   participant rt as "Runtime"
728   participant sei as "Storage Engine Interface"
729   participant hton as "Storage Engine Handlerton"
730   participant handler as "Storage Engine Handler"
731 
732   ddl -> server : DDL QUERY TEXT
733   == ... ==
734   server -> rt : ( execution code path )
735   == Storage Engine (table) ==
736   rt -> sei : ha_create_table()
737   sei -> hton : handlerton::create()
738   hton -> handler : (build a new table handler)
739   activate handler
740   sei <-- handler : storage engine table handler
741   sei -> handler : handler::create()
742 
743   @enduml
744 
745   When execution of the CREATE TABLE statement
746   reaches the storage engine interface,
747   the SQL layer function @ref ha_create_table()
748   invokes the storage engine @ref handlerton::create()
749   method to instantiate a new storage engine table,
750   represented by @ref handler.
751   The SQL layer then calls @ref handler::create() to create
752   the table inside the storage engine.
753 */
754 
755 /**
756   @page PAGE_SQL_Optimizer SQL Optimizer
757 
758   The task of query optimizer is to determine the most efficient means for
759   executing queries. The query optimizer consists of the following
760   sub-modules:
761 
762   - @ref Query_Resolver
763   - @ref Query_Optimizer
764   - @ref Query_Planner
765   - @ref Query_Executor
766 
767   @subpage PAGE_OPT_TRACE
768 
769   Additional articles about the query optimizer:
770 
771   - @ref PAGE_OPT_TRACE
772   - @ref AGGREGATE_CHECKS
773 */
774 /* clang-format on */
775 
776 #include "sql/mysqld.h"
777 
778 #include "my_config.h"
779 
780 #include "errmsg.h"  // init_client_errs
781 #include "ft_global.h"
782 #include "keycache.h"  // KEY_CACHE
783 #include "libbinlogevents/include/binlog_event.h"
784 #include "libbinlogevents/include/control_events.h"
785 #include "m_string.h"
786 #include "migrate_keyring.h"  // Migrate_keyring
787 #include "my_alloc.h"
788 #include "my_base.h"
789 #include "my_bitmap.h"  // MY_BITMAP
790 #include "my_command.h"
791 #include "my_dbug.h"
792 #include "my_default.h"  // print_defaults
793 #include "my_dir.h"
794 #include "my_getpwnam.h"
795 #include "my_loglevel.h"
796 #include "my_macros.h"
797 #include "my_shm_defaults.h"  // IWYU pragma: keep
798 #include "my_stacktrace.h"    // my_set_exception_pointers
799 #include "my_thread_local.h"
800 #include "my_time.h"
801 #include "my_timer.h"  // my_timer_initialize
802 #include "myisam.h"
803 #include "mysql/components/services/log_builtins.h"
804 #include "mysql/components/services/log_shared.h"
805 #include "mysql/components/services/mysql_runtime_error_service.h"
806 #include "mysql/plugin.h"
807 #include "mysql/plugin_audit.h"
808 #include "mysql/psi/mysql_cond.h"
809 #include "mysql/psi/mysql_file.h"
810 #include "mysql/psi/mysql_memory.h"  // mysql_memory_init
811 #include "mysql/psi/mysql_mutex.h"
812 #include "mysql/psi/mysql_rwlock.h"
813 #include "mysql/psi/mysql_socket.h"
814 #include "mysql/psi/mysql_stage.h"
815 #include "mysql/psi/mysql_statement.h"
816 #include "mysql/psi/mysql_thread.h"
817 #include "mysql/psi/psi_base.h"
818 #include "mysql/psi/psi_cond.h"
819 #include "mysql/psi/psi_data_lock.h"
820 #include "mysql/psi/psi_error.h"
821 #include "mysql/psi/psi_file.h"
822 #include "mysql/psi/psi_idle.h"
823 #include "mysql/psi/psi_mdl.h"
824 #include "mysql/psi/psi_memory.h"
825 #include "mysql/psi/psi_mutex.h"
826 #include "mysql/psi/psi_rwlock.h"
827 #include "mysql/psi/psi_socket.h"
828 #include "mysql/psi/psi_stage.h"
829 #include "mysql/psi/psi_statement.h"
830 #include "mysql/psi/psi_system.h"
831 #include "mysql/psi/psi_table.h"
832 #include "mysql/psi/psi_thread.h"
833 #include "mysql/psi/psi_tls_channel.h"
834 #include "mysql/psi/psi_transaction.h"
835 #include "mysql/service_mysql_alloc.h"
836 #include "mysql/thread_type.h"
837 #include "mysql_com.h"
838 #include "mysql_time.h"
839 #include "mysql_version.h"
840 #include "mysqld_error.h"
841 #include "mysys_err.h"  // EXIT_OUT_OF_MEMORY
842 #include "pfs_thread_provider.h"
843 #include "print_version.h"
844 #ifdef _WIN32
845 #include <shellapi.h>
846 #endif
847 #include "sql/auth/auth_common.h"         // grant_init
848 #include "sql/auth/sql_authentication.h"  // init_rsa_keys
849 #include "sql/auth/sql_security_ctx.h"
850 #include "sql/auto_thd.h"   // Auto_THD
851 #include "sql/binlog.h"     // mysql_bin_log
852 #include "sql/bootstrap.h"  // bootstrap
853 #include "sql/check_stack.h"
854 #include "sql/conn_handler/connection_acceptor.h"  // Connection_acceptor
855 #include "sql/conn_handler/connection_handler_impl.h"  // Per_thread_connection_handler
856 #include "sql/conn_handler/connection_handler_manager.h"  // Connection_handler_manager
857 #include "sql/conn_handler/socket_connection.h"  // stmt_info_new_packet
858 #include "sql/current_thd.h"                     // current_thd
859 #include "sql/dd/cache/dictionary_client.h"
860 #include "sql/debug_sync.h"  // debug_sync_end
861 #include "sql/derror.h"
862 #include "sql/event_data_objects.h"  // init_scheduler_psi_keys
863 #include "sql/events.h"              // Events
864 #include "sql/handler.h"
865 #include "sql/hostname_cache.h"  // hostname_cache_init
866 #include "sql/init.h"            // unireg_init
867 #include "sql/item.h"
868 #include "sql/item_cmpfunc.h"  // Arg_comparator
869 #include "sql/item_create.h"
870 #include "sql/item_func.h"
871 #include "sql/item_strfunc.h"  // Item_func_uuid
872 #include "sql/keycaches.h"     // get_or_create_key_cache
873 #include "sql/log.h"
874 #include "sql/log_event.h"  // Rows_log_event
875 #include "sql/log_resource.h"
876 #include "sql/mdl.h"
877 #include "sql/mdl_context_backup.h"  // mdl_context_backup_manager
878 #include "sql/my_decimal.h"
879 #include "sql/mysqld_daemon.h"
880 #include "sql/mysqld_thd_manager.h"              // Global_THD_manager
881 #include "sql/opt_costconstantcache.h"           // delete_optimizer_cost_module
882 #include "sql/opt_range.h"                       // range_optimizer_init
883 #include "sql/options_mysqld.h"                  // OPT_THREAD_CACHE_SIZE
884 #include "sql/partitioning/partition_handler.h"  // partitioning_init
885 #include "sql/persisted_variable.h"              // Persisted_variables_cache
886 #include "sql/plugin_table.h"
887 #include "sql/protocol.h"
888 #include "sql/psi_memory_key.h"  // key_memory_MYSQL_RELAY_LOG_index
889 #include "sql/query_options.h"
890 #include "sql/replication.h"                        // thd_enter_cond
891 #include "sql/resourcegroups/resource_group_mgr.h"  // init, post_init
892 #ifdef _WIN32
893 #include "sql/restart_monitor_win.h"
894 #endif
895 #include "sql/rpl_filter.h"
896 #include "sql/rpl_gtid.h"
897 #include "sql/rpl_gtid_persist.h"  // Gtid_table_persistor
898 #include "sql/rpl_handler.h"       // RUN_HOOK
899 #include "sql/rpl_info_factory.h"
900 #include "sql/rpl_info_handler.h"
901 #include "sql/rpl_injector.h"  // injector
902 #include "sql/rpl_log_encryption.h"
903 #include "sql/rpl_master.h"  // max_binlog_dump_events
904 #include "sql/rpl_mi.h"
905 #include "sql/rpl_msr.h"    // Multisource_info
906 #include "sql/rpl_rli.h"    // Relay_log_info
907 #include "sql/rpl_slave.h"  // slave_load_tmpdir
908 #include "sql/rpl_trx_tracking.h"
909 #include "sql/sd_notify.h"  // sd_notify_connect
910 #include "sql/session_tracker.h"
911 #include "sql/set_var.h"
912 #include "sql/sp_head.h"    // init_sp_psi_keys
913 #include "sql/sql_audit.h"  // mysql_audit_general
914 #include "sql/sql_base.h"
915 #include "sql/sql_callback.h"  // MUSQL_CALLBACK
916 #include "sql/sql_class.h"     // THD
917 #include "sql/sql_connect.h"
918 #include "sql/sql_error.h"
919 #include "sql/sql_initialize.h"  // opt_initialize_insecure
920 #include "sql/sql_lex.h"
921 #include "sql/sql_list.h"
922 #include "sql/sql_locale.h"   // MY_LOCALE
923 #include "sql/sql_manager.h"  // start_handle_manager
924 #include "sql/sql_parse.h"    // check_stack_overrun
925 #include "sql/sql_plugin.h"   // opt_plugin_dir
926 #include "sql/sql_plugin_ref.h"
927 #include "sql/sql_reload.h"          // handle_reload_request
928 #include "sql/sql_restart_server.h"  // is_mysqld_managed
929 #include "sql/sql_servers.h"
930 #include "sql/sql_show.h"
931 #include "sql/sql_table.h"  // build_table_filename
932 #include "sql/sql_udf.h"
933 #include "sql/ssl_acceptor_context_iterator.h"
934 #include "sql/ssl_acceptor_context_operator.h"
935 #include "sql/ssl_acceptor_context_status.h"
936 #include "sql/ssl_init_callback.h"
937 #include "sql/sys_vars.h"         // fixup_enforce_gtid_consistency_...
938 #include "sql/sys_vars_shared.h"  // intern_find_sys_var
939 #include "sql/table_cache.h"      // table_cache_manager
940 #include "sql/tc_log.h"           // tc_log
941 #include "sql/thd_raii.h"
942 #include "sql/thr_malloc.h"
943 #include "sql/transaction.h"
944 #include "sql/tztime.h"  // Time_zone
945 #include "sql/xa.h"
946 #include "sql_common.h"  // mysql_client_plugin_init
947 #include "sql_string.h"
948 #include "storage/myisam/ha_myisam.h"  // HA_RECOVER_OFF
949 #include "storage/perfschema/pfs_services.h"
950 #include "thr_lock.h"
951 #include "thr_mutex.h"
952 #include "typelib.h"
953 #include "violite.h"
954 
955 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
956 #include "storage/perfschema/pfs_server.h"
957 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
958 
959 #ifdef _WIN32
960 #include "sql/conn_handler/named_pipe_connection.h"
961 #include "sql/conn_handler/shared_memory_connection.h"
962 #include "sql/named_pipe.h"
963 #endif
964 
965 #ifdef MY_MSCRT_DEBUG
966 #include <crtdbg.h>
967 #endif
968 #include <errno.h>
969 #include <fcntl.h>
970 #include <fenv.h>
971 #include <limits.h>
972 #ifdef HAVE_GRP_H
973 #include <grp.h>
974 #endif
975 #ifndef _WIN32
976 #include <netdb.h>
977 #endif
978 #ifdef HAVE_NETINET_IN_H
979 #include <netinet/in.h>
980 #endif
981 #include <signal.h>
982 #include <stdarg.h>
983 #include <stddef.h>
984 #include <stdio.h>
985 #include <stdlib.h>
986 #include <string.h>
987 #include <sys/types.h>
988 #ifdef HAVE_SYS_MMAN_H
989 #include <sys/mman.h>
990 #endif
991 #ifdef HAVE_SYS_PRCTL_H
992 #include <sys/prctl.h>
993 #endif
994 #ifdef HAVE_SYS_RESOURCE_H
995 #include <sys/resource.h>
996 #endif
997 #include <sys/stat.h>
998 #ifdef HAVE_UNISTD_H
999 #include <unistd.h>
1000 #endif
1001 #ifdef _WIN32
1002 #include <crtdbg.h>
1003 #include <process.h>
1004 #endif
1005 #include "unicode/uclean.h"  // u_cleanup()
1006 
1007 #include <algorithm>
1008 #include <atomic>
1009 #include <functional>
1010 #include <new>
1011 #include <string>
1012 #include <vector>
1013 
1014 #ifndef EMBEDDED_LIBRARY
1015 #ifdef WITH_LOCK_ORDER
1016 #include "sql/debug_lock_order.h"
1017 #endif /* WITH_LOCK_ORDER */
1018 #endif /* EMBEDDED_LIBRARY */
1019 
1020 #ifndef EMBEDDED_LIBRARY
1021 #include "srv_session.h"
1022 #endif
1023 
1024 #include <mysql/components/minimal_chassis.h>
1025 #include <mysql/components/services/dynamic_loader_scheme_file.h>
1026 #include <mysql/components/services/mysql_psi_system_service.h>
1027 #include <mysql/components/services/mysql_rwlock_service.h>
1028 #include <mysql/components/services/ongoing_transaction_query_service.h>
1029 #include "sql/auth/dynamic_privileges_impl.h"
1030 #include "sql/dd/dd.h"                   // dd::shutdown
1031 #include "sql/dd/dd_kill_immunizer.h"    // dd::DD_kill_immunizer
1032 #include "sql/dd/dictionary.h"           // dd::get_dictionary
1033 #include "sql/dd/ndbinfo_schema/init.h"  // dd::ndbinfo::init_schema_and_tables()
1034 #include "sql/dd/performance_schema/init.h"  // performance_schema::init
1035 #include "sql/dd/upgrade/server.h"      // dd::upgrade::upgrade_system_schemas
1036 #include "sql/dd/upgrade_57/upgrade.h"  // dd::upgrade_57::in_progress
1037 #include "sql/server_component/component_sys_var_service_imp.h"
1038 #include "sql/server_component/log_builtins_filter_imp.h"
1039 #include "sql/server_component/log_builtins_imp.h"
1040 #include "sql/server_component/persistent_dynamic_loader_imp.h"
1041 #include "sql/srv_session.h"
1042 
1043 using std::max;
1044 using std::min;
1045 using std::vector;
1046 
1047 #define mysqld_charset &my_charset_latin1
1048 #define mysqld_default_locale_name "en_US"
1049 
1050 #ifdef HAVE_FPU_CONTROL_H
1051 #include <fpu_control.h>  // IWYU pragma: keep
1052 #elif defined(__i386__)
1053 #define fpu_control_t unsigned int
1054 #define _FPU_EXTENDED 0x300
1055 #define _FPU_DOUBLE 0x200
1056 #if defined(__GNUC__) || defined(__SUNPRO_CC)
1057 #define _FPU_GETCW(cw) asm volatile("fnstcw %0" : "=m"(*&cw))
1058 #define _FPU_SETCW(cw) asm volatile("fldcw %0" : : "m"(*&cw))
1059 #else
1060 #define _FPU_GETCW(cw) (cw = 0)
1061 #define _FPU_SETCW(cw)
1062 #endif
1063 #endif
setup_fpu()1064 inline void setup_fpu() {
1065 #ifdef HAVE_FEDISABLEEXCEPT
1066   fedisableexcept(FE_ALL_EXCEPT);
1067 #endif
1068 
1069   /* Set FPU rounding mode to "round-to-nearest" */
1070   fesetround(FE_TONEAREST);
1071 
1072   /*
1073     x86 (32-bit) requires FPU precision to be explicitly set to 64 bit
1074     (double precision) for portable results of floating point operations.
1075     However, there is no need to do so if compiler is using SSE2 for floating
1076     point, double values will be stored and processed in 64 bits anyway.
1077   */
1078 #if defined(__i386__) && !defined(__SSE2_MATH__)
1079 #if !defined(_WIN32)
1080   fpu_control_t cw;
1081   _FPU_GETCW(cw);
1082   cw = (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE;
1083   _FPU_SETCW(cw);
1084 #endif /* _WIN32 && */
1085 #endif /* __i386__ */
1086 }
1087 
1088 extern "C" void handle_fatal_signal(int sig);
1089 
1090 /* Constants */
1091 
1092 #include "welcome_copyright_notice.h"  // ORACLE_WELCOME_COPYRIGHT_NOTICE
1093 
1094 const char *show_comp_option_name[] = {"YES", "NO", "DISABLED"};
1095 
1096 static const char *tc_heuristic_recover_names[] = {"OFF", "COMMIT", "ROLLBACK",
1097                                                    NullS};
1098 static TYPELIB tc_heuristic_recover_typelib = {
1099     array_elements(tc_heuristic_recover_names) - 1, "",
1100     tc_heuristic_recover_names, nullptr};
1101 
1102 const char *first_keyword = "first", *binary_keyword = "BINARY";
1103 const char *my_localhost = "localhost";
1104 
1105 bool opt_large_files = sizeof(my_off_t) > 4;
1106 static bool opt_autocommit;  ///< for --autocommit command-line option
1107 static get_opt_arg_source source_autocommit;
1108 
1109 /*
1110   Used with --help for detailed option
1111 */
1112 bool opt_help = false, opt_verbose = false, opt_validate_config = false;
1113 
1114 arg_cmp_func Arg_comparator::comparator_matrix[5] = {
1115     &Arg_comparator::compare_string,      // Compare strings
1116     &Arg_comparator::compare_real,        // Compare float values
1117     &Arg_comparator::compare_int_signed,  // Compare signed int values
1118     &Arg_comparator::compare_row,         // Compare row values
1119     &Arg_comparator::compare_decimal};    // Compare decimal values
1120 
1121 PSI_file_key key_file_binlog_cache;
1122 PSI_file_key key_file_binlog_index_cache;
1123 
1124 #ifdef HAVE_PSI_INTERFACE
1125 static PSI_mutex_key key_LOCK_status;
1126 static PSI_mutex_key key_LOCK_manager;
1127 static PSI_mutex_key key_LOCK_crypt;
1128 static PSI_mutex_key key_LOCK_user_conn;
1129 static PSI_mutex_key key_LOCK_global_system_variables;
1130 static PSI_mutex_key key_LOCK_prepared_stmt_count;
1131 static PSI_mutex_key key_LOCK_sql_slave_skip_counter;
1132 static PSI_mutex_key key_LOCK_slave_net_timeout;
1133 static PSI_mutex_key key_LOCK_slave_trans_dep_tracker;
1134 static PSI_mutex_key key_LOCK_uuid_generator;
1135 static PSI_mutex_key key_LOCK_error_messages;
1136 static PSI_mutex_key key_LOCK_default_password_lifetime;
1137 static PSI_mutex_key key_LOCK_mandatory_roles;
1138 static PSI_mutex_key key_LOCK_password_history;
1139 static PSI_mutex_key key_LOCK_password_reuse_interval;
1140 static PSI_mutex_key key_LOCK_sql_rand;
1141 static PSI_mutex_key key_LOCK_log_throttle_qni;
1142 static PSI_mutex_key key_LOCK_reset_gtid_table;
1143 static PSI_mutex_key key_LOCK_compress_gtid_table;
1144 static PSI_mutex_key key_LOCK_collect_instance_log;
1145 static PSI_mutex_key key_BINLOG_LOCK_commit;
1146 static PSI_mutex_key key_BINLOG_LOCK_commit_queue;
1147 static PSI_mutex_key key_BINLOG_LOCK_done;
1148 static PSI_mutex_key key_BINLOG_LOCK_flush_queue;
1149 static PSI_mutex_key key_BINLOG_LOCK_index;
1150 static PSI_mutex_key key_BINLOG_LOCK_log;
1151 static PSI_mutex_key key_BINLOG_LOCK_binlog_end_pos;
1152 static PSI_mutex_key key_BINLOG_LOCK_sync;
1153 static PSI_mutex_key key_BINLOG_LOCK_sync_queue;
1154 static PSI_mutex_key key_BINLOG_LOCK_xids;
1155 static PSI_rwlock_key key_rwlock_global_sid_lock;
1156 PSI_rwlock_key key_rwlock_gtid_mode_lock;
1157 static PSI_rwlock_key key_rwlock_LOCK_system_variables_hash;
1158 static PSI_rwlock_key key_rwlock_LOCK_sys_init_connect;
1159 static PSI_rwlock_key key_rwlock_LOCK_sys_init_slave;
1160 static PSI_cond_key key_BINLOG_COND_done;
1161 static PSI_cond_key key_BINLOG_update_cond;
1162 static PSI_cond_key key_BINLOG_prep_xids_cond;
1163 static PSI_cond_key key_COND_manager;
1164 static PSI_cond_key key_COND_compress_gtid_table;
1165 static PSI_thread_key key_thread_signal_hand;
1166 static PSI_thread_key key_thread_main;
1167 static PSI_file_key key_file_casetest;
1168 static PSI_file_key key_file_pid;
1169 #if defined(_WIN32)
1170 static PSI_thread_key key_thread_handle_con_namedpipes;
1171 static PSI_thread_key key_thread_handle_con_sharedmem;
1172 static PSI_thread_key key_thread_handle_con_sockets;
1173 static PSI_mutex_key key_LOCK_handler_count;
1174 static PSI_cond_key key_COND_handler_count;
1175 static PSI_thread_key key_thread_handle_shutdown_restart;
1176 static PSI_rwlock_key key_rwlock_LOCK_named_pipe_full_access_group;
1177 #else
1178 static PSI_mutex_key key_LOCK_socket_listener_active;
1179 static PSI_cond_key key_COND_socket_listener_active;
1180 static PSI_mutex_key key_LOCK_start_signal_handler;
1181 static PSI_cond_key key_COND_start_signal_handler;
1182 #endif  // _WIN32
1183 static PSI_mutex_key key_LOCK_server_started;
1184 static PSI_cond_key key_COND_server_started;
1185 static PSI_mutex_key key_LOCK_keyring_operations;
1186 static PSI_mutex_key key_LOCK_tls_ctx_options;
1187 static PSI_mutex_key key_LOCK_admin_tls_ctx_options;
1188 static PSI_mutex_key key_LOCK_rotate_binlog_master_key;
1189 #endif /* HAVE_PSI_INTERFACE */
1190 
1191 /**
1192   Statement instrumentation key for replication.
1193 */
1194 #ifdef HAVE_PSI_STATEMENT_INTERFACE
1195 PSI_statement_info stmt_info_rpl;
1196 #endif
1197 
1198 /* the default log output is log tables */
1199 static bool lower_case_table_names_used = false;
1200 #if !defined(_WIN32)
1201 static bool socket_listener_active = false;
1202 static int pipe_write_fd = -1;
1203 static bool opt_daemonize = false;
1204 #endif
1205 bool opt_debugging = false;
1206 static bool opt_external_locking = false, opt_console = false;
1207 static bool opt_short_log_format = false;
1208 static char *mysqld_user, *mysqld_chroot;
1209 static const char *default_character_set_name;
1210 static const char *character_set_filesystem_name;
1211 static const char *lc_messages;
1212 static const char *lc_time_names_name;
1213 char *my_bind_addr_str;
1214 char *my_admin_bind_addr_str;
1215 uint mysqld_admin_port;
1216 bool listen_admin_interface_in_separate_thread;
1217 static const char *default_collation_name;
1218 const char *default_storage_engine;
1219 const char *default_tmp_storage_engine;
1220 ulonglong temptable_max_ram;
1221 bool temptable_use_mmap;
1222 static char compiled_default_collation_name[] = MYSQL_DEFAULT_COLLATION_NAME;
1223 static bool binlog_format_used = false;
1224 
1225 LEX_STRING opt_init_connect, opt_init_slave;
1226 
1227 /* Global variables */
1228 
1229 LEX_STRING opt_mandatory_roles;
1230 bool opt_mandatory_roles_cache = false;
1231 bool opt_always_activate_granted_roles = false;
1232 bool opt_bin_log;
1233 bool opt_general_log, opt_slow_log, opt_general_log_raw;
1234 ulonglong log_output_options;
1235 bool opt_log_queries_not_using_indexes = false;
1236 ulong opt_log_throttle_queries_not_using_indexes = 0;
1237 bool opt_log_slow_extra = false;
1238 bool opt_disable_networking = false, opt_skip_show_db = false;
1239 bool opt_skip_name_resolve = false;
1240 bool opt_character_set_client_handshake = true;
1241 bool server_id_supplied = false;
1242 static bool opt_endinfo;
1243 bool using_udf_functions;
1244 bool locked_in_memory;
1245 bool opt_using_transactions;
1246 ulong opt_tc_log_size;
1247 std::atomic<int32> connection_events_loop_aborted_flag;
1248 static std::atomic<enum_server_operational_state> server_operational_state{
1249     SERVER_BOOTING};
1250 char *opt_log_error_suppression_list;
1251 char *opt_log_error_services;
1252 char *opt_keyring_migration_user = nullptr;
1253 char *opt_keyring_migration_host = nullptr;
1254 char *opt_keyring_migration_password = nullptr;
1255 char *opt_keyring_migration_socket = nullptr;
1256 char *opt_keyring_migration_source = nullptr;
1257 char *opt_keyring_migration_destination = nullptr;
1258 ulong opt_keyring_migration_port = 0;
1259 bool migrate_connect_options = false;
1260 uint host_cache_size;
1261 ulong log_error_verbosity = 3;  // have a non-zero value during early start-up
1262 
1263 #if defined(_WIN32)
1264 /*
1265   Thread handle of shutdown event handler thread.
1266   It is used as argument during thread join.
1267 */
1268 my_thread_handle shutdown_restart_thr_handle;
1269 
1270 ulong slow_start_timeout;
1271 bool opt_no_monitor = false;
1272 #endif
1273 
1274 bool opt_no_dd_upgrade = false;
1275 long opt_upgrade_mode = UPGRADE_AUTO;
1276 bool opt_initialize = false;
1277 bool opt_skip_slave_start = false;  ///< If set, slave is not autostarted
1278 bool opt_enable_named_pipe = false;
1279 bool opt_local_infile, opt_slave_compressed_protocol;
1280 bool opt_safe_user_create = false;
1281 bool opt_show_slave_auth_info;
1282 bool opt_log_slave_updates = false;
1283 char *opt_slave_skip_errors;
1284 bool opt_slave_allow_batching = false;
1285 
1286 /**
1287   compatibility option:
1288     - index usage hints (USE INDEX without a FOR clause) behave as in 5.0
1289 */
1290 bool old_mode;
1291 
1292 /*
1293   Legacy global handlerton. These will be removed (please do not add more).
1294 */
1295 handlerton *heap_hton;
1296 handlerton *temptable_hton;
1297 handlerton *myisam_hton;
1298 handlerton *innodb_hton;
1299 
1300 char *opt_disabled_storage_engines;
1301 uint opt_server_id_bits = 0;
1302 ulong opt_server_id_mask = 0;
1303 bool read_only = false, opt_readonly = false;
1304 bool super_read_only = false, opt_super_readonly = false;
1305 bool opt_require_secure_transport = false;
1306 bool relay_log_purge;
1307 bool relay_log_recovery;
1308 bool opt_allow_suspicious_udfs;
1309 const char *opt_secure_file_priv;
1310 bool opt_log_slow_admin_statements = false;
1311 bool opt_log_slow_slave_statements = false;
1312 bool lower_case_file_system = false;
1313 bool opt_large_pages = false;
1314 bool opt_super_large_pages = false;
1315 bool opt_myisam_use_mmap = false;
1316 std::atomic<bool> offline_mode;
1317 uint opt_large_page_size = 0;
1318 uint default_password_lifetime = 0;
1319 bool password_require_current = false;
1320 std::atomic<bool> partial_revokes;
1321 bool opt_partial_revokes;
1322 
1323 mysql_mutex_t LOCK_default_password_lifetime;
1324 mysql_mutex_t LOCK_mandatory_roles;
1325 mysql_mutex_t LOCK_password_history;
1326 mysql_mutex_t LOCK_password_reuse_interval;
1327 mysql_mutex_t LOCK_tls_ctx_options;
1328 mysql_mutex_t LOCK_admin_tls_ctx_options;
1329 
1330 #if defined(ENABLED_DEBUG_SYNC)
1331 MYSQL_PLUGIN_IMPORT uint opt_debug_sync_timeout = 0;
1332 #endif /* defined(ENABLED_DEBUG_SYNC) */
1333 bool opt_old_style_user_limits = false, trust_function_creators = false;
1334 bool check_proxy_users = false, mysql_native_password_proxy_users = false,
1335      sha256_password_proxy_users = false;
1336 /*
1337   True if there is at least one per-hour limit for some user, so we should
1338   check them before each query (and possibly reset counters when hour is
1339   changed). False otherwise.
1340 */
1341 volatile bool mqh_used = false;
1342 bool opt_noacl = false;
1343 bool sp_automatic_privileges = true;
1344 
1345 int32_t opt_regexp_time_limit;
1346 int32_t opt_regexp_stack_limit;
1347 
1348 /** True, if restarted from a cloned database. This information
1349 is needed by GR to set some configurations right after clone. */
1350 bool clone_startup = false;
1351 
1352 /** True, if clone recovery has failed. For managed server we
1353 restart server again with old databse files. */
1354 bool clone_recovery_error = false;
1355 
1356 ulong binlog_row_event_max_size;
1357 ulong binlog_checksum_options;
1358 ulong binlog_row_metadata;
1359 bool opt_master_verify_checksum = false;
1360 bool opt_slave_sql_verify_checksum = true;
1361 const char *binlog_format_names[] = {"MIXED", "STATEMENT", "ROW", NullS};
1362 bool binlog_gtid_simple_recovery;
1363 ulong binlog_error_action;
1364 const char *binlog_error_action_list[] = {"IGNORE_ERROR", "ABORT_SERVER",
1365                                           NullS};
1366 uint32 gtid_executed_compression_period = 0;
1367 bool opt_log_unsafe_statements;
1368 
1369 const char *timestamp_type_names[] = {"UTC", "SYSTEM", NullS};
1370 ulong opt_log_timestamps;
1371 uint mysqld_port, test_flags, select_errors, ha_open_options;
1372 uint mysqld_port_timeout;
1373 ulong delay_key_write_options;
1374 uint protocol_version;
1375 uint lower_case_table_names;
1376 long tc_heuristic_recover;
1377 ulong back_log, connect_timeout, server_id;
1378 ulong table_cache_size;
1379 ulong table_cache_instances;
1380 ulong table_cache_size_per_instance;
1381 ulong schema_def_size;
1382 ulong stored_program_def_size;
1383 ulong table_def_size;
1384 ulong tablespace_def_size;
1385 ulong what_to_log;
1386 ulong slow_launch_time;
1387 std::atomic<int32> atomic_slave_open_temp_tables{0};
1388 ulong open_files_limit, max_binlog_size, max_relay_log_size;
1389 ulong slave_trans_retries;
1390 uint slave_net_timeout;
1391 ulong slave_exec_mode_options;
1392 ulonglong slave_type_conversions_options;
1393 ulong opt_mts_slave_parallel_workers;
1394 ulonglong opt_mts_pending_jobs_size_max;
1395 ulonglong slave_rows_search_algorithms_options;
1396 bool opt_slave_preserve_commit_order;
1397 #ifndef DBUG_OFF
1398 uint slave_rows_last_search_algorithm_used;
1399 #endif
1400 ulong mts_parallel_option;
1401 ulong binlog_cache_size = 0;
1402 ulonglong max_binlog_cache_size = 0;
1403 ulong slave_max_allowed_packet = 0;
1404 ulong binlog_stmt_cache_size = 0;
1405 int32 opt_binlog_max_flush_queue_time = 0;
1406 long opt_binlog_group_commit_sync_delay = 0;
1407 ulong opt_binlog_group_commit_sync_no_delay_count = 0;
1408 ulonglong max_binlog_stmt_cache_size = 0;
1409 ulong refresh_version; /* Increments on each reload */
1410 std::atomic<query_id_t> atomic_global_query_id{1};
1411 ulong aborted_threads;
1412 ulong delayed_insert_timeout, delayed_insert_limit, delayed_queue_size;
1413 ulong delayed_insert_threads, delayed_insert_writes, delayed_rows_in_use;
1414 ulong delayed_insert_errors, flush_time;
1415 ulong specialflag = 0;
1416 ulong binlog_cache_use = 0, binlog_cache_disk_use = 0;
1417 ulong binlog_stmt_cache_use = 0, binlog_stmt_cache_disk_use = 0;
1418 ulong max_connections, max_connect_errors;
1419 ulong rpl_stop_slave_timeout = LONG_TIMEOUT;
1420 bool log_bin_use_v1_row_events = false;
1421 bool thread_cache_size_specified = false;
1422 bool host_cache_size_specified = false;
1423 bool table_definition_cache_specified = false;
1424 ulong locked_account_connection_count = 0;
1425 
1426 /**
1427   Limit of the total number of prepared statements in the server.
1428   Is necessary to protect the server against out-of-memory attacks.
1429 */
1430 ulong max_prepared_stmt_count;
1431 /**
1432   Current total number of prepared statements in the server. This number
1433   is exact, and therefore may not be equal to the difference between
1434   `com_stmt_prepare' and `com_stmt_close' (global status variables), as
1435   the latter ones account for all registered attempts to prepare
1436   a statement (including unsuccessful ones).  Prepared statements are
1437   currently connection-local: if the same SQL query text is prepared in
1438   two different connections, this counts as two distinct prepared
1439   statements.
1440 */
1441 ulong prepared_stmt_count = 0;
1442 ulong current_pid;
1443 uint sync_binlog_period = 0, sync_relaylog_period = 0,
1444      sync_relayloginfo_period = 0, sync_masterinfo_period = 0,
1445      opt_mts_checkpoint_period, opt_mts_checkpoint_group;
1446 ulong expire_logs_days = 0;
1447 ulong binlog_expire_logs_seconds = 0;
1448 /**
1449   Soft upper limit for number of sp_head objects that can be stored
1450   in the sp_cache for one connection.
1451 */
1452 ulong stored_program_cache_size = 0;
1453 /**
1454   Compatibility option to prevent auto upgrade of old temporals
1455   during certain ALTER TABLE operations.
1456 */
1457 bool avoid_temporal_upgrade;
1458 
1459 bool persisted_globals_load = true;
1460 
1461 bool opt_keyring_operations = true;
1462 
1463 bool opt_table_encryption_privilege_check = false;
1464 
1465 const double log_10[] = {
1466     1e000, 1e001, 1e002, 1e003, 1e004, 1e005, 1e006, 1e007, 1e008, 1e009, 1e010,
1467     1e011, 1e012, 1e013, 1e014, 1e015, 1e016, 1e017, 1e018, 1e019, 1e020, 1e021,
1468     1e022, 1e023, 1e024, 1e025, 1e026, 1e027, 1e028, 1e029, 1e030, 1e031, 1e032,
1469     1e033, 1e034, 1e035, 1e036, 1e037, 1e038, 1e039, 1e040, 1e041, 1e042, 1e043,
1470     1e044, 1e045, 1e046, 1e047, 1e048, 1e049, 1e050, 1e051, 1e052, 1e053, 1e054,
1471     1e055, 1e056, 1e057, 1e058, 1e059, 1e060, 1e061, 1e062, 1e063, 1e064, 1e065,
1472     1e066, 1e067, 1e068, 1e069, 1e070, 1e071, 1e072, 1e073, 1e074, 1e075, 1e076,
1473     1e077, 1e078, 1e079, 1e080, 1e081, 1e082, 1e083, 1e084, 1e085, 1e086, 1e087,
1474     1e088, 1e089, 1e090, 1e091, 1e092, 1e093, 1e094, 1e095, 1e096, 1e097, 1e098,
1475     1e099, 1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109,
1476     1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119, 1e120,
1477     1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129, 1e130, 1e131,
1478     1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139, 1e140, 1e141, 1e142,
1479     1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149, 1e150, 1e151, 1e152, 1e153,
1480     1e154, 1e155, 1e156, 1e157, 1e158, 1e159, 1e160, 1e161, 1e162, 1e163, 1e164,
1481     1e165, 1e166, 1e167, 1e168, 1e169, 1e170, 1e171, 1e172, 1e173, 1e174, 1e175,
1482     1e176, 1e177, 1e178, 1e179, 1e180, 1e181, 1e182, 1e183, 1e184, 1e185, 1e186,
1483     1e187, 1e188, 1e189, 1e190, 1e191, 1e192, 1e193, 1e194, 1e195, 1e196, 1e197,
1484     1e198, 1e199, 1e200, 1e201, 1e202, 1e203, 1e204, 1e205, 1e206, 1e207, 1e208,
1485     1e209, 1e210, 1e211, 1e212, 1e213, 1e214, 1e215, 1e216, 1e217, 1e218, 1e219,
1486     1e220, 1e221, 1e222, 1e223, 1e224, 1e225, 1e226, 1e227, 1e228, 1e229, 1e230,
1487     1e231, 1e232, 1e233, 1e234, 1e235, 1e236, 1e237, 1e238, 1e239, 1e240, 1e241,
1488     1e242, 1e243, 1e244, 1e245, 1e246, 1e247, 1e248, 1e249, 1e250, 1e251, 1e252,
1489     1e253, 1e254, 1e255, 1e256, 1e257, 1e258, 1e259, 1e260, 1e261, 1e262, 1e263,
1490     1e264, 1e265, 1e266, 1e267, 1e268, 1e269, 1e270, 1e271, 1e272, 1e273, 1e274,
1491     1e275, 1e276, 1e277, 1e278, 1e279, 1e280, 1e281, 1e282, 1e283, 1e284, 1e285,
1492     1e286, 1e287, 1e288, 1e289, 1e290, 1e291, 1e292, 1e293, 1e294, 1e295, 1e296,
1493     1e297, 1e298, 1e299, 1e300, 1e301, 1e302, 1e303, 1e304, 1e305, 1e306, 1e307,
1494     1e308};
1495 
1496 /* Index extention. */
1497 const int index_ext_length = 6;
1498 const char *index_ext = ".index";
1499 const int relay_ext_length = 10;
1500 const char *relay_ext = "-relay-bin";
1501 /* True if --log-bin option is used. */
1502 bool log_bin_supplied = false;
1503 
1504 time_t server_start_time, flush_status_time;
1505 
1506 char server_uuid[UUID_LENGTH + 1];
1507 const char *server_uuid_ptr;
1508 char mysql_home[FN_REFLEN], pidfile_name[FN_REFLEN], system_time_zone[30];
1509 char default_logfile_name[FN_REFLEN];
1510 char default_binlogfile_name[FN_REFLEN];
1511 char default_binlog_index_name[FN_REFLEN + index_ext_length];
1512 char default_relaylogfile_name[FN_REFLEN + relay_ext_length];
1513 char default_relaylog_index_name[FN_REFLEN + relay_ext_length +
1514                                  index_ext_length];
1515 char *default_tz_name;
1516 static char errorlog_filename_buff[FN_REFLEN];
1517 const char *log_error_dest;
1518 const char *my_share_dir[FN_REFLEN];
1519 char glob_hostname[HOSTNAME_LENGTH + 1];
1520 char mysql_real_data_home[FN_REFLEN], lc_messages_dir[FN_REFLEN],
1521     reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN], *opt_init_file;
1522 const char *opt_tc_log_file;
1523 char *lc_messages_dir_ptr;
1524 char mysql_unpacked_real_data_home[FN_REFLEN];
1525 size_t mysql_unpacked_real_data_home_len;
1526 size_t mysql_data_home_len = 1;
1527 uint reg_ext_length;
1528 char logname_path[FN_REFLEN];
1529 char slow_logname_path[FN_REFLEN];
1530 char secure_file_real_path[FN_REFLEN];
1531 Time_zone *default_tz;
1532 char *mysql_data_home = const_cast<char *>(".");
1533 const char *mysql_real_data_home_ptr = mysql_real_data_home;
1534 char *opt_protocol_compression_algorithms;
1535 char server_version[SERVER_VERSION_LENGTH];
1536 const char *mysqld_unix_port;
1537 char *opt_mysql_tmpdir;
1538 
1539 /** name of reference on left expression in rewritten IN subquery */
1540 const char *in_left_expr_name = "<left expr>";
1541 
1542 my_decimal decimal_zero;
1543 /** Number of connection errors from internal server errors. */
1544 ulong connection_errors_internal = 0;
1545 /** Number of errors when reading the peer address. */
1546 ulong connection_errors_peer_addr = 0;
1547 
1548 /* classes for comparation parsing/processing */
1549 Eq_creator eq_creator;
1550 Ne_creator ne_creator;
1551 Equal_creator equal_creator;
1552 Gt_creator gt_creator;
1553 Lt_creator lt_creator;
1554 Ge_creator ge_creator;
1555 Le_creator le_creator;
1556 
1557 Rpl_global_filter rpl_global_filter;
1558 Rpl_filter *binlog_filter;
1559 
1560 struct System_variables global_system_variables;
1561 struct System_variables max_system_variables;
1562 struct System_status_var global_status_var;
1563 
1564 MY_TMPDIR mysql_tmpdir_list;
1565 
1566 CHARSET_INFO *system_charset_info, *files_charset_info;
1567 CHARSET_INFO *national_charset_info, *table_alias_charset;
1568 CHARSET_INFO *character_set_filesystem;
1569 
1570 MY_LOCALE *my_default_lc_messages;
1571 MY_LOCALE *my_default_lc_time_names;
1572 
1573 SHOW_COMP_OPTION have_symlink, have_dlopen, have_query_cache;
1574 SHOW_COMP_OPTION have_geometry, have_rtree_keys;
1575 SHOW_COMP_OPTION have_compress;
1576 SHOW_COMP_OPTION have_profiling;
1577 SHOW_COMP_OPTION have_statement_timeout = SHOW_OPTION_DISABLED;
1578 
1579 /* Thread specific variables */
1580 
1581 thread_local MEM_ROOT **THR_MALLOC = nullptr;
1582 
1583 mysql_mutex_t LOCK_status, LOCK_uuid_generator, LOCK_crypt,
1584     LOCK_global_system_variables, LOCK_user_conn, LOCK_error_messages;
1585 mysql_mutex_t LOCK_sql_rand;
1586 
1587 /**
1588   The below lock protects access to two global server variables:
1589   max_prepared_stmt_count and prepared_stmt_count. These variables
1590   set the limit and hold the current total number of prepared statements
1591   in the server, respectively. As PREPARE/DEALLOCATE rate in a loaded
1592   server may be fairly high, we need a dedicated lock.
1593 */
1594 mysql_mutex_t LOCK_prepared_stmt_count;
1595 
1596 /*
1597  The below two locks are introduced as guards (second mutex) for
1598   the global variables sql_slave_skip_counter and slave_net_timeout
1599   respectively. See fix_slave_skip_counter/fix_slave_net_timeout
1600   for more details
1601 */
1602 mysql_mutex_t LOCK_sql_slave_skip_counter;
1603 mysql_mutex_t LOCK_slave_net_timeout;
1604 mysql_mutex_t LOCK_slave_trans_dep_tracker;
1605 mysql_mutex_t LOCK_log_throttle_qni;
1606 mysql_rwlock_t LOCK_sys_init_connect, LOCK_sys_init_slave;
1607 mysql_rwlock_t LOCK_system_variables_hash;
1608 my_thread_handle signal_thread_id;
1609 sigset_t mysqld_signal_mask;
1610 my_thread_attr_t connection_attrib;
1611 mysql_mutex_t LOCK_server_started;
1612 mysql_cond_t COND_server_started;
1613 mysql_mutex_t LOCK_reset_gtid_table;
1614 mysql_mutex_t LOCK_compress_gtid_table;
1615 mysql_cond_t COND_compress_gtid_table;
1616 mysql_mutex_t LOCK_collect_instance_log;
1617 #if !defined(_WIN32)
1618 mysql_mutex_t LOCK_socket_listener_active;
1619 mysql_cond_t COND_socket_listener_active;
1620 mysql_mutex_t LOCK_start_signal_handler;
1621 mysql_cond_t COND_start_signal_handler;
1622 #endif
1623 
1624 /*
1625   The below lock protects access to global server variable
1626   keyring_operations.
1627 */
1628 mysql_mutex_t LOCK_keyring_operations;
1629 /*
1630   The below lock protects to execute commands 'ALTER INSTANCE ROTATE BINLOG
1631   MASTER KEY' and 'SET @@GLOBAL.binlog_encryption=ON/OFF' in parallel.
1632 */
1633 mysql_mutex_t LOCK_rotate_binlog_master_key;
1634 
1635 bool mysqld_server_started = false;
1636 /**
1637   Set to true to signal at startup if the process must die.
1638 
1639   Needed because kill_mysql() will not do anything before
1640   the server is fully initialized. Thus it now just sets this
1641   flag to on and exits. And then mysqld_main() will check if
1642   the flag is on at the right place and exit the process if it
1643   is.
1644 */
1645 static bool mysqld_process_must_end_at_startup = false;
1646 
1647 /* replication parameters, if master_host is not NULL, we are a slave */
1648 uint report_port = 0;
1649 ulong master_retry_count = 0;
1650 const char *master_info_file;
1651 const char *relay_log_info_file;
1652 char *report_user, *report_password, *report_host;
1653 char *opt_relay_logname = nullptr, *opt_relaylog_index_name = nullptr;
1654 /*
1655   True if the --relay-log-index is set by users from
1656   config file or command line.
1657 */
1658 bool opt_relaylog_index_name_supplied = false;
1659 /*
1660   True if the --relay-log is set by users from
1661   config file or command line.
1662 */
1663 bool opt_relay_logname_supplied = false;
1664 /*
1665   True if --log-slave-updates option is set explicitly
1666   on command line or configuration file.
1667 */
1668 bool log_slave_updates_supplied = false;
1669 
1670 /*
1671   True if --slave-preserve-commit-order-supplied option is set explicitly
1672   on command line or configuration file.
1673 */
1674 bool slave_preserve_commit_order_supplied = false;
1675 char *opt_general_logname, *opt_slow_logname, *opt_bin_logname;
1676 
1677 /*
1678   True if expire_logs_days and binlog_expire_logs_seconds is set
1679   explictly.
1680 */
1681 bool expire_logs_days_supplied = false;
1682 bool binlog_expire_logs_seconds_supplied = false;
1683 /* Static variables */
1684 
1685 static bool opt_myisam_log;
1686 static int cleanup_done;
1687 static ulong opt_specialflag;
1688 char *opt_binlog_index_name;
1689 char *mysql_home_ptr, *pidfile_name_ptr;
1690 char *default_auth_plugin;
1691 /**
1692   Memory for allocating command line arguments, after load_defaults().
1693 */
1694 static MEM_ROOT argv_alloc{PSI_NOT_INSTRUMENTED, 512};
1695 /** Remaining command line arguments (count), filtered by handle_options().*/
1696 static int remaining_argc;
1697 /** Remaining command line arguments (arguments), filtered by
1698  * handle_options().*/
1699 static char **remaining_argv;
1700 
1701 /**
1702  Holds the "original" (i.e. as on startup) set of arguments.
1703 
1704  The argument processing goes as follows:
1705  1. At startup the "original" set of arguments is shallow-copied into
1706  the read only list @ref orig_argv.
1707  2. The config file arguments are read from the config files (.cnf and
1708    persisted read-only) and are appended as command line arguments.
1709    In the process the argv is deep copied because of the expansion
1710  3. The result from 2 is set into @ref remaining_argv / @ref remaining_argc.
1711  4. Then remaining_argv is fed into various consumers:
1712    - the server compiled in set of arguments
1713    - the early plugins
1714    - the rest of the plugins
1715    - the error log
1716    - the components from the persisted dynamic loader init.
1717    All of the above "take away" the values they match from the extended
1718    command line set. And vary the values of @ref my_getopt_skip_unknown
1719    according to their needs (mostly keep it set).
1720    As a result, when the server is done booting up the things that remain
1721    in remaining_argv become less and less.
1722  5. When the bootstrap process is done a check is run:
1723     my_getopt_skip_unknown is set to off and the argument parser is called
1724     on remaining_argv with an empty set of argument definitions.
1725     This ensures that all of the remaining argument values in remaining_argv
1726     are either marked as "loose" (i.e. optional) or are "consumed" by prior
1727     argument list processings.
1728     The side effect of this is that all --loose arguments are also consumed
1729     out of remaining_argv.
1730  6. A check is made if the remaining_argv is an empty list. If not the server
1731     exits.
1732  7. At this point the server is marked as succesfully started.
1733  8. Subsequent argument processings happen when e.g. a plugin is loaded via
1734     @ref mysql_install_plugin or a component registers system variables via
1735     @ref mysql_component_sys_variable_imp::register_variable. However, since
1736     remaining_argv is empty these need to run over the orig_argc/orig_argv.
1737     But argument value assignment would normally "eat" out the values found.
1738     This would mean that the orig_argv array will get shortened and if you
1739     load the same plugin twice for example its system variables will not have
1740     the values supplied the second time they start.
1741     Thus once the server is started (@ref mysqld_server_started is on) any
1742     argument value parsing should happen over a *copy* of orig_argc/orig_argv
1743     that should subsequently be discarded.
1744     @ref remaining_argv should not be consulted anymore at this point.
1745 */
1746 int orig_argc;
1747 char **orig_argv;
1748 namespace {
1749 FILE *nstdout = nullptr;
1750 char my_progpath[FN_REFLEN];
1751 const char *my_orig_progname = nullptr;
1752 
1753 /**
1754   This variable holds the exit value of the signal handler thread.
1755 */
1756 std::atomic<int> signal_hand_thr_exit_code(MYSQLD_SUCCESS_EXIT);
1757 
1758 /**
1759   Inspects the program name in argv[0] and substitutes the full path
1760   of the executable.
1761 
1762   @param argv argument vector (array) for executable.
1763  */
substitute_progpath(char ** argv)1764 void substitute_progpath(char **argv) {
1765   if (test_if_hard_path(argv[0])) return;
1766 
1767 #if defined(_WIN32)
1768   if (GetModuleFileName(NULL, my_progpath, sizeof(my_progpath))) {
1769     my_orig_progname = argv[0];
1770     argv[0] = my_progpath;
1771   }
1772 #else
1773   /* If the path has a directory component, use my_realpath()
1774      (implicitly relative to cwd) */
1775   if (strchr(argv[0], FN_LIBCHAR) != nullptr &&
1776       !my_realpath(my_progpath, argv[0], MYF(0))) {
1777     my_orig_progname = argv[0];
1778     argv[0] = my_progpath;
1779     return;
1780   }
1781 
1782   // my_realpath() cannot resolve it, it must be a bare executable
1783   // name in path
1784   DBUG_ASSERT(strchr(argv[0], FN_LIBCHAR) == nullptr);
1785 
1786   const char *spbegin = getenv("PATH");
1787   if (spbegin == nullptr) spbegin = "";
1788   const char *spend = spbegin + strlen(spbegin);
1789 
1790   while (true) {
1791     const char *colonend = std::find(spbegin, spend, ':');
1792     std::string cand{spbegin, colonend};
1793     spbegin = colonend + 1;
1794 
1795     cand.append(1, '/');
1796     cand.append(argv[0]);
1797 
1798     if (my_access(cand.c_str(), X_OK) == 0) {
1799       if (my_realpath(my_progpath, cand.c_str(), MYF(0))) {
1800         // Fallback to raw cand
1801         DBUG_ASSERT(cand.length() < FN_REFLEN);
1802         std::copy(cand.begin(), cand.end(), my_progpath);
1803         my_progpath[cand.length()] = '\0';
1804       }
1805       my_orig_progname = argv[0];
1806       argv[0] = my_progpath;
1807       break;
1808     }
1809     if (colonend == spend) {
1810       DBUG_ASSERT(false);
1811       break;
1812     }
1813   }  // while (true)
1814 #endif  // defined(_WIN32)
1815   if (my_orig_progname == nullptr) {
1816     LogErr(WARNING_LEVEL, ER_FAILED_TO_GET_ABSOLUTE_PATH, argv[0]);
1817   }
1818 }
1819 }  // namespace
1820 
1821 static Connection_acceptor<Mysqld_socket_listener> *mysqld_socket_acceptor =
1822     nullptr;
1823 #ifdef _WIN32
1824 static Named_pipe_listener *named_pipe_listener = NULL;
1825 Connection_acceptor<Named_pipe_listener> *named_pipe_acceptor = NULL;
1826 Connection_acceptor<Shared_mem_listener> *shared_mem_acceptor = NULL;
1827 mysql_rwlock_t LOCK_named_pipe_full_access_group;
1828 char *named_pipe_full_access_group;
1829 #endif
1830 
1831 Checkable_rwlock *global_sid_lock = nullptr;
1832 Sid_map *global_sid_map = nullptr;
1833 Gtid_state *gtid_state = nullptr;
1834 Gtid_table_persistor *gtid_table_persistor = nullptr;
1835 
1836 /* cache for persisted variables */
1837 static Persisted_variables_cache persisted_variables_cache;
1838 
set_remaining_args(int argc,char ** argv)1839 void set_remaining_args(int argc, char **argv) {
1840   remaining_argc = argc;
1841   remaining_argv = argv;
1842 }
1843 
get_remaining_argc()1844 int *get_remaining_argc() { return &remaining_argc; }
1845 
get_remaining_argv()1846 char ***get_remaining_argv() { return &remaining_argv; }
1847 
1848 /*
1849   Multiple threads of execution use the random state maintained in global
1850   sql_rand to generate random numbers. sql_rnd_with_mutex use mutex
1851   LOCK_sql_rand to protect sql_rand across multiple instantiations that use
1852   sql_rand to generate random numbers.
1853  */
sql_rnd_with_mutex()1854 ulong sql_rnd_with_mutex() {
1855   mysql_mutex_lock(&LOCK_sql_rand);
1856   ulong tmp =
1857       (ulong)(my_rnd(&sql_rand) * 0xffffffff); /* make all bits random */
1858   mysql_mutex_unlock(&LOCK_sql_rand);
1859   return tmp;
1860 }
1861 
get_thd_status_var(THD * thd,bool * aggregated)1862 struct System_status_var *get_thd_status_var(THD *thd, bool *aggregated) {
1863   *aggregated = thd->status_var_aggregated;
1864   return &thd->status_var;
1865 }
1866 
option_error_reporter(enum loglevel level,uint ecode,...)1867 static void option_error_reporter(enum loglevel level, uint ecode, ...) {
1868   va_list args;
1869   va_start(args, ecode);
1870 
1871   /*
1872     Don't print warnings for --loose options during initialize.
1873   */
1874   if (level == ERROR_LEVEL || !opt_initialize || (log_error_verbosity > 1)) {
1875     error_log_print(level, ecode, args);
1876   }
1877   va_end(args);
1878 }
1879 
1880 /**
1881   Character set and collation error reporter that prints to sql error log.
1882   @param level          log message level
1883   @param ecode          Error code of the error message.
1884 
1885   This routine is used to print character set and collation
1886   warnings and errors inside an already running mysqld server,
1887   e.g. when a character set or collation is requested for the very first time
1888   and its initialization does not go well for some reasons.
1889 */
1890 
charset_error_reporter(enum loglevel level,uint ecode,...)1891 static void charset_error_reporter(enum loglevel level, uint ecode, ...) {
1892   va_list args;
1893   va_start(args, ecode);
1894   error_log_print(level, ecode, args);
1895   va_end(args);
1896 }
1897 
1898 struct rand_struct sql_rand;  ///< used by sql_class.cc:THD::THD()
1899 
1900 #ifndef _WIN32
1901 PasswdValue user_info;
1902 static my_thread_t main_thread_id;
1903 #endif  // !_WIN32
1904 
1905 /* OS specific variables */
1906 
1907 #ifdef _WIN32
1908 static bool mysqld_early_option = false;
1909 static bool windows_service = false;
1910 static bool use_opt_args;
1911 static int opt_argc;
1912 static char **opt_argv;
1913 static char **my_global_argv = nullptr;
1914 static int my_global_argc;
1915 
1916 static mysql_mutex_t LOCK_handler_count;
1917 static mysql_cond_t COND_handler_count;
1918 static HANDLE hEventShutdown;
1919 static HANDLE hEventRestart;
1920 const char *shared_memory_base_name = default_shared_memory_base_name;
1921 bool opt_enable_shared_memory;
1922 static char shutdown_event_name[40];
1923 static char restart_event_name[40];
1924 static NTService Service;  ///< Service object for WinNT
1925 #endif                     /* _WIN32 */
1926 
1927 static bool dynamic_plugins_are_initialized = false;
1928 
1929 #ifndef DBUG_OFF
1930 static const char *default_dbug_option;
1931 #endif
1932 
1933 #ifndef XTRABACKUP
1934 bool opt_use_ssl = true;
1935 bool opt_use_admin_ssl = true;
1936 ulong opt_ssl_fips_mode = SSL_FIPS_MODE_OFF;
1937 #endif
1938 
1939 /* Function declarations */
1940 
1941 static int mysql_init_variables();
1942 static int get_options(int *argc_ptr, char ***argv_ptr);
1943 static void add_terminator(vector<my_option> *options);
1944 extern "C" bool mysqld_get_one_option(int, const struct my_option *, char *);
1945 static void set_server_version(void);
1946 static int init_thread_environment();
1947 static const char *get_relative_path(const char *path);
1948 static int fix_paths(void);
1949 static int test_if_case_insensitive(const char *dir_name);
1950 static void end_ssl();
1951 static void delete_dictionary_tablespace();
1952 
1953 extern "C" void *signal_hand(void *arg);
1954 static bool pid_file_created = false;
1955 static void usage(void);
1956 static void clean_up_mutexes(void);
1957 static bool create_pid_file();
1958 static void mysqld_exit(int exit_code) MY_ATTRIBUTE((noreturn));
1959 static void delete_pid_file(myf flags);
1960 static void clean_up(bool print_message);
1961 static int handle_early_options();
1962 static void adjust_related_options(ulong *requested_open_files);
1963 static void process_bootstrap();
1964 #ifdef HAVE_PSI_INTERFACE
1965 static void init_server_psi_keys();
1966 #endif
1967 
1968 /**
1969   Notify any waiters that the server components have been initialized.
1970   Used by the signal handler thread and by Cluster.
1971 
1972   @see signal_hand
1973 */
1974 
server_components_initialized()1975 static void server_components_initialized() {
1976   mysql_mutex_lock(&LOCK_server_started);
1977   mysqld_server_started = true;
1978   mysql_cond_broadcast(&COND_server_started);
1979   mysql_mutex_unlock(&LOCK_server_started);
1980 }
1981 
1982 SERVICE_TYPE(mysql_runtime_error) * error_service;
1983 SERVICE_TYPE(mysql_psi_system_v1) * system_service;
1984 SERVICE_TYPE(mysql_rwlock_v1) * rwlock_service;
1985 SERVICE_TYPE_NO_CONST(registry) * srv_registry;
1986 SERVICE_TYPE(dynamic_loader_scheme_file) * scheme_file_srv;
1987 using loader_type_t = SERVICE_TYPE_NO_CONST(dynamic_loader);
1988 using runtime_error_type_t = SERVICE_TYPE_NO_CONST(mysql_runtime_error);
1989 using psi_system_type_t = SERVICE_TYPE_NO_CONST(mysql_psi_system_v1);
1990 using rwlock_type_t = SERVICE_TYPE_NO_CONST(mysql_rwlock_v1);
1991 using loader_scheme_type_t = SERVICE_TYPE_NO_CONST(dynamic_loader_scheme_file);
1992 extern REQUIRES_SERVICE_PLACEHOLDER(mysql_rwlock_v1);
1993 extern REQUIRES_SERVICE_PLACEHOLDER(mysql_psi_system_v1);
1994 extern bool initialize_minimal_chassis(SERVICE_TYPE_NO_CONST(registry) *
1995                                        *registry);
1996 extern bool deinitialize_minimal_chassis(SERVICE_TYPE_NO_CONST(registry) *
1997                                          registry);
1998 
1999 /**
2000   Initializes component infrastructure by bootstrapping core component
2001   subsystem.
2002 
2003   @return Status of performed operation
2004   @retval false success
2005   @retval true failure
2006 */
component_infrastructure_init()2007 bool component_infrastructure_init() {
2008   if (initialize_minimal_chassis(&srv_registry)) {
2009     LogErr(ERROR_LEVEL, ER_COMPONENTS_INFRASTRUCTURE_BOOTSTRAP);
2010     return true;
2011   }
2012   /* Here minimal_chassis dynamic_loader_scheme_file service has
2013      to be acquired */
2014   srv_registry->acquire(
2015       "dynamic_loader_scheme_file.mysql_minimal_chassis",
2016       reinterpret_cast<my_h_service *>(
2017           const_cast<loader_scheme_type_t **>(&scheme_file_srv)));
2018 
2019   srv_registry->acquire("dynamic_loader",
2020                         reinterpret_cast<my_h_service *>(
2021                             const_cast<loader_type_t **>(&dynamic_loader_srv)));
2022 
2023   my_service<SERVICE_TYPE(registry_registration)> registrator(
2024       "registry_registration", srv_registry);
2025 
2026   // Sets default file scheme loader for MySQL server.
2027   registrator->set_default(
2028       "dynamic_loader_scheme_file.mysql_server_path_filter");
2029 
2030   // Sets default rw_lock for MySQL server.
2031   registrator->set_default("mysql_rwlock_v1.mysql_server");
2032   srv_registry->acquire("mysql_rwlock_v1.mysql_server",
2033                         reinterpret_cast<my_h_service *>(
2034                             const_cast<rwlock_type_t **>(&rwlock_service)));
2035   mysql_service_mysql_rwlock_v1 =
2036       reinterpret_cast<SERVICE_TYPE(mysql_rwlock_v1) *>(rwlock_service);
2037 
2038   // Sets default psi_system event service for MySQL server.
2039   registrator->set_default("mysql_psi_system_v1.mysql_server");
2040   srv_registry->acquire("mysql_psi_system_v1.mysql_server",
2041                         reinterpret_cast<my_h_service *>(
2042                             const_cast<psi_system_type_t **>(&system_service)));
2043   /* This service variable is needed for mysql_unload_plugin */
2044   mysql_service_mysql_psi_system_v1 =
2045       reinterpret_cast<SERVICE_TYPE(mysql_psi_system_v1) *>(system_service);
2046 
2047   // Sets default mysql_runtime_error for MySQL server.
2048   registrator->set_default("mysql_runtime_error.mysql_server");
2049   srv_registry->acquire(
2050       "mysql_runtime_error.mysql_server",
2051       reinterpret_cast<my_h_service *>(
2052           const_cast<runtime_error_type_t **>(&error_service)));
2053   /* This service variable is needed where ever mysql_error_service_printf()
2054      service api is used */
2055   mysql_service_mysql_runtime_error =
2056       reinterpret_cast<SERVICE_TYPE(mysql_runtime_error) *>(error_service);
2057 
2058   return false;
2059 }
2060 
2061 /**
2062   This function is used to initialize the mysql_server component services.
2063 */
server_component_init()2064 static void server_component_init() { mysql_comp_sys_var_services_init(); }
2065 
2066 /**
2067   Initializes MySQL Server component infrastructure part by initialize of
2068   dynamic loader persistence.
2069 
2070   @return Status of performed operation
2071   @retval false success
2072   @retval true failure
2073 */
2074 
mysql_component_infrastructure_init()2075 static bool mysql_component_infrastructure_init() {
2076   /* We need a temporary THD during boot */
2077   Auto_THD thd;
2078   Disable_autocommit_guard autocommit_guard(thd.thd);
2079   dd::cache::Dictionary_client::Auto_releaser scope_releaser(
2080       thd.thd->dd_client());
2081   if (persistent_dynamic_loader_init(thd.thd)) {
2082     LogErr(ERROR_LEVEL, ER_COMPONENTS_PERSIST_LOADER_BOOTSTRAP);
2083     trans_rollback_stmt(thd.thd);
2084     // Full rollback in case we have THD::transaction_rollback_request.
2085     trans_rollback(thd.thd);
2086     return true;
2087   }
2088   server_component_init();
2089   return trans_commit_stmt(thd.thd) || trans_commit(thd.thd);
2090 }
2091 
2092 /**
2093   De-initializes Component infrastructure by de-initialization of the MySQL
2094   Server services (persistent dynamic loader) followed by de-initailization of
2095   the core Components infrostructure.
2096 
2097   @return Status of performed operation
2098   @retval false success
2099   @retval true failure
2100 */
component_infrastructure_deinit()2101 bool component_infrastructure_deinit() {
2102   persistent_dynamic_loader_deinit();
2103 
2104   srv_registry->release(reinterpret_cast<my_h_service>(
2105       const_cast<loader_scheme_type_t *>(scheme_file_srv)));
2106   srv_registry->release(reinterpret_cast<my_h_service>(
2107       const_cast<loader_type_t *>(dynamic_loader_srv)));
2108   srv_registry->release(reinterpret_cast<my_h_service>(
2109       const_cast<runtime_error_type_t *>(error_service)));
2110   srv_registry->release(reinterpret_cast<my_h_service>(
2111       const_cast<psi_system_type_t *>(system_service)));
2112   srv_registry->release(reinterpret_cast<my_h_service>(
2113       const_cast<rwlock_type_t *>(rwlock_service)));
2114 
2115   if (deinitialize_minimal_chassis(srv_registry)) {
2116     LogErr(ERROR_LEVEL, ER_COMPONENTS_INFRASTRUCTURE_SHUTDOWN);
2117     return true;
2118   }
2119   return false;
2120 }
2121 
2122 /**
2123   Block and wait until server components have been initialized.
2124 */
2125 
server_components_init_wait()2126 static void server_components_init_wait() {
2127   mysql_mutex_lock(&LOCK_server_started);
2128   while (!mysqld_server_started)
2129     mysql_cond_wait(&COND_server_started, &LOCK_server_started);
2130   mysql_mutex_unlock(&LOCK_server_started);
2131 }
2132 
2133 /****************************************************************************
2134 ** Code to end mysqld
2135 ****************************************************************************/
2136 
2137 /**
2138   This class implements callback function used by close_connections()
2139   to set KILL_CONNECTION flag on all thds in thd list.
2140   If m_kill_dump_thread_flag is not set it kills all other threads
2141   except dump threads. If this flag is set, it kills dump threads.
2142 */
2143 class Set_kill_conn : public Do_THD_Impl {
2144  private:
2145   int m_dump_thread_count;
2146   bool m_kill_dump_threads_flag;
2147 
2148  public:
Set_kill_conn()2149   Set_kill_conn() : m_dump_thread_count(0), m_kill_dump_threads_flag(false) {}
2150 
set_dump_thread_flag()2151   void set_dump_thread_flag() { m_kill_dump_threads_flag = true; }
2152 
get_dump_thread_count() const2153   int get_dump_thread_count() const { return m_dump_thread_count; }
2154 
operator ()(THD * killing_thd)2155   virtual void operator()(THD *killing_thd) {
2156     DBUG_PRINT("quit", ("Informing thread %u that it's time to die",
2157                         killing_thd->thread_id()));
2158     if (!m_kill_dump_threads_flag) {
2159       // We skip slave threads & scheduler on this first loop through.
2160       if (killing_thd->slave_thread) return;
2161 
2162       if (killing_thd->get_command() == COM_BINLOG_DUMP ||
2163           killing_thd->get_command() == COM_BINLOG_DUMP_GTID) {
2164         ++m_dump_thread_count;
2165         return;
2166       }
2167       DBUG_EXECUTE_IF("Check_dump_thread_is_alive", {
2168         DBUG_ASSERT(killing_thd->get_command() != COM_BINLOG_DUMP &&
2169                     killing_thd->get_command() != COM_BINLOG_DUMP_GTID);
2170       };);
2171     }
2172     mysql_mutex_lock(&killing_thd->LOCK_thd_data);
2173 
2174     if (killing_thd->kill_immunizer) {
2175       /*
2176         If killing_thd is in kill immune mode (i.e. operation on new DD tables
2177         is in progress) then just save state_to_set with THD::kill_immunizer
2178         object.
2179 
2180         While exiting kill immune mode, awake() is called again with the killed
2181         state saved in THD::kill_immunizer object.
2182       */
2183       killing_thd->kill_immunizer->save_killed_state(THD::KILL_CONNECTION);
2184     } else {
2185       killing_thd->killed = THD::KILL_CONNECTION;
2186 
2187       MYSQL_CALLBACK(Connection_handler_manager::event_functions,
2188                      post_kill_notification, (killing_thd));
2189     }
2190 
2191     if (killing_thd->is_killable && killing_thd->kill_immunizer == nullptr) {
2192       mysql_mutex_lock(&killing_thd->LOCK_current_cond);
2193       if (killing_thd->current_cond.load()) {
2194         mysql_mutex_lock(killing_thd->current_mutex);
2195         mysql_cond_broadcast(killing_thd->current_cond);
2196         mysql_mutex_unlock(killing_thd->current_mutex);
2197       }
2198       mysql_mutex_unlock(&killing_thd->LOCK_current_cond);
2199     }
2200     mysql_mutex_unlock(&killing_thd->LOCK_thd_data);
2201   }
2202 };
2203 
2204 /**
2205   This class implements callback function used by close_connections()
2206   to close vio connection for all thds in thd list
2207 */
2208 class Call_close_conn : public Do_THD_Impl {
2209  public:
Call_close_conn(bool server_shutdown)2210   Call_close_conn(bool server_shutdown) : is_server_shutdown(server_shutdown) {}
2211 
operator ()(THD * closing_thd)2212   virtual void operator()(THD *closing_thd) {
2213     if (closing_thd->get_protocol()->connection_alive()) {
2214       LEX_CSTRING main_sctx_user = closing_thd->m_main_security_ctx.user();
2215       LogErr(WARNING_LEVEL, ER_FORCE_CLOSE_THREAD, my_progname,
2216              (long)closing_thd->thread_id(),
2217              (main_sctx_user.length ? main_sctx_user.str : ""));
2218       /*
2219         Do not generate MYSQL_AUDIT_CONNECTION_DISCONNECT event, when closing
2220         thread close sessions. Each session will generate DISCONNECT event by
2221         itself.
2222       */
2223       close_connection(closing_thd, 0, is_server_shutdown, false);
2224     }
2225   }
2226 
2227  private:
2228   bool is_server_shutdown;
2229 };
2230 
close_connections(void)2231 static void close_connections(void) {
2232   DBUG_TRACE;
2233   (void)RUN_HOOK(server_state, before_server_shutdown, (nullptr));
2234 
2235   Per_thread_connection_handler::kill_blocked_pthreads();
2236 
2237   uint dump_thread_count = 0;
2238   uint dump_thread_kill_retries = 8;
2239 
2240   // Close listeners.
2241   if (mysqld_socket_acceptor != nullptr)
2242     mysqld_socket_acceptor->close_listener();
2243 #ifdef _WIN32
2244   if (named_pipe_acceptor != NULL) named_pipe_acceptor->close_listener();
2245 
2246   if (shared_mem_acceptor != NULL) shared_mem_acceptor->close_listener();
2247 #endif
2248 
2249   /*
2250     First signal all threads that it's time to die
2251     This will give the threads some time to gracefully abort their
2252     statements and inform their clients that the server is about to die.
2253   */
2254 
2255   Global_THD_manager *thd_manager = Global_THD_manager::get_instance();
2256   LogErr(INFORMATION_LEVEL, ER_DEPART_WITH_GRACE,
2257          static_cast<int>(thd_manager->get_thd_count()));
2258 
2259   Set_kill_conn set_kill_conn;
2260   thd_manager->do_for_all_thd(&set_kill_conn);
2261   LogErr(INFORMATION_LEVEL, ER_SHUTTING_DOWN_SLAVE_THREADS);
2262   end_slave();
2263 
2264   if (set_kill_conn.get_dump_thread_count()) {
2265     /*
2266       Replication dump thread should be terminated after the clients are
2267       terminated. Wait for few more seconds for other sessions to end.
2268      */
2269     while (thd_manager->get_thd_count() > dump_thread_count &&
2270            dump_thread_kill_retries) {
2271       sleep(1);
2272       dump_thread_kill_retries--;
2273     }
2274     set_kill_conn.set_dump_thread_flag();
2275     thd_manager->do_for_all_thd(&set_kill_conn);
2276   }
2277 
2278   // Disable the event scheduler
2279   Events::stop();
2280 
2281   if (thd_manager->get_thd_count() > 0) sleep(2);  // Give threads time to die
2282 
2283   /*
2284     Force remaining threads to die by closing the connection to the client
2285     This will ensure that threads that are waiting for a command from the
2286     client on a blocking read call are aborted.
2287   */
2288 
2289   LogErr(INFORMATION_LEVEL, ER_DISCONNECTING_REMAINING_CLIENTS,
2290          static_cast<int>(thd_manager->get_thd_count()));
2291 
2292   Call_close_conn call_close_conn(true);
2293   thd_manager->do_for_all_thd(&call_close_conn);
2294 
2295   (void)RUN_HOOK(server_state, after_server_shutdown, (nullptr));
2296 
2297   /*
2298     All threads have now been aborted. Stop event scheduler thread
2299     after aborting all client connections, otherwise user may
2300     start/stop event scheduler after Events::deinit() deallocates
2301     scheduler object(static member in Events class)
2302   */
2303   Events::deinit();
2304   DBUG_PRINT("quit", ("Waiting for threads to die (count=%u)",
2305                       thd_manager->get_thd_count()));
2306   thd_manager->wait_till_no_thd();
2307   /*
2308     Connection threads might take a little while to go down after removing from
2309     global thread list. Give it some time.
2310   */
2311   Connection_handler_manager::wait_till_no_connection();
2312 
2313   delete_slave_info_objects();
2314   DBUG_PRINT("quit", ("close_connections thread"));
2315 }
2316 
signal_restart_server()2317 bool signal_restart_server() {
2318   if (!is_mysqld_managed()) {
2319     my_error(ER_RESTART_SERVER_FAILED, MYF(0),
2320              "mysqld is not managed by supervisor process");
2321     return true;
2322   }
2323 
2324 #ifdef _WIN32
2325   if (!SetEvent(hEventRestart)) {
2326     LogErr(ERROR_LEVEL, ER_SET_EVENT_FAILED, GetLastError());
2327     my_error(ER_RESTART_SERVER_FAILED, MYF(0), "Internal operation failure");
2328     return true;
2329   }
2330 #else
2331 
2332   if (pthread_kill(signal_thread_id.thread, SIGUSR2)) {
2333     DBUG_PRINT("error", ("Got error %d from pthread_kill", errno));
2334     my_error(ER_RESTART_SERVER_FAILED, MYF(0), "Internal operation failure");
2335     return true;
2336   }
2337 #endif
2338   return false;
2339 }
2340 
kill_mysql(void)2341 void kill_mysql(void) {
2342   DBUG_TRACE;
2343 
2344   if (!mysqld_server_started) {
2345     mysqld_process_must_end_at_startup = true;
2346     return;
2347   }
2348 #if defined(_WIN32)
2349   {
2350     if (!SetEvent(hEventShutdown)) {
2351       DBUG_PRINT("error", ("Got error: %ld from SetEvent", GetLastError()));
2352     }
2353     /*
2354       or:
2355       HANDLE hEvent=OpenEvent(0, false, "MySqlShutdown");
2356       SetEvent(hEventShutdown);
2357       CloseHandle(hEvent);
2358     */
2359   }
2360 #else
2361   if (pthread_kill(signal_thread_id.thread, SIGTERM)) {
2362     DBUG_PRINT("error", ("Got error %d from pthread_kill",
2363                          errno)); /* purecov: inspected */
2364   }
2365 #endif
2366   DBUG_PRINT("quit", ("After pthread_kill"));
2367 }
2368 
unireg_abort(int exit_code)2369 static void unireg_abort(int exit_code) {
2370   DBUG_TRACE;
2371 
2372   if (errno) {
2373     sysd::notify("ERRNO=", errno, "\n");
2374   }
2375 
2376   if (opt_initialize && exit_code && !opt_validate_config)
2377     LogErr(ERROR_LEVEL,
2378            mysql_initialize_directory_freshly_created
2379                ? ER_DATA_DIRECTORY_UNUSABLE_DELETABLE
2380                : ER_DATA_DIRECTORY_UNUSABLE,
2381            mysql_real_data_home);
2382 
2383   // At this point it does not make sense to buffer more messages.
2384   // Just flush what we have and write directly to stderr.
2385   flush_error_log_messages();
2386 
2387   if (opt_help) usage();
2388 
2389   bool daemon_launcher_quiet =
2390       (IF_WIN(false, opt_daemonize) && !mysqld::runtime::is_daemon() &&
2391        !is_help_or_validate_option());
2392 
2393   if (!daemon_launcher_quiet && exit_code) LogErr(ERROR_LEVEL, ER_ABORTING);
2394 
2395   mysql_audit_notify(MYSQL_AUDIT_SERVER_SHUTDOWN_SHUTDOWN,
2396                      MYSQL_AUDIT_SERVER_SHUTDOWN_REASON_ABORT, exit_code);
2397 #ifndef _WIN32
2398   if (signal_thread_id.thread != 0) {
2399     // Make sure the signal thread isn't blocked when we are trying to exit.
2400     server_components_initialized();
2401 
2402     pthread_kill(signal_thread_id.thread, SIGTERM);
2403     my_thread_join(&signal_thread_id, nullptr);
2404   }
2405   signal_thread_id.thread = 0;
2406 
2407   if (mysqld::runtime::is_daemon()) {
2408     mysqld::runtime::signal_parent(pipe_write_fd, 0);
2409   }
2410 #endif
2411   clean_up(!is_help_or_validate_option() && !daemon_launcher_quiet &&
2412            (exit_code || !opt_initialize)); /* purecov: inspected */
2413   DBUG_PRINT("quit", ("done with cleanup in unireg_abort"));
2414   mysqld_exit(exit_code);
2415 }
2416 
clean_up_mysqld_mutexes()2417 void clean_up_mysqld_mutexes() { clean_up_mutexes(); }
2418 
mysqld_exit(int exit_code)2419 static void mysqld_exit(int exit_code) {
2420   DBUG_ASSERT(
2421       (exit_code >= MYSQLD_SUCCESS_EXIT && exit_code <= MYSQLD_ABORT_EXIT) ||
2422       exit_code == MYSQLD_RESTART_EXIT);
2423   mysql_audit_finalize();
2424   Srv_session::module_deinit();
2425   delete_optimizer_cost_module();
2426   clean_up_mutexes();
2427   my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
2428   destroy_error_log();
2429 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
2430   shutdown_performance_schema();
2431 #endif
2432 
2433 #ifdef WITH_LOCK_ORDER
2434   LO_cleanup();
2435 #endif
2436 
2437 #if defined(_WIN32)
2438   if (hEventShutdown) CloseHandle(hEventShutdown);
2439   close_service_status_pipe_in_mysqld();
2440 #endif  // _WIN32
2441 
2442   exit(exit_code); /* purecov: inspected */
2443 }
2444 
2445 /**
2446    GTID cleanup destroys objects and reset their pointer.
2447    Function is reentrant.
2448 */
gtid_server_cleanup()2449 void gtid_server_cleanup() {
2450   if (gtid_state != nullptr) {
2451     delete gtid_state;
2452     gtid_state = nullptr;
2453   }
2454   if (global_sid_map != nullptr) {
2455     delete global_sid_map;
2456     global_sid_map = nullptr;
2457   }
2458   if (global_sid_lock != nullptr) {
2459     delete global_sid_lock;
2460     global_sid_lock = nullptr;
2461   }
2462   if (gtid_table_persistor != nullptr) {
2463     delete gtid_table_persistor;
2464     gtid_table_persistor = nullptr;
2465   }
2466 }
2467 
2468 /**
2469    GTID initialization.
2470 
2471    @return true if allocation does not succeed
2472            false if OK
2473 */
gtid_server_init()2474 bool gtid_server_init() {
2475   global_gtid_mode.set(
2476       static_cast<Gtid_mode::value_type>(Gtid_mode::sysvar_mode));
2477   bool res = (!(global_sid_lock = new Checkable_rwlock(
2478 #ifdef HAVE_PSI_INTERFACE
2479                     key_rwlock_global_sid_lock
2480 #endif
2481                     )) ||
2482               !(global_sid_map = new Sid_map(global_sid_lock)) ||
2483               !(gtid_state = new Gtid_state(global_sid_lock, global_sid_map)) ||
2484               !(gtid_table_persistor = new Gtid_table_persistor()));
2485 
2486   if (res) {
2487     gtid_server_cleanup();
2488   }
2489   return res;
2490 }
2491 
2492 // Free connection acceptors
free_connection_acceptors()2493 static void free_connection_acceptors() {
2494   delete mysqld_socket_acceptor;
2495   mysqld_socket_acceptor = nullptr;
2496 
2497 #ifdef _WIN32
2498   delete named_pipe_acceptor;
2499   named_pipe_acceptor = NULL;
2500   delete shared_mem_acceptor;
2501   shared_mem_acceptor = NULL;
2502 #endif
2503 }
2504 
clean_up(bool print_message)2505 static void clean_up(bool print_message) {
2506   DBUG_PRINT("exit", ("clean_up"));
2507   if (cleanup_done++) return; /* purecov: inspected */
2508 
2509   ha_pre_dd_shutdown();
2510   dd::shutdown();
2511 
2512   Events::deinit();
2513   stop_handle_manager();
2514 
2515   memcached_shutdown();
2516 
2517   /*
2518     make sure that handlers finish up
2519     what they have that is dependent on the binlog
2520   */
2521   if (print_message && (!is_help_or_validate_option() || opt_verbose))
2522     LogErr(INFORMATION_LEVEL, ER_BINLOG_END);
2523   ha_binlog_end(current_thd);
2524 
2525   injector::free_instance();
2526   mysql_bin_log.cleanup();
2527 
2528   if (use_slave_mask) bitmap_free(&slave_error_mask);
2529   my_tz_free();
2530   servers_free(true);
2531   acl_free(true);
2532   grant_free();
2533   hostname_cache_free();
2534   range_optimizer_free();
2535   item_func_sleep_free();
2536   lex_free(); /* Free some memory */
2537   item_create_cleanup();
2538   if (!opt_noacl) udf_unload_udfs();
2539   table_def_start_shutdown();
2540   plugin_shutdown();
2541   gtid_server_cleanup();  // after plugin_shutdown
2542   delete_optimizer_cost_module();
2543   ha_end();
2544   if (tc_log) {
2545     tc_log->close();
2546     tc_log = nullptr;
2547   }
2548 
2549   if (dd::upgrade_57::in_progress()) delete_dictionary_tablespace();
2550 
2551   Recovered_xa_transactions::destroy();
2552   delegates_destroy();
2553   transaction_cache_free();
2554   MDL_context_backup_manager::destroy();
2555   table_def_free();
2556   mdl_destroy();
2557   key_caches.delete_elements();
2558   multi_keycache_free();
2559   query_logger.cleanup();
2560   free_tmpdir(&mysql_tmpdir_list);
2561   my_free(opt_bin_logname);
2562   free_max_user_conn();
2563   end_slave_list();
2564   delete binlog_filter;
2565   rpl_channel_filters.clean_up();
2566   end_ssl();
2567   vio_end();
2568   u_cleanup();
2569 #if defined(ENABLED_DEBUG_SYNC)
2570   /* End the debug sync facility. See debug_sync.cc. */
2571   debug_sync_end();
2572 #endif /* defined(ENABLED_DEBUG_SYNC) */
2573 
2574   delete_pid_file(MYF(0));
2575 
2576   if (print_message && my_default_lc_messages && server_start_time)
2577     LogErr(SYSTEM_LEVEL, ER_SERVER_SHUTDOWN_COMPLETE, my_progname,
2578            server_version, MYSQL_COMPILATION_COMMENT_SERVER);
2579   cleanup_errmsgs();
2580 
2581   free_connection_acceptors();
2582   Connection_handler_manager::destroy_instance();
2583 
2584   if (!is_help_or_validate_option() && !opt_initialize)
2585     resourcegroups::Resource_group_mgr::destroy_instance();
2586   mysql_client_plugin_deinit();
2587 
2588   Global_THD_manager::destroy_instance();
2589 
2590   my_free(const_cast<char *>(log_bin_basename));
2591   my_free(const_cast<char *>(log_bin_index));
2592   my_free(const_cast<char *>(relay_log_basename));
2593   my_free(const_cast<char *>(relay_log_index));
2594   free_list(opt_early_plugin_load_list_ptr);
2595   free_list(opt_plugin_load_list_ptr);
2596 
2597   /*
2598     Is this the best place for components deinit? It may be changed when new
2599     dependencies are discovered, possibly being divided into separate points
2600     where all dependencies are still ok.
2601   */
2602   log_error_stage_set(LOG_ERROR_STAGE_SHUTTING_DOWN);
2603   log_builtins_error_stack(LOG_ERROR_SERVICES_DEFAULT, false, nullptr);
2604 #ifdef HAVE_PSI_THREAD_INTERFACE
2605   if (!is_help_or_validate_option() && !opt_initialize) {
2606     unregister_pfs_notification_service();
2607     unregister_pfs_resource_group_service();
2608   }
2609 #endif
2610   deinit_tls_psi_keys();
2611   component_infrastructure_deinit();
2612   /*
2613     component unregister_variable() api depends on system_variable_hash.
2614     component_infrastructure_deinit() interns calls the deinit funtion
2615     of components which are loaded, and the deinit functions can have
2616     the component system unregister_ variable()  api's, hence we need
2617     to call the sys_var_end() after component_infrastructure_deinit()
2618   */
2619   sys_var_end();
2620   free_status_vars();
2621 
2622   finish_client_errs();
2623   deinit_errmessage();  // finish server errs
2624   DBUG_PRINT("quit", ("Error messages freed"));
2625 
2626   if (have_statement_timeout == SHOW_OPTION_YES) my_timer_deinitialize();
2627 
2628   have_statement_timeout = SHOW_OPTION_DISABLED;
2629 
2630   persisted_variables_cache.cleanup();
2631 
2632   udf_deinit_globals();
2633   /*
2634     The following lines may never be executed as the main thread may have
2635     killed us
2636   */
2637   DBUG_PRINT("quit", ("done with cleanup"));
2638 } /* clean_up */
2639 
clean_up_mutexes()2640 static void clean_up_mutexes() {
2641   mysql_mutex_destroy(&LOCK_log_throttle_qni);
2642   mysql_mutex_destroy(&LOCK_status);
2643   mysql_mutex_destroy(&LOCK_manager);
2644   mysql_mutex_destroy(&LOCK_crypt);
2645   mysql_mutex_destroy(&LOCK_user_conn);
2646   mysql_rwlock_destroy(&LOCK_sys_init_connect);
2647   mysql_rwlock_destroy(&LOCK_sys_init_slave);
2648   mysql_mutex_destroy(&LOCK_global_system_variables);
2649   mysql_rwlock_destroy(&LOCK_system_variables_hash);
2650   mysql_mutex_destroy(&LOCK_uuid_generator);
2651   mysql_mutex_destroy(&LOCK_sql_rand);
2652   mysql_mutex_destroy(&LOCK_prepared_stmt_count);
2653   mysql_mutex_destroy(&LOCK_sql_slave_skip_counter);
2654   mysql_mutex_destroy(&LOCK_slave_net_timeout);
2655   mysql_mutex_destroy(&LOCK_slave_trans_dep_tracker);
2656   mysql_mutex_destroy(&LOCK_error_messages);
2657   mysql_mutex_destroy(&LOCK_default_password_lifetime);
2658   mysql_mutex_destroy(&LOCK_mandatory_roles);
2659   mysql_mutex_destroy(&LOCK_server_started);
2660   mysql_cond_destroy(&COND_server_started);
2661   mysql_mutex_destroy(&LOCK_reset_gtid_table);
2662   mysql_mutex_destroy(&LOCK_compress_gtid_table);
2663   mysql_cond_destroy(&COND_compress_gtid_table);
2664   mysql_mutex_destroy(&LOCK_collect_instance_log);
2665   mysql_mutex_destroy(&LOCK_password_history);
2666   mysql_mutex_destroy(&LOCK_password_reuse_interval);
2667   mysql_cond_destroy(&COND_manager);
2668 #ifdef _WIN32
2669   mysql_cond_destroy(&COND_handler_count);
2670   mysql_mutex_destroy(&LOCK_handler_count);
2671   mysql_rwlock_destroy(&LOCK_named_pipe_full_access_group);
2672 #endif
2673 #ifndef _WIN32
2674   mysql_cond_destroy(&COND_socket_listener_active);
2675   mysql_mutex_destroy(&LOCK_socket_listener_active);
2676   mysql_cond_destroy(&COND_start_signal_handler);
2677   mysql_mutex_destroy(&LOCK_start_signal_handler);
2678 #endif
2679   mysql_mutex_destroy(&LOCK_keyring_operations);
2680   mysql_mutex_destroy(&LOCK_tls_ctx_options);
2681   mysql_mutex_destroy(&LOCK_rotate_binlog_master_key);
2682   mysql_mutex_destroy(&LOCK_admin_tls_ctx_options);
2683 }
2684 
2685 /****************************************************************************
2686 ** Init IP and UNIX socket
2687 ****************************************************************************/
2688 
set_ports()2689 static void set_ports() {
2690   char *env;
2691   if (!mysqld_port &&
2692       !opt_disable_networking) {  // Get port if not from commandline
2693     mysqld_port = MYSQL_PORT;
2694 
2695     /*
2696       if builder specifically requested a default port, use that
2697       (even if it coincides with our factory default).
2698       only if they didn't do we check /etc/services (and, failing
2699       on that, fall back to the factory default of 3306).
2700       either default can be overridden by the environment variable
2701       MYSQL_TCP_PORT, which in turn can be overridden with command
2702       line options.
2703     */
2704 
2705 #if MYSQL_PORT_DEFAULT == 0
2706     struct servent *serv_ptr;
2707     if ((serv_ptr = getservbyname("mysql", "tcp")))
2708       mysqld_port = ntohs((u_short)serv_ptr->s_port); /* purecov: inspected */
2709 #endif
2710     if ((env = getenv("MYSQL_TCP_PORT")))
2711       mysqld_port = (uint)atoi(env); /* purecov: inspected */
2712   }
2713   if (!mysqld_unix_port) {
2714 #ifdef _WIN32
2715     mysqld_unix_port = (char *)MYSQL_NAMEDPIPE;
2716 #else
2717     mysqld_unix_port = MYSQL_UNIX_ADDR;
2718 #endif
2719     if ((env = getenv("MYSQL_UNIX_PORT")))
2720       mysqld_unix_port = env; /* purecov: inspected */
2721   }
2722 }
2723 
2724 #if !defined(_WIN32)
2725 /* Change to run as another user if started with --user */
2726 
check_user(const char * user)2727 static PasswdValue check_user(const char *user) {
2728   uid_t user_id = geteuid();
2729 
2730   PasswdValue tmp_user_info =
2731       (user == nullptr ? PasswdValue{} : my_getpwnam(user));
2732 
2733   // Don't bother if we aren't superuser
2734   if (user_id) {
2735     if (user) {
2736       /* Don't give a warning, if real user is same as given with --user */
2737       if ((tmp_user_info.IsVoid() || user_id != tmp_user_info.pw_uid))
2738         LogErr(WARNING_LEVEL, ER_USER_REQUIRES_ROOT);
2739     }
2740     return PasswdValue{};
2741   }
2742   DBUG_ASSERT(user_id == 0);  // we are running as root
2743 
2744   if (!user) {
2745     if (!opt_initialize && !is_help_or_validate_option()) {
2746       LogErr(ERROR_LEVEL, ER_REALLY_RUN_AS_ROOT);
2747       unireg_abort(MYSQLD_ABORT_EXIT);
2748     }
2749     return PasswdValue{};
2750   }
2751   /* purecov: begin tested */
2752   if (!strcmp(user, "root"))
2753     return PasswdValue{};  // Avoid problem with dynamic libraries
2754 
2755   if (tmp_user_info.IsVoid()) {
2756     // Allow a numeric uid to be used
2757     const char *pos;
2758     for (pos = user; my_isdigit(mysqld_charset, *pos); pos++)
2759       ;
2760     if (*pos)  // Not numeric id
2761       goto err;
2762 
2763     tmp_user_info = my_getpwuid(atoi(user));
2764     if (tmp_user_info.IsVoid()) goto err;
2765   }
2766   return tmp_user_info;
2767   /* purecov: end */
2768 
2769 err:
2770   LogErr(ERROR_LEVEL, ER_USER_WHAT_USER, user);
2771   unireg_abort(MYSQLD_ABORT_EXIT);
2772 
2773   return PasswdValue{};
2774 }
2775 
2776 namespace mysqld_funcs_unit_test {
check_user_drv(const char * user)2777 PasswdValue check_user_drv(const char *user) { return check_user(user); }
2778 }  // namespace mysqld_funcs_unit_test
2779 
set_user(const char * user,const PasswdValue & user_info_arg)2780 static void set_user(const char *user, const PasswdValue &user_info_arg) {
2781   /* purecov: begin tested */
2782   DBUG_ASSERT(user_info_arg.IsVoid() == false);
2783 #ifdef HAVE_INITGROUPS
2784   initgroups(user, user_info_arg.pw_gid);
2785 #endif
2786   if (setgid(user_info_arg.pw_gid) == -1) {
2787     LogErr(ERROR_LEVEL, ER_FAIL_SETGID, strerror(errno));
2788     unireg_abort(MYSQLD_ABORT_EXIT);
2789   }
2790   if (setuid(user_info_arg.pw_uid) == -1) {
2791     LogErr(ERROR_LEVEL, ER_FAIL_SETUID, strerror(errno));
2792     unireg_abort(MYSQLD_ABORT_EXIT);
2793   }
2794 
2795 #ifdef HAVE_SYS_PRCTL_H
2796   if (test_flags & TEST_CORE_ON_SIGNAL) {
2797     /* inform kernel that process is dumpable */
2798     (void)prctl(PR_SET_DUMPABLE, 1);
2799   }
2800 #endif
2801 
2802   /* purecov: end */
2803 }
2804 
set_effective_user(const PasswdValue & user_info_arg)2805 static void set_effective_user(const PasswdValue &user_info_arg) {
2806   DBUG_ASSERT(user_info_arg.IsVoid() == false);
2807   if (setregid((gid_t)-1, user_info_arg.pw_gid) == -1) {
2808     LogErr(ERROR_LEVEL, ER_FAIL_SETREGID, strerror(errno));
2809     unireg_abort(MYSQLD_ABORT_EXIT);
2810   }
2811   if (setreuid((uid_t)-1, user_info_arg.pw_uid) == -1) {
2812     LogErr(ERROR_LEVEL, ER_FAIL_SETREUID, strerror(errno));
2813     unireg_abort(MYSQLD_ABORT_EXIT);
2814   }
2815 }
2816 
2817 /** Change root user if started with @c --chroot . */
set_root(const char * path)2818 static void set_root(const char *path) {
2819   if (chroot(path) == -1) {
2820     LogErr(ERROR_LEVEL, ER_FAIL_CHROOT, strerror(errno));
2821     unireg_abort(MYSQLD_ABORT_EXIT);
2822   }
2823   my_setwd("/", MYF(0));
2824 }
2825 #endif  // !_WIN32
2826 
2827 /**
2828   Check that an address value is a wildcard IP value,
2829   that is it has either the value 0.0.0.0 for IPv4 or the value ::1 in
2830   case IPv6, or has the specially treated symbol * as its value.
2831 
2832   @param address_value   Address value to check
2833   @param address_length  Address length
2834 
2835   @return true in case the address value is a wildcard value, else false.
2836 */
check_address_is_wildcard(const char * address_value,size_t address_length)2837 bool check_address_is_wildcard(const char *address_value,
2838                                size_t address_length) {
2839   return
2840       // Wildcard is not allowed in case a comma separated list of
2841       // addresses is specified
2842       native_strncasecmp(address_value, MY_BIND_ALL_ADDRESSES,
2843                          address_length) == 0 ||
2844       // The specially treated address :: is not allowed in case
2845       // a comma separated list of addresses is specified
2846       native_strncasecmp(address_value, ipv6_all_addresses, address_length) ==
2847           0 ||
2848       // The specially treated address 0.0.0.0 is not allowed in case
2849       // a comma separated list of addresses is specified
2850       native_strncasecmp(address_value, ipv4_all_addresses, address_length) ==
2851           0;
2852 }
2853 
2854 /**
2855   Take a string representing host or ip address followed by
2856   optional delimiter '/' and namespace name and put address part
2857   and namespace part into corresponding output parameters.
2858 
2859   @param begin_address_value  start of a string containing an address value
2860   @param end_address_value  pointer to an end of string containing
2861                             an address value. Has the value nullptr in case
2862                             address value not continue
2863   @param [out] address_value  address value extracted from address string
2864   @param [out] network_namespace  network namespace extracted from
2865                                   the address string value if any
2866 
2867   @return false on success, true on address format error
2868 */
parse_address_string(const char * begin_address_value,const char * end_address_value,std::string * address_value,std::string * network_namespace)2869 static bool parse_address_string(const char *begin_address_value,
2870                                  const char *end_address_value,
2871                                  std::string *address_value,
2872                                  std::string *network_namespace) {
2873   const char *namespace_separator = strchr(begin_address_value, '/');
2874 
2875   if (namespace_separator != nullptr) {
2876     if (begin_address_value == namespace_separator)
2877       /*
2878         Parse error: there is no character before '/',
2879         that is missed address value
2880       */
2881       return true;
2882 
2883     if (namespace_separator < end_address_value) {
2884       if (end_address_value - namespace_separator == 1)
2885         /*
2886           Parse error: there is no character immediately after '/',
2887           that is missed namespace name.
2888         */
2889         return true;
2890 
2891       /*
2892         Found namespace delimiter. Extract namespace and address values
2893       */
2894       *address_value = std::string(begin_address_value, namespace_separator);
2895       *network_namespace =
2896           std::string(namespace_separator + 1, end_address_value);
2897     } else if (end_address_value != nullptr)
2898       /*
2899         This branch corresponds to the case when namespace separator is located
2900         after the last character of the address subvalue being processed.
2901         For example, if the following string '192.168.1.1,172.1.1.1/red'
2902         passed into the function create_bind_address_info_from_string(),
2903         then during handling of the address 192.168.1.1 search of '/'
2904         will return a position after the end of the sub string 192.168.1.1
2905         (in the next sub string 172.1.1.1/red) that should be ignored.
2906       */
2907       *address_value = std::string(begin_address_value, end_address_value);
2908     else {
2909       /*
2910         This branch corresponds to the case when namespace separator is located
2911         at the last part of address values. For example,
2912         this branch is executed during handling of the following value
2913         192.168.1.1,::1,::1/greeen for the option --bind-address.
2914       */
2915       *address_value = std::string(begin_address_value, namespace_separator);
2916       *network_namespace = std::string(namespace_separator + 1);
2917       if (*(namespace_separator + 1) == 0)
2918         /*
2919           Parse error: there is no character immediately
2920           after '/' - a namespace name missed.
2921         */
2922         return true;
2923     }
2924   } else {
2925     /*
2926       Regular address without network namespace found.
2927     */
2928     *address_value = end_address_value != nullptr
2929                          ? std::string(begin_address_value, end_address_value)
2930                          : std::string(begin_address_value);
2931   }
2932 
2933   return false;
2934 }
2935 
2936 /**
2937   Parse a value of address sub string with checking of address string format,
2938   extract address part and namespace part of the address value, and store
2939   their values into the argument valid_bind_addresses.
2940 
2941   @return false on success, true on address format error
2942 */
create_bind_address_info_from_string(const char * begin_address_value,const char * end_address_value,std::list<Bind_address_info> * valid_bind_addresses)2943 static bool create_bind_address_info_from_string(
2944     const char *begin_address_value, const char *end_address_value,
2945     std::list<Bind_address_info> *valid_bind_addresses) {
2946   Bind_address_info bind_address_info;
2947   std::string address_value, network_namespace;
2948 
2949   if (parse_address_string(begin_address_value, end_address_value,
2950                            &address_value, &network_namespace))
2951     return true;
2952 
2953   if (network_namespace.empty())
2954     bind_address_info = Bind_address_info(address_value);
2955   else {
2956     /*
2957       Wildcard value is not allowed in case network namespace specified
2958       for address value in the option bind-address.
2959     */
2960     if (check_address_is_wildcard(address_value.c_str(),
2961                                   address_value.length())) {
2962       LogErr(ERROR_LEVEL,
2963              ER_NETWORK_NAMESPACE_NOT_ALLOWED_FOR_WILDCARD_ADDRESS);
2964       return true;
2965     }
2966 
2967     bind_address_info = Bind_address_info(address_value, network_namespace);
2968   }
2969 
2970   valid_bind_addresses->emplace_back(bind_address_info);
2971 
2972   return false;
2973 }
2974 
2975 /**
2976   Check acceptable value(s) of parameter bind-address
2977 
2978   @param      bind_address          Value of the parameter bind-address
2979   @param[out] valid_bind_addresses  List of addresses to listen and their
2980                                     corresponding network namespaces if set.
2981 
2982   @return false on success, true on failure
2983 */
check_bind_address_has_valid_value(const char * bind_address,std::list<Bind_address_info> * valid_bind_addresses)2984 static bool check_bind_address_has_valid_value(
2985     const char *bind_address,
2986     std::list<Bind_address_info> *valid_bind_addresses) {
2987   if (strlen(bind_address) == 0)
2988     // Empty value for bind_address is an error
2989     return true;
2990 
2991   const char *comma_separator = strchr(bind_address, ',');
2992   const char *begin_of_value = bind_address;
2993   const bool multiple_bind_addresses = (comma_separator != nullptr);
2994 
2995   if (comma_separator == begin_of_value)
2996     // Return an error if a value of bind_address begins with comma
2997     return true;
2998 
2999   while (comma_separator != nullptr) {
3000     Bind_address_info bind_address_info;
3001     std::string address_value, network_namespace;
3002     /*
3003       Wildcard value is not allowed in case multi-addresses value specified
3004       for the option bind-address.
3005     */
3006     if (check_address_is_wildcard(begin_of_value,
3007                                   comma_separator - begin_of_value)) {
3008       LogErr(ERROR_LEVEL, ER_WILDCARD_NOT_ALLOWED_FOR_MULTIADDRESS_BIND);
3009 
3010       return true;
3011     }
3012 
3013     if (create_bind_address_info_from_string(begin_of_value, comma_separator,
3014                                              valid_bind_addresses))
3015       return true;
3016 
3017     begin_of_value = comma_separator + 1;
3018     comma_separator = strchr(begin_of_value, ',');
3019     if (comma_separator == begin_of_value)
3020       // Return an error if a value of bind_address has two adjacent commas
3021       return true;
3022   }
3023 
3024   /*
3025     Wildcard value is not allowed in case multi-addresses value specified
3026     for the option bind-address.
3027   */
3028   if (multiple_bind_addresses &&
3029       (check_address_is_wildcard(begin_of_value, strlen(begin_of_value)) ||
3030        strlen(begin_of_value) == 0))
3031     return true;
3032 
3033   if (create_bind_address_info_from_string(begin_of_value, comma_separator,
3034                                            valid_bind_addresses))
3035     return true;
3036 
3037   return false;
3038 }
3039 
3040 /**
3041   Check acceptable value(s) of the parameter admin-address
3042 
3043   @param      admin_bind_addr_str   Value of the parameter admin-address
3044   @param[out] admin_address_info    List of addresses to listen and their
3045                                     corresponding network namespaces if set.
3046 
3047   @return false on success, true on failure
3048 */
check_admin_address_has_valid_value(const char * admin_bind_addr_str,Bind_address_info * admin_address_info)3049 static bool check_admin_address_has_valid_value(
3050     const char *admin_bind_addr_str, Bind_address_info *admin_address_info) {
3051   std::string address_value, network_namespace;
3052 
3053   if (parse_address_string(admin_bind_addr_str, nullptr, &address_value,
3054                            &network_namespace))
3055     return true;
3056 
3057   if (check_address_is_wildcard(address_value.c_str(),
3058                                 address_value.length())) {
3059     if (!network_namespace.empty())
3060       LogErr(ERROR_LEVEL,
3061              ER_NETWORK_NAMESPACE_NOT_ALLOWED_FOR_WILDCARD_ADDRESS);
3062 
3063     return true;
3064   }
3065 
3066   if (network_namespace.empty())
3067     *admin_address_info = Bind_address_info(address_value);
3068   else
3069     *admin_address_info = Bind_address_info(address_value, network_namespace);
3070 
3071   return false;
3072 }
3073 
network_init(void)3074 static bool network_init(void) {
3075   if (opt_initialize) return false;
3076 
3077 #ifdef HAVE_SYS_UN_H
3078   std::string const unix_sock_name(mysqld_unix_port ? mysqld_unix_port : "");
3079 #else
3080   std::string const unix_sock_name("");
3081 #endif
3082 
3083   std::list<Bind_address_info> bind_addresses_info;
3084 
3085   if (!opt_disable_networking || unix_sock_name != "") {
3086     if (my_bind_addr_str != nullptr &&
3087         check_bind_address_has_valid_value(my_bind_addr_str,
3088                                            &bind_addresses_info)) {
3089       LogErr(ERROR_LEVEL, ER_INVALID_VALUE_OF_BIND_ADDRESSES, my_bind_addr_str);
3090       return true;
3091     }
3092 
3093     Bind_address_info admin_address_info;
3094     if (!opt_disable_networking) {
3095       if (my_admin_bind_addr_str != nullptr &&
3096           check_admin_address_has_valid_value(my_admin_bind_addr_str,
3097                                               &admin_address_info)) {
3098         LogErr(ERROR_LEVEL, ER_INVALID_ADMIN_ADDRESS, my_admin_bind_addr_str);
3099         return true;
3100       }
3101       /*
3102         Port 0 is interpreted by implementations of TCP protocol
3103         as a hint to find a first free port value to use and bind to it.
3104         On the other hand, the option mysqld_admin_port can be assigned
3105         the value 0 if a user specified a value that is out of allowable
3106         range of values. Therefore, to avoid a case when an operating
3107         system binds admin interface to am arbitrary selected port value,
3108         set it explicitly to the value MYSQL_ADMIN_PORT in case it has value 0.
3109       */
3110       if (mysqld_admin_port == 0) mysqld_admin_port = MYSQL_ADMIN_PORT;
3111     }
3112     Mysqld_socket_listener *mysqld_socket_listener = new (std::nothrow)
3113         Mysqld_socket_listener(bind_addresses_info, mysqld_port,
3114                                admin_address_info, mysqld_admin_port,
3115                                admin_address_info.address.empty()
3116                                    ? false
3117                                    : listen_admin_interface_in_separate_thread,
3118                                back_log, mysqld_port_timeout, unix_sock_name);
3119     if (mysqld_socket_listener == nullptr) return true;
3120 
3121     mysqld_socket_acceptor = new (std::nothrow)
3122         Connection_acceptor<Mysqld_socket_listener>(mysqld_socket_listener);
3123     if (mysqld_socket_acceptor == nullptr) {
3124       delete mysqld_socket_listener;
3125       mysqld_socket_listener = nullptr;
3126       return true;
3127     }
3128 
3129     if (mysqld_socket_acceptor->init_connection_acceptor())
3130       return true;  // mysqld_socket_acceptor would be freed in unireg_abort.
3131 
3132     if (report_port == 0) report_port = mysqld_port;
3133 
3134     if (!opt_disable_networking) DBUG_ASSERT(report_port != 0);
3135   }
3136 #ifdef _WIN32
3137   // Create named pipe
3138   if (opt_enable_named_pipe) {
3139     std::string pipe_name = mysqld_unix_port ? mysqld_unix_port : "";
3140 
3141     named_pipe_listener = new (std::nothrow) Named_pipe_listener(&pipe_name);
3142     if (named_pipe_listener == NULL) return true;
3143 
3144     named_pipe_acceptor = new (std::nothrow)
3145         Connection_acceptor<Named_pipe_listener>(named_pipe_listener);
3146     if (named_pipe_acceptor == NULL) {
3147       delete named_pipe_listener;
3148       named_pipe_listener = NULL;
3149       return true;
3150     }
3151 
3152     if (named_pipe_acceptor->init_connection_acceptor())
3153       return true;  // named_pipe_acceptor would be freed in unireg_abort.
3154   }
3155 
3156   // Setup shared_memory acceptor
3157   if (opt_enable_shared_memory) {
3158     std::string shared_mem_base_name =
3159         shared_memory_base_name ? shared_memory_base_name : "";
3160 
3161     Shared_mem_listener *shared_mem_listener =
3162         new (std::nothrow) Shared_mem_listener(&shared_mem_base_name);
3163     if (shared_mem_listener == NULL) return true;
3164 
3165     shared_mem_acceptor = new (std::nothrow)
3166         Connection_acceptor<Shared_mem_listener>(shared_mem_listener);
3167     if (shared_mem_acceptor == NULL) {
3168       delete shared_mem_listener;
3169       shared_mem_listener = NULL;
3170       return true;
3171     }
3172 
3173     if (shared_mem_acceptor->init_connection_acceptor())
3174       return true;  // shared_mem_acceptor would be freed in unireg_abort.
3175   }
3176 #endif  // _WIN32
3177   return false;
3178 }
3179 
3180 #ifdef _WIN32
3181 static uint handler_count = 0;
3182 
decrement_handler_count()3183 static inline void decrement_handler_count() {
3184   mysql_mutex_lock(&LOCK_handler_count);
3185   handler_count--;
3186   mysql_cond_signal(&COND_handler_count);
3187   mysql_mutex_unlock(&LOCK_handler_count);
3188 }
3189 
socket_conn_event_handler(void * arg)3190 extern "C" void *socket_conn_event_handler(void *arg) {
3191   my_thread_init();
3192 
3193   Connection_acceptor<Mysqld_socket_listener> *conn_acceptor =
3194       static_cast<Connection_acceptor<Mysqld_socket_listener> *>(arg);
3195   conn_acceptor->connection_event_loop();
3196 
3197   decrement_handler_count();
3198   my_thread_end();
3199   return 0;
3200 }
3201 
named_pipe_conn_event_handler(void * arg)3202 extern "C" void *named_pipe_conn_event_handler(void *arg) {
3203   my_thread_init();
3204 
3205   Connection_acceptor<Named_pipe_listener> *conn_acceptor =
3206       static_cast<Connection_acceptor<Named_pipe_listener> *>(arg);
3207   conn_acceptor->connection_event_loop();
3208 
3209   decrement_handler_count();
3210   my_thread_end();
3211   return 0;
3212 }
3213 
shared_mem_conn_event_handler(void * arg)3214 extern "C" void *shared_mem_conn_event_handler(void *arg) {
3215   my_thread_init();
3216 
3217   Connection_acceptor<Shared_mem_listener> *conn_acceptor =
3218       static_cast<Connection_acceptor<Shared_mem_listener> *>(arg);
3219   conn_acceptor->connection_event_loop();
3220 
3221   decrement_handler_count();
3222   my_thread_end();
3223   return 0;
3224 }
3225 
setup_conn_event_handler_threads()3226 void setup_conn_event_handler_threads() {
3227   my_thread_handle hThread;
3228 
3229   DBUG_TRACE;
3230 
3231   if ((!have_tcpip || opt_disable_networking) && !opt_enable_shared_memory &&
3232       !opt_enable_named_pipe) {
3233     LogErr(ERROR_LEVEL, ER_WIN_LISTEN_BUT_HOW);
3234     unireg_abort(MYSQLD_ABORT_EXIT);  // Will not return
3235   }
3236 
3237   mysql_mutex_lock(&LOCK_handler_count);
3238   handler_count = 0;
3239 
3240   if (opt_enable_named_pipe) {
3241     int error = mysql_thread_create(
3242         key_thread_handle_con_namedpipes, &hThread, &connection_attrib,
3243         named_pipe_conn_event_handler, named_pipe_acceptor);
3244     if (!error)
3245       handler_count++;
3246     else
3247       LogErr(WARNING_LEVEL, ER_CANT_CREATE_NAMED_PIPES_THREAD, error);
3248   }
3249 
3250   if (have_tcpip && !opt_disable_networking) {
3251     int error = mysql_thread_create(
3252         key_thread_handle_con_sockets, &hThread, &connection_attrib,
3253         socket_conn_event_handler, mysqld_socket_acceptor);
3254     if (!error)
3255       handler_count++;
3256     else
3257       LogErr(WARNING_LEVEL, ER_CANT_CREATE_TCPIP_THREAD, error);
3258   }
3259 
3260   if (opt_enable_shared_memory) {
3261     int error = mysql_thread_create(
3262         key_thread_handle_con_sharedmem, &hThread, &connection_attrib,
3263         shared_mem_conn_event_handler, shared_mem_acceptor);
3264     if (!error)
3265       handler_count++;
3266     else
3267       LogErr(WARNING_LEVEL, ER_CANT_CREATE_SHM_THREAD, error);
3268   }
3269 
3270   // Block until all connection listener threads have exited.
3271   while (handler_count > 0)
3272     mysql_cond_wait(&COND_handler_count, &LOCK_handler_count);
3273   mysql_mutex_unlock(&LOCK_handler_count);
3274 }
3275 
3276 /*
3277   On Windows, we use native SetConsoleCtrlHandler for handle events like Ctrl-C
3278   with graceful shutdown.
3279   Also, we do not use signal(), but SetUnhandledExceptionFilter instead - as it
3280   provides possibility to pass the exception to just-in-time debugger, collect
3281   dumps and potentially also the exception and thread context used to output
3282   callstack.
3283 */
3284 
console_event_handler(DWORD type)3285 static BOOL WINAPI console_event_handler(DWORD type) {
3286   DBUG_TRACE;
3287   if (type == CTRL_C_EVENT) {
3288     /*
3289       Do not shutdown before startup is finished and shutdown
3290       thread is initialized. Otherwise there is a race condition
3291       between main thread doing initialization and CTRL-C thread doing
3292       cleanup, which can result into crash.
3293     */
3294     if (hEventShutdown)
3295       kill_mysql();
3296     else
3297       LogErr(WARNING_LEVEL, ER_NOT_RIGHT_NOW);
3298     return true;
3299   }
3300   return false;
3301 }
3302 
3303 #ifdef DEBUG_UNHANDLED_EXCEPTION_FILTER
3304 #define DEBUGGER_ATTACH_TIMEOUT 120
3305 /*
3306   Wait for debugger to attach and break into debugger. If debugger is not
3307   attached, resume after timeout.
3308 */
wait_for_debugger(int timeout_sec)3309 static void wait_for_debugger(int timeout_sec) {
3310   if (!IsDebuggerPresent()) {
3311     int i;
3312     printf("Waiting for debugger to attach, pid=%u\n", GetCurrentProcessId());
3313     fflush(stdout);
3314     for (i = 0; i < timeout_sec; i++) {
3315       Sleep(1000);
3316       if (IsDebuggerPresent()) {
3317         /* Break into debugger */
3318         __debugbreak();
3319         return;
3320       }
3321     }
3322     printf("pid=%u, debugger not attached after %d seconds, resuming\n",
3323            GetCurrentProcessId(), timeout_sec);
3324     fflush(stdout);
3325   }
3326 }
3327 #endif /* DEBUG_UNHANDLED_EXCEPTION_FILTER */
3328 
my_unhandler_exception_filter(EXCEPTION_POINTERS * ex_pointers)3329 LONG WINAPI my_unhandler_exception_filter(EXCEPTION_POINTERS *ex_pointers) {
3330   static BOOL first_time = true;
3331   if (!first_time) {
3332     /*
3333       This routine can be called twice, typically
3334       when detaching in JIT debugger.
3335       Return EXCEPTION_EXECUTE_HANDLER to terminate process.
3336     */
3337     return EXCEPTION_EXECUTE_HANDLER;
3338   }
3339   first_time = false;
3340 #ifdef DEBUG_UNHANDLED_EXCEPTION_FILTER
3341   /*
3342    Unfortunately there is no clean way to debug unhandled exception filters,
3343    as debugger does not stop there(also documented in MSDN)
3344    To overcome, one could put a MessageBox, but this will not work in service.
3345    Better solution is to print error message and sleep some minutes
3346    until debugger is attached
3347  */
3348   wait_for_debugger(DEBUGGER_ATTACH_TIMEOUT);
3349 #endif /* DEBUG_UNHANDLED_EXCEPTION_FILTER */
3350   __try {
3351     my_set_exception_pointers(ex_pointers);
3352     handle_fatal_signal(ex_pointers->ExceptionRecord->ExceptionCode);
3353   } __except (EXCEPTION_EXECUTE_HANDLER) {
3354     DWORD written;
3355     const char msg[] = "Got exception in exception handler!\n";
3356     WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), msg, sizeof(msg) - 1, &written,
3357               NULL);
3358   }
3359   /*
3360     Return EXCEPTION_CONTINUE_SEARCH to give JIT debugger
3361     (drwtsn32 or vsjitdebugger) possibility to attach,
3362     if JIT debugger is configured.
3363     Windows Error reporting might generate a dump here.
3364   */
3365   return EXCEPTION_CONTINUE_SEARCH;
3366 }
3367 
my_init_signals()3368 void my_init_signals() {
3369   if (opt_console) SetConsoleCtrlHandler(console_event_handler, true);
3370 
3371   /* Avoid MessageBox()es*/
3372   _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
3373   _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
3374   _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
3375   _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
3376   _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
3377   _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
3378 
3379   /*
3380     Do not use SEM_NOGPFAULTERRORBOX in the following SetErrorMode (),
3381     because it would prevent JIT debugger and Windows error reporting
3382     from working. We need WER or JIT-debugging, since our own unhandled
3383     exception filter is not guaranteed to work in all situation
3384     (like heap corruption or stack overflow)
3385   */
3386   SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS |
3387                SEM_NOOPENFILEERRORBOX);
3388   SetUnhandledExceptionFilter(my_unhandler_exception_filter);
3389 }
3390 
3391 #else  // !_WIN32
3392 
3393 extern "C" {
empty_signal_handler(int sig MY_ATTRIBUTE ((unused)))3394 static void empty_signal_handler(int sig MY_ATTRIBUTE((unused))) {}
3395 }
3396 
my_init_signals()3397 void my_init_signals() {
3398   DBUG_TRACE;
3399   struct sigaction sa;
3400   (void)sigemptyset(&sa.sa_mask);
3401 
3402   if (!(test_flags & TEST_NO_STACKTRACE) ||
3403       (test_flags & TEST_CORE_ON_SIGNAL)) {
3404 #ifdef HAVE_STACKTRACE
3405     my_init_stacktrace();
3406 #endif
3407 
3408     if (test_flags & TEST_CORE_ON_SIGNAL) {
3409       // Change limits so that we will get a core file.
3410       struct rlimit rl;
3411       rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
3412       if (setrlimit(RLIMIT_CORE, &rl)) LogErr(WARNING_LEVEL, ER_CORE_VALUES);
3413     }
3414 
3415     /*
3416       SA_RESETHAND resets handler action to default when entering handler.
3417       SA_NODEFER allows receiving the same signal during handler.
3418       E.g. SIGABRT during our signal handler will dump core (default action).
3419     */
3420     sa.sa_flags = SA_RESETHAND | SA_NODEFER;
3421     sa.sa_handler = handle_fatal_signal;
3422     // Treat these as fatal and handle them.
3423     sigaction(SIGABRT, &sa, nullptr);
3424     sigaction(SIGFPE, &sa, nullptr);
3425     // Handle these as well, except for ASAN/UBSAN builds:
3426     // we let sanitizer runtime handle them instead.
3427 #if defined(HANDLE_FATAL_SIGNALS)
3428     sigaction(SIGBUS, &sa, nullptr);
3429     sigaction(SIGILL, &sa, nullptr);
3430     sigaction(SIGSEGV, &sa, nullptr);
3431 #endif
3432   }
3433 
3434   // Ignore SIGPIPE
3435   sa.sa_flags = 0;
3436   sa.sa_handler = SIG_IGN;
3437   (void)sigaction(SIGPIPE, &sa, nullptr);
3438 
3439   // SIGALRM is used to interrupt the socket listener.
3440   sa.sa_handler = empty_signal_handler;
3441   (void)sigaction(SIGALRM, &sa, nullptr);
3442 
3443   // Fix signals if ignored by parents (can happen on Mac OS X).
3444   sa.sa_handler = SIG_DFL;
3445   (void)sigaction(SIGTERM, &sa, nullptr);
3446   (void)sigaction(SIGHUP, &sa, nullptr);
3447   (void)sigaction(SIGUSR1, &sa, nullptr);
3448 
3449   (void)sigemptyset(&mysqld_signal_mask);
3450   /*
3451     Block SIGQUIT, SIGHUP, SIGTERM, SIGUSR1 and SIGUSR2.
3452     The signal handler thread does sigwait() on these.
3453   */
3454   (void)sigaddset(&mysqld_signal_mask, SIGQUIT);
3455   (void)sigaddset(&mysqld_signal_mask, SIGHUP);
3456   (void)sigaddset(&mysqld_signal_mask, SIGTERM);
3457   (void)sigaddset(&mysqld_signal_mask, SIGTSTP);
3458   (void)sigaddset(&mysqld_signal_mask, SIGUSR1);
3459   (void)sigaddset(&mysqld_signal_mask, SIGUSR2);
3460   /*
3461     Block SIGINT unless debugging to prevent Ctrl+C from causing
3462     unclean shutdown of the server.
3463   */
3464   if (!(test_flags & TEST_SIGINT)) (void)sigaddset(&mysqld_signal_mask, SIGINT);
3465   pthread_sigmask(SIG_SETMASK, &mysqld_signal_mask, nullptr);
3466 }
3467 
start_signal_handler()3468 static void start_signal_handler() {
3469   int error;
3470   my_thread_attr_t thr_attr;
3471   DBUG_TRACE;
3472 
3473   (void)my_thread_attr_init(&thr_attr);
3474   (void)pthread_attr_setscope(&thr_attr, PTHREAD_SCOPE_SYSTEM);
3475   (void)my_thread_attr_setdetachstate(&thr_attr, MY_THREAD_CREATE_JOINABLE);
3476 
3477   size_t guardize = 0;
3478   (void)pthread_attr_getguardsize(&thr_attr, &guardize);
3479 #if defined(__ia64__) || defined(__ia64)
3480   /*
3481     Peculiar things with ia64 platforms - it seems we only have half the
3482     stack size in reality, so we have to double it here
3483   */
3484   guardize = my_thread_stack_size;
3485 #endif
3486   if (0 !=
3487       my_thread_attr_setstacksize(&thr_attr, my_thread_stack_size + guardize)) {
3488     DBUG_ASSERT(false);
3489   }
3490 
3491   /*
3492     Set main_thread_id so that SIGTERM/SIGQUIT/SIGKILL/SIGUSR2 can interrupt
3493     the socket listener successfully.
3494   */
3495   main_thread_id = my_thread_self();
3496 
3497   mysql_mutex_lock(&LOCK_start_signal_handler);
3498   if ((error = mysql_thread_create(key_thread_signal_hand, &signal_thread_id,
3499                                    &thr_attr, signal_hand, nullptr))) {
3500     LogErr(ERROR_LEVEL, ER_CANT_CREATE_INTERRUPT_THREAD, error, errno);
3501     flush_error_log_messages();
3502     exit(MYSQLD_ABORT_EXIT);
3503   }
3504   mysql_cond_wait(&COND_start_signal_handler, &LOCK_start_signal_handler);
3505   mysql_mutex_unlock(&LOCK_start_signal_handler);
3506 
3507   (void)my_thread_attr_destroy(&thr_attr);
3508 }
3509 
3510 /** This thread handles SIGTERM, SIGQUIT, SIGHUP, SIGUSR1 and SIGUSR2 signals.
3511  */
3512 /* ARGSUSED */
signal_hand(void * arg MY_ATTRIBUTE ((unused)))3513 extern "C" void *signal_hand(void *arg MY_ATTRIBUTE((unused))) {
3514   my_thread_init();
3515 
3516   sigset_t set;
3517   (void)sigemptyset(&set);
3518   (void)sigaddset(&set, SIGTERM);
3519   (void)sigaddset(&set, SIGQUIT);
3520   (void)sigaddset(&set, SIGHUP);
3521   (void)sigaddset(&set, SIGUSR1);
3522   (void)sigaddset(&set, SIGUSR2);
3523 
3524   /*
3525     Signal to start_signal_handler that we are ready.
3526     This works by waiting for start_signal_handler to free mutex,
3527     after which we signal it that we are ready.
3528   */
3529   mysql_mutex_lock(&LOCK_start_signal_handler);
3530   mysql_cond_broadcast(&COND_start_signal_handler);
3531   mysql_mutex_unlock(&LOCK_start_signal_handler);
3532 
3533   /*
3534     Wait until that all server components have been successfully initialized.
3535     This step is mandatory since signal processing can be done safely only when
3536     all server components have been initialized.
3537   */
3538   server_components_init_wait();
3539   for (;;) {
3540     int sig = 0;
3541     int rc;
3542     bool error;
3543 #ifdef __APPLE__
3544     while ((rc = sigwait(&set, &sig)) == EINTR) {
3545     }
3546     error = rc != 0;
3547 #else
3548     siginfo_t sig_info;
3549     while ((rc = sigwaitinfo(&set, &sig_info)) == -1 && errno == EINTR) {
3550     }
3551     error = rc == -1;
3552     if (!error) sig = sig_info.si_signo;
3553 #endif             // __APPLE__
3554     if (error)
3555       sql_print_error(
3556           "Fatal error in signal handling thread. sigwait/sigwaitinfo returned "
3557           "error  %d\n. Exiting signal handler "
3558           "thread.",
3559           errno);
3560 
3561     if (error || cleanup_done) {
3562       my_thread_end();
3563       my_thread_exit(nullptr);  // Safety
3564       return nullptr;           // Avoid compiler warnings
3565     }
3566     switch (sig) {
3567       case SIGUSR2:
3568         signal_hand_thr_exit_code = MYSQLD_RESTART_EXIT;
3569 #ifndef __APPLE__  // Mac OS doesn't have sigwaitinfo.
3570         //  Log a note if mysqld is restarted via kill command.
3571         if (sig_info.si_pid != getpid()) {
3572           sql_print_information(
3573               "Received signal SIGUSR2."
3574               " Restarting mysqld (Version %s)",
3575               server_version);
3576         }
3577 #endif             // __APPLE__
3578         // fall through
3579       case SIGTERM:
3580       case SIGQUIT:
3581 #ifndef __APPLE__  // Mac OS doesn't have sigwaitinfo.
3582         if (sig_info.si_pid != getpid())
3583           LogErr(SYSTEM_LEVEL, ER_SERVER_SHUTDOWN_INFO, "<via user signal>",
3584                  server_version, MYSQL_COMPILATION_COMMENT_SERVER);
3585 #else
3586         LogErr(SYSTEM_LEVEL, ER_SERVER_SHUTDOWN_INFO, "<via user signal>",
3587                server_version, MYSQL_COMPILATION_COMMENT_SERVER);
3588 #endif  // __APPLE__
3589         // Switch to the file log message processing.
3590         query_logger.set_handlers((log_output_options != LOG_NONE) ? LOG_FILE
3591                                                                    : LOG_NONE);
3592         DBUG_PRINT("info",
3593                    ("Got signal: %d  connection_events_loop_aborted: %d", sig,
3594                     connection_events_loop_aborted()));
3595         if (!connection_events_loop_aborted()) {
3596           // Mark abort for threads.
3597           set_connection_events_loop_aborted(true);
3598 #ifdef HAVE_PSI_THREAD_INTERFACE
3599           // Delete the instrumentation for the signal thread.
3600           PSI_THREAD_CALL(delete_current_thread)();
3601 #endif /* HAVE_PSI_THREAD_INTERFACE */
3602           /*
3603             Kill the socket listener.
3604             The main thread will then set socket_listener_active= false,
3605             and wait for us to finish all the cleanup below.
3606           */
3607           mysql_mutex_lock(&LOCK_socket_listener_active);
3608           while (socket_listener_active) {
3609             DBUG_PRINT("info", ("Killing socket listener"));
3610             if (pthread_kill(main_thread_id, SIGALRM)) {
3611               DBUG_ASSERT(false);
3612               break;
3613             }
3614             mysql_cond_wait(&COND_socket_listener_active,
3615                             &LOCK_socket_listener_active);
3616           }
3617           mysql_mutex_unlock(&LOCK_socket_listener_active);
3618 
3619           close_connections();
3620         }
3621         my_thread_end();
3622         my_thread_exit(nullptr);
3623         return nullptr;  // Avoid compiler warnings
3624         break;
3625       case SIGHUP:
3626         if (!connection_events_loop_aborted()) {
3627           int not_used;
3628           handle_reload_request(
3629               nullptr,
3630               (REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST | REFRESH_GRANT |
3631                REFRESH_THREADS | REFRESH_HOSTS),
3632               nullptr, &not_used);  // Flush logs
3633           // Reenable query logs after the options were reloaded.
3634           query_logger.set_handlers(log_output_options);
3635         }
3636         break;
3637       case SIGUSR1:
3638         if (!connection_events_loop_aborted()) {
3639           int not_used;
3640           handle_reload_request(
3641               nullptr,
3642               (REFRESH_ERROR_LOG |   /**< Rotate only the error log */
3643                REFRESH_GENERAL_LOG | /**< Flush the general log */
3644                REFRESH_SLOW_LOG),    /**< Flush the slow query log */
3645               nullptr, &not_used);   // Flush logs
3646           // Reenable query logs after the options were reloaded.
3647           query_logger.set_handlers(log_output_options);
3648         }
3649         break;
3650       default:
3651         break; /* purecov: tested */
3652     }
3653   }
3654   return nullptr; /* purecov: deadcode */
3655 }
3656 
3657 #endif  // !_WIN32
3658 
3659 /**
3660   All global error messages are sent here where the first one is stored
3661   for the client.
3662 */
3663 /* ARGSUSED */
3664 extern "C" void my_message_sql(uint error, const char *str, myf MyFlags);
3665 
my_message_sql(uint error,const char * str,myf MyFlags)3666 void my_message_sql(uint error, const char *str, myf MyFlags) {
3667   THD *thd = current_thd;
3668   DBUG_TRACE;
3669   DBUG_PRINT("error", ("error: %u  message: '%s'", error, str));
3670 
3671   DBUG_ASSERT(str != nullptr);
3672   /*
3673     An error should have a valid error number (!= 0), so it can be caught
3674     in stored procedures by SQL exception handlers.
3675     Calling my_error() with error == 0 is a bug.
3676     Remaining known places to fix:
3677     - storage/myisam/mi_create.c, my_printf_error()
3678     TODO:
3679     DBUG_ASSERT(error != 0);
3680   */
3681 
3682   if (error == 0) {
3683     /* At least, prevent new abuse ... */
3684     DBUG_ASSERT(strncmp(str, "MyISAM table", 12) == 0);
3685     error = ER_UNKNOWN_ERROR;
3686   }
3687 
3688   /* Caller wishes to inform client, and one is attached. */
3689   if (thd) {
3690     (void)thd->raise_condition(error, nullptr, Sql_condition::SL_ERROR, str,
3691                                MyFlags & ME_FATALERROR);
3692 
3693     /*
3694       Now for an argument check.
3695       We're asserting after rather than before raising the
3696       condition to make the culprit easier to track down.
3697 
3698       Messages intended for the error-log are in the range
3699       starting at ER_SERVER_RANGE_START (error_code 10,000);
3700       messages intended for sending to a client are in the
3701       range below ER_SERVER_RANGE_START. If a message is to
3702       be sent to both a client and the error log, it must
3703       be added twice (once in each range), and two separate
3704       calls (e.g. my_error() and LogErr()) must be added to
3705       the code.
3706 
3707       Only error-codes from the client range should be seen
3708       in this if(). If your patch asserts here, one of two
3709       things probably happened:
3710 
3711       - You added a new message to messages_to_error_log.txt:
3712         The message was added to the server range, but code
3713         was added that tries to send the message to a client
3714         (my_error(), push_warning_printf(), etc.).
3715 
3716         => Move the new message to messages_to_clients.txt.
3717            The copied message should be added at the end of
3718            the range for the lowest server version you're adding
3719            the message to.
3720            Rebuild the server; rerun your test.
3721 
3722       - You used an existing message:
3723         The existing message is intended for use with
3724         the error-log (it appears in messages_to_error_log.txt),
3725         but the new code tries to send it to a client (my_error(),
3726         push_warning_printf(), etc.).
3727 
3728         => Copy the existing message to messages_to_clients.txt.
3729            - The copied message should be added at the end of
3730              the range for the lowest server version you're adding
3731              the message to.
3732            - The copied message will need its own symbol;
3733              if in doubt, call the copy of ER_EXAMPLE_MESSAGE
3734              ER_DA_EXAMPLE_MESSAGE (as this version is for use
3735              with the diagnostics area).
3736            Then make sure that your new code references
3737            this new symbol when it sends the message
3738            to a client.
3739            Rebuild the server; rerun your test.
3740 
3741       We'll assert this here (rather than in raise_condition) as
3742       SQL's SIGNAL command also calls raise_condition, and SIGNAL
3743       is currently allowed to set any error-code (regardless of
3744       range). SIGNALing an error-code from the error-log range
3745       will not result in writing to that log to prevent abuse.
3746     */
3747     DBUG_ASSERT(error < ER_SERVER_RANGE_START);
3748   }
3749 
3750   /* When simulating OOM, skip writing to error log to avoid mtr errors */
3751   DBUG_EXECUTE_IF("simulate_out_of_memory", return;);
3752 
3753   /*
3754     Caller wishes to send to both the client and the error-log.
3755     This is legacy behaviour that is no longer legal as errors flagged
3756     to a client and those sent to the error-log are in different
3757     numeric ranges now. If you own code that does this, see about
3758     updating it by splitting it into two calls, one sending status
3759     to the client, the other sending it to the error-log using
3760     LogErr() and friends.
3761   */
3762   if (MyFlags & ME_ERRORLOG) {
3763     /*
3764       We've removed most uses of ME_ERRORLOG in the server.
3765       This leaves three possible cases, in which we'll rewrite
3766       the error-code from one in the client-range to one in
3767       the error-log range here:
3768 
3769       - EE_OUTOFMEMORY: Correct to ER_SERVER_OUT_OF_RESOURCES so
3770                         mysys can remain logger-agnostic.
3771 
3772       - HA_* range:     Correct to catch-all ER_SERVER_HANDLER_ERROR.
3773 
3774       - otherwise:      Flag as using info from the diagnostics area
3775                         (ER_ERROR_INFO_FROM_DA). This is a failsafe;
3776                         if your code triggers it, your code is probably
3777                         wrong.
3778     */
3779     if ((error == EE_OUTOFMEMORY) || (error == HA_ERR_OUT_OF_MEM))
3780       error = ER_SERVER_OUT_OF_RESOURCES;
3781     else if (error <= HA_ERR_LAST)
3782       error = ER_SERVER_HANDLER_ERROR;
3783 
3784     if (error < ER_SERVER_RANGE_START)
3785       LogEvent()
3786           .type(LOG_TYPE_ERROR)
3787           .prio(ERROR_LEVEL)
3788           .errcode(ER_ERROR_INFO_FROM_DA)
3789           .lookup(ER_ERROR_INFO_FROM_DA, error, str);
3790     else
3791       LogEvent()
3792           .type(LOG_TYPE_ERROR)
3793           .prio(ERROR_LEVEL)
3794           .errcode(error)
3795           .verbatim(str);
3796 
3797     /*
3798       This is no longer supported behaviour except for the cases
3799       outlined above, so flag anything else in debug builds!
3800       (We're bailing after rather than before printing to make the
3801       culprit easier to track down.)
3802     */
3803     DBUG_ASSERT((error == ER_FEATURE_NOT_AVAILABLE) ||
3804                 (error >= ER_SERVER_RANGE_START));
3805   }
3806 
3807   /*
3808     Caller wishes to send to client, but none is attached, so we send
3809     to error-log instead.
3810   */
3811   else if (!thd) {
3812     LogEvent()
3813         .type(LOG_TYPE_ERROR)
3814         .subsys(LOG_SUBSYSTEM_TAG)
3815         .prio(ERROR_LEVEL)
3816         .errcode((error < ER_SERVER_RANGE_START)
3817                      ? ER_SERVER_NO_SESSION_TO_SEND_TO
3818                      : error)
3819         .lookup(ER_SERVER_NO_SESSION_TO_SEND_TO, error, str);
3820   }
3821 }
3822 
3823 extern "C" void *my_str_malloc_mysqld(size_t size);
3824 extern "C" void my_str_free_mysqld(void *ptr);
3825 extern "C" void *my_str_realloc_mysqld(void *ptr, size_t size);
3826 
my_str_malloc_mysqld(size_t size)3827 void *my_str_malloc_mysqld(size_t size) {
3828   return my_malloc(key_memory_my_str_malloc, size, MYF(MY_FAE));
3829 }
3830 
my_str_free_mysqld(void * ptr)3831 void my_str_free_mysqld(void *ptr) { my_free(ptr); }
3832 
my_str_realloc_mysqld(void * ptr,size_t size)3833 void *my_str_realloc_mysqld(void *ptr, size_t size) {
3834   return my_realloc(key_memory_my_str_malloc, ptr, size, MYF(MY_FAE));
3835 }
3836 
3837 const char *load_default_groups[] = {
3838 #ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
3839     "mysql_cluster",
3840 #endif
3841     "mysqld",        "server", MYSQL_BASE_VERSION, nullptr, nullptr};
3842 
3843 #if defined(_WIN32)
3844 static const int load_default_groups_sz =
3845     sizeof(load_default_groups) / sizeof(load_default_groups[0]);
3846 #endif
3847 
3848 /**
3849   This function is used to check for stack overrun for pathological
3850   cases of regular expressions and 'like' expressions.
3851   The call to current_thd is quite expensive, so we try to avoid it
3852   for the normal cases.
3853   The size of each stack frame for the wildcmp() routines is ~128 bytes,
3854   so checking *every* recursive call is not necessary.
3855  */
3856 extern "C" {
check_enough_stack_size(int recurse_level)3857 static int check_enough_stack_size(int recurse_level) {
3858   uchar stack_top;
3859   if (recurse_level % 16 != 0) return 0;
3860 
3861   THD *my_thd = current_thd;
3862   if (my_thd != nullptr)
3863     return check_stack_overrun(my_thd, STACK_MIN_SIZE * 4, &stack_top);
3864   return 0;
3865 }
3866 }  // extern "C"
3867 
3868 SHOW_VAR com_status_vars[] = {
3869     {"admin_commands", (char *)offsetof(System_status_var, com_other),
3870      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3871     {"assign_to_keycache",
3872      (char *)offsetof(System_status_var,
3873                       com_stat[(uint)SQLCOM_ASSIGN_TO_KEYCACHE]),
3874      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3875     {"alter_db",
3876      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_ALTER_DB]),
3877      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3878     {"alter_event",
3879      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_ALTER_EVENT]),
3880      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3881     {"alter_function",
3882      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_ALTER_FUNCTION]),
3883      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3884     {"alter_instance",
3885      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_ALTER_INSTANCE]),
3886      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3887     {"alter_procedure",
3888      (char *)offsetof(System_status_var,
3889                       com_stat[(uint)SQLCOM_ALTER_PROCEDURE]),
3890      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3891     {"alter_resource_group",
3892      (char *)offsetof(System_status_var,
3893                       com_stat[(uint)SQLCOM_ALTER_RESOURCE_GROUP]),
3894      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3895     {"alter_server",
3896      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_ALTER_SERVER]),
3897      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3898     {"alter_table",
3899      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_ALTER_TABLE]),
3900      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3901     {"alter_tablespace",
3902      (char *)offsetof(System_status_var,
3903                       com_stat[(uint)SQLCOM_ALTER_TABLESPACE]),
3904      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3905     {"alter_user",
3906      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_ALTER_USER]),
3907      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3908     {"alter_user_default_role",
3909      (char *)offsetof(System_status_var,
3910                       com_stat[(uint)SQLCOM_ALTER_USER_DEFAULT_ROLE]),
3911      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3912     {"analyze",
3913      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_ANALYZE]),
3914      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3915     {"begin", (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_BEGIN]),
3916      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3917     {"binlog",
3918      (char *)offsetof(System_status_var,
3919                       com_stat[(uint)SQLCOM_BINLOG_BASE64_EVENT]),
3920      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3921     {"call_procedure",
3922      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CALL]),
3923      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3924     {"change_db",
3925      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CHANGE_DB]),
3926      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3927     {"change_master",
3928      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CHANGE_MASTER]),
3929      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3930     {"change_repl_filter",
3931      (char *)offsetof(System_status_var,
3932                       com_stat[(uint)SQLCOM_CHANGE_REPLICATION_FILTER]),
3933      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3934     {"check", (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CHECK]),
3935      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3936     {"checksum",
3937      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CHECKSUM]),
3938      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3939     {"clone", (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CLONE]),
3940      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3941     {"commit",
3942      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_COMMIT]),
3943      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3944     {"create_db",
3945      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CREATE_DB]),
3946      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3947     {"create_event",
3948      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CREATE_EVENT]),
3949      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3950     {"create_function",
3951      (char *)offsetof(System_status_var,
3952                       com_stat[(uint)SQLCOM_CREATE_SPFUNCTION]),
3953      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3954     {"create_index",
3955      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CREATE_INDEX]),
3956      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3957     {"create_procedure",
3958      (char *)offsetof(System_status_var,
3959                       com_stat[(uint)SQLCOM_CREATE_PROCEDURE]),
3960      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3961     {"create_role",
3962      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CREATE_ROLE]),
3963      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3964     {"create_server",
3965      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CREATE_SERVER]),
3966      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3967     {"create_table",
3968      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CREATE_TABLE]),
3969      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3970     {"create_resource_group",
3971      (char *)offsetof(System_status_var,
3972                       com_stat[(uint)SQLCOM_CREATE_RESOURCE_GROUP]),
3973      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3974     {"create_trigger",
3975      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CREATE_TRIGGER]),
3976      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3977     {"create_udf",
3978      (char *)offsetof(System_status_var,
3979                       com_stat[(uint)SQLCOM_CREATE_FUNCTION]),
3980      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3981     {"create_user",
3982      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CREATE_USER]),
3983      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3984     {"create_view",
3985      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CREATE_VIEW]),
3986      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3987     {"create_spatial_reference_system",
3988      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_CREATE_SRS]),
3989      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3990     {"dealloc_sql",
3991      (char *)offsetof(System_status_var,
3992                       com_stat[(uint)SQLCOM_DEALLOCATE_PREPARE]),
3993      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3994     {"delete",
3995      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DELETE]),
3996      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
3997     {"delete_multi",
3998      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DELETE_MULTI]),
3999      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4000     {"do", (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DO]),
4001      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4002     {"drop_db",
4003      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DROP_DB]),
4004      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4005     {"drop_event",
4006      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DROP_EVENT]),
4007      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4008     {"drop_function",
4009      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DROP_FUNCTION]),
4010      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4011     {"drop_index",
4012      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DROP_INDEX]),
4013      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4014     {"drop_procedure",
4015      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DROP_PROCEDURE]),
4016      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4017     {"drop_resource_group",
4018      (char *)offsetof(System_status_var,
4019                       com_stat[(uint)SQLCOM_DROP_RESOURCE_GROUP]),
4020      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4021     {"drop_role",
4022      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DROP_ROLE]),
4023      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4024     {"drop_server",
4025      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DROP_SERVER]),
4026      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4027     {"drop_spatial_reference_system",
4028      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DROP_SRS]),
4029      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4030     {"drop_table",
4031      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DROP_TABLE]),
4032      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4033     {"drop_trigger",
4034      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DROP_TRIGGER]),
4035      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4036     {"drop_user",
4037      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DROP_USER]),
4038      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4039     {"drop_view",
4040      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_DROP_VIEW]),
4041      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4042     {"empty_query",
4043      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_EMPTY_QUERY]),
4044      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4045     {"execute_sql",
4046      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_EXECUTE]),
4047      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4048     {"explain_other",
4049      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_EXPLAIN_OTHER]),
4050      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4051     {"flush", (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_FLUSH]),
4052      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4053     {"get_diagnostics",
4054      (char *)offsetof(System_status_var,
4055                       com_stat[(uint)SQLCOM_GET_DIAGNOSTICS]),
4056      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4057     {"grant", (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_GRANT]),
4058      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4059     {"grant_roles",
4060      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_GRANT_ROLE]),
4061      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4062     {"ha_close",
4063      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_HA_CLOSE]),
4064      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4065     {"ha_open",
4066      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_HA_OPEN]),
4067      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4068     {"ha_read",
4069      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_HA_READ]),
4070      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4071     {"help", (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_HELP]),
4072      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4073     {"import",
4074      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_IMPORT]),
4075      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4076     {"insert",
4077      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_INSERT]),
4078      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4079     {"insert_select",
4080      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_INSERT_SELECT]),
4081      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4082     {"install_component",
4083      (char *)offsetof(System_status_var,
4084                       com_stat[(uint)SQLCOM_INSTALL_COMPONENT]),
4085      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4086     {"install_plugin",
4087      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_INSTALL_PLUGIN]),
4088      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4089     {"kill", (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_KILL]),
4090      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4091     {"load", (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_LOAD]),
4092      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4093     {"lock_instance",
4094      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_LOCK_INSTANCE]),
4095      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4096     {"lock_tables",
4097      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_LOCK_TABLES]),
4098      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4099     {"optimize",
4100      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_OPTIMIZE]),
4101      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4102     {"preload_keys",
4103      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_PRELOAD_KEYS]),
4104      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4105     {"prepare_sql",
4106      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_PREPARE]),
4107      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4108     {"purge", (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_PURGE]),
4109      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4110     {"purge_before_date",
4111      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_PURGE_BEFORE]),
4112      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4113     {"release_savepoint",
4114      (char *)offsetof(System_status_var,
4115                       com_stat[(uint)SQLCOM_RELEASE_SAVEPOINT]),
4116      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4117     {"rename_table",
4118      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_RENAME_TABLE]),
4119      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4120     {"rename_user",
4121      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_RENAME_USER]),
4122      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4123     {"repair",
4124      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_REPAIR]),
4125      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4126     {"replace",
4127      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_REPLACE]),
4128      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4129     {"replace_select",
4130      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_REPLACE_SELECT]),
4131      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4132     {"reset", (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_RESET]),
4133      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4134     {"resignal",
4135      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_RESIGNAL]),
4136      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4137     {"restart",
4138      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_RESTART_SERVER]),
4139      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4140     {"revoke",
4141      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_REVOKE]),
4142      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4143     {"revoke_all",
4144      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_REVOKE_ALL]),
4145      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4146     {"revoke_roles",
4147      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_REVOKE_ROLE]),
4148      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4149     {"rollback",
4150      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_ROLLBACK]),
4151      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4152     {"rollback_to_savepoint",
4153      (char *)offsetof(System_status_var,
4154                       com_stat[(uint)SQLCOM_ROLLBACK_TO_SAVEPOINT]),
4155      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4156     {"savepoint",
4157      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SAVEPOINT]),
4158      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4159     {"select",
4160      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SELECT]),
4161      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4162     {"set_option",
4163      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SET_OPTION]),
4164      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4165     {"set_password",
4166      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SET_PASSWORD]),
4167      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4168     {"set_resource_group",
4169      (char *)offsetof(System_status_var,
4170                       com_stat[(uint)SQLCOM_SET_RESOURCE_GROUP]),
4171      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4172     {"set_role",
4173      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SET_ROLE]),
4174      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4175     {"signal",
4176      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SIGNAL]),
4177      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4178     {"show_binlog_events",
4179      (char *)offsetof(System_status_var,
4180                       com_stat[(uint)SQLCOM_SHOW_BINLOG_EVENTS]),
4181      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4182     {"show_binlogs",
4183      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_BINLOGS]),
4184      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4185     {"show_charsets",
4186      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_CHARSETS]),
4187      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4188     {"show_collations",
4189      (char *)offsetof(System_status_var,
4190                       com_stat[(uint)SQLCOM_SHOW_COLLATIONS]),
4191      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4192     {"show_create_db",
4193      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_CREATE_DB]),
4194      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4195     {"show_create_event",
4196      (char *)offsetof(System_status_var,
4197                       com_stat[(uint)SQLCOM_SHOW_CREATE_EVENT]),
4198      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4199     {"show_create_func",
4200      (char *)offsetof(System_status_var,
4201                       com_stat[(uint)SQLCOM_SHOW_CREATE_FUNC]),
4202      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4203     {"show_create_proc",
4204      (char *)offsetof(System_status_var,
4205                       com_stat[(uint)SQLCOM_SHOW_CREATE_PROC]),
4206      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4207     {"show_create_table",
4208      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_CREATE]),
4209      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4210     {"show_create_trigger",
4211      (char *)offsetof(System_status_var,
4212                       com_stat[(uint)SQLCOM_SHOW_CREATE_TRIGGER]),
4213      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4214     {"show_databases",
4215      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_DATABASES]),
4216      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4217     {"show_engine_logs",
4218      (char *)offsetof(System_status_var,
4219                       com_stat[(uint)SQLCOM_SHOW_ENGINE_LOGS]),
4220      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4221     {"show_engine_mutex",
4222      (char *)offsetof(System_status_var,
4223                       com_stat[(uint)SQLCOM_SHOW_ENGINE_MUTEX]),
4224      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4225     {"show_engine_status",
4226      (char *)offsetof(System_status_var,
4227                       com_stat[(uint)SQLCOM_SHOW_ENGINE_STATUS]),
4228      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4229     {"show_events",
4230      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_EVENTS]),
4231      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4232     {"show_errors",
4233      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_ERRORS]),
4234      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4235     {"show_fields",
4236      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_FIELDS]),
4237      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4238     {"show_function_code",
4239      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_FUNC_CODE]),
4240      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4241     {"show_function_status",
4242      (char *)offsetof(System_status_var,
4243                       com_stat[(uint)SQLCOM_SHOW_STATUS_FUNC]),
4244      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4245     {"show_grants",
4246      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_GRANTS]),
4247      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4248     {"show_keys",
4249      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_KEYS]),
4250      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4251     {"show_master_status",
4252      (char *)offsetof(System_status_var,
4253                       com_stat[(uint)SQLCOM_SHOW_MASTER_STAT]),
4254      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4255     {"show_open_tables",
4256      (char *)offsetof(System_status_var,
4257                       com_stat[(uint)SQLCOM_SHOW_OPEN_TABLES]),
4258      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4259     {"show_plugins",
4260      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_PLUGINS]),
4261      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4262     {"show_privileges",
4263      (char *)offsetof(System_status_var,
4264                       com_stat[(uint)SQLCOM_SHOW_PRIVILEGES]),
4265      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4266     {"show_procedure_code",
4267      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_PROC_CODE]),
4268      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4269     {"show_procedure_status",
4270      (char *)offsetof(System_status_var,
4271                       com_stat[(uint)SQLCOM_SHOW_STATUS_PROC]),
4272      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4273     {"show_processlist",
4274      (char *)offsetof(System_status_var,
4275                       com_stat[(uint)SQLCOM_SHOW_PROCESSLIST]),
4276      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4277     {"show_profile",
4278      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_PROFILE]),
4279      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4280     {"show_profiles",
4281      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_PROFILES]),
4282      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4283     {"show_relaylog_events",
4284      (char *)offsetof(System_status_var,
4285                       com_stat[(uint)SQLCOM_SHOW_RELAYLOG_EVENTS]),
4286      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4287     {"show_slave_hosts",
4288      (char *)offsetof(System_status_var,
4289                       com_stat[(uint)SQLCOM_SHOW_SLAVE_HOSTS]),
4290      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4291     {"show_slave_status",
4292      (char *)offsetof(System_status_var,
4293                       com_stat[(uint)SQLCOM_SHOW_SLAVE_STAT]),
4294      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4295     {"show_status",
4296      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_STATUS]),
4297      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4298     {"show_storage_engines",
4299      (char *)offsetof(System_status_var,
4300                       com_stat[(uint)SQLCOM_SHOW_STORAGE_ENGINES]),
4301      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4302     {"show_table_status",
4303      (char *)offsetof(System_status_var,
4304                       com_stat[(uint)SQLCOM_SHOW_TABLE_STATUS]),
4305      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4306     {"show_tables",
4307      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_TABLES]),
4308      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4309     {"show_triggers",
4310      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_TRIGGERS]),
4311      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4312     {"show_variables",
4313      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_VARIABLES]),
4314      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4315     {"show_warnings",
4316      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHOW_WARNS]),
4317      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4318     {"show_create_user",
4319      (char *)offsetof(System_status_var,
4320                       com_stat[(uint)SQLCOM_SHOW_CREATE_USER]),
4321      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4322     {"shutdown",
4323      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SHUTDOWN]),
4324      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4325     {"slave_start",
4326      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SLAVE_START]),
4327      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4328     {"slave_stop",
4329      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_SLAVE_STOP]),
4330      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4331     {"group_replication_start",
4332      (char *)offsetof(System_status_var,
4333                       com_stat[(uint)SQLCOM_START_GROUP_REPLICATION]),
4334      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4335     {"group_replication_stop",
4336      (char *)offsetof(System_status_var,
4337                       com_stat[(uint)SQLCOM_STOP_GROUP_REPLICATION]),
4338      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4339     {"stmt_execute", (char *)offsetof(System_status_var, com_stmt_execute),
4340      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4341     {"stmt_close", (char *)offsetof(System_status_var, com_stmt_close),
4342      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4343     {"stmt_fetch", (char *)offsetof(System_status_var, com_stmt_fetch),
4344      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4345     {"stmt_prepare", (char *)offsetof(System_status_var, com_stmt_prepare),
4346      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4347     {"stmt_reset", (char *)offsetof(System_status_var, com_stmt_reset),
4348      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4349     {"stmt_send_long_data",
4350      (char *)offsetof(System_status_var, com_stmt_send_long_data),
4351      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4352     {"truncate",
4353      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_TRUNCATE]),
4354      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4355     {"uninstall_component",
4356      (char *)offsetof(System_status_var,
4357                       com_stat[(uint)SQLCOM_UNINSTALL_COMPONENT]),
4358      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4359     {"uninstall_plugin",
4360      (char *)offsetof(System_status_var,
4361                       com_stat[(uint)SQLCOM_UNINSTALL_PLUGIN]),
4362      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4363     {"unlock_instance",
4364      (char *)offsetof(System_status_var,
4365                       com_stat[(uint)SQLCOM_UNLOCK_INSTANCE]),
4366      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4367     {"unlock_tables",
4368      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_UNLOCK_TABLES]),
4369      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4370     {"update",
4371      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_UPDATE]),
4372      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4373     {"update_multi",
4374      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_UPDATE_MULTI]),
4375      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4376     {"xa_commit",
4377      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_XA_COMMIT]),
4378      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4379     {"xa_end",
4380      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_XA_END]),
4381      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4382     {"xa_prepare",
4383      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_XA_PREPARE]),
4384      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4385     {"xa_recover",
4386      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_XA_RECOVER]),
4387      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4388     {"xa_rollback",
4389      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_XA_ROLLBACK]),
4390      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4391     {"xa_start",
4392      (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_XA_START]),
4393      SHOW_LONG_STATUS, SHOW_SCOPE_ALL},
4394     {NullS, NullS, SHOW_LONG, SHOW_SCOPE_ALL}};
4395 
4396 LEX_CSTRING sql_statement_names[(uint)SQLCOM_END + 1];
4397 
init_sql_statement_names()4398 static void init_sql_statement_names() {
4399   char *first_com = (char *)offsetof(System_status_var, com_stat[0]);
4400   char *last_com =
4401       (char *)offsetof(System_status_var, com_stat[(uint)SQLCOM_END]);
4402   int record_size = (char *)offsetof(System_status_var, com_stat[1]) -
4403                     (char *)offsetof(System_status_var, com_stat[0]);
4404   char *ptr;
4405   uint i;
4406   uint com_index;
4407 
4408   for (i = 0; i < ((uint)SQLCOM_END + 1); i++)
4409     sql_statement_names[i] = {STRING_WITH_LEN("")};
4410 
4411   SHOW_VAR *var = &com_status_vars[0];
4412   while (var->name != nullptr) {
4413     ptr = var->value;
4414     if ((first_com <= ptr) && (ptr <= last_com)) {
4415       com_index = ((int)(ptr - first_com)) / record_size;
4416       DBUG_ASSERT(com_index < (uint)SQLCOM_END);
4417       sql_statement_names[com_index].str = var->name;
4418       /* TODO: Change SHOW_VAR::name to a LEX_STRING, to avoid strlen() */
4419       sql_statement_names[com_index].length = strlen(var->name);
4420     }
4421     var++;
4422   }
4423 
4424   DBUG_ASSERT(strcmp(sql_statement_names[(uint)SQLCOM_SELECT].str, "select") ==
4425               0);
4426   DBUG_ASSERT(strcmp(sql_statement_names[(uint)SQLCOM_SIGNAL].str, "signal") ==
4427               0);
4428 
4429   sql_statement_names[(uint)SQLCOM_END].str = "error";
4430 }
4431 
4432 #ifdef HAVE_PSI_STATEMENT_INTERFACE
4433 PSI_statement_info sql_statement_info[(uint)SQLCOM_END + 1];
4434 PSI_statement_info com_statement_info[(uint)COM_END + 1];
4435 
4436 /**
4437   Initialize the command names array.
4438   Since we do not want to maintain a separate array,
4439   this is populated from data mined in com_status_vars,
4440   which already has one name for each command.
4441 */
init_sql_statement_info()4442 static void init_sql_statement_info() {
4443   uint i;
4444 
4445   for (i = 0; i < ((uint)SQLCOM_END + 1); i++) {
4446     sql_statement_info[i].m_name = sql_statement_names[i].str;
4447     sql_statement_info[i].m_flags = 0;
4448     sql_statement_info[i].m_documentation = PSI_DOCUMENT_ME;
4449   }
4450 
4451   /* "statement/sql/error" represents broken queries (syntax error). */
4452   sql_statement_info[(uint)SQLCOM_END].m_name = "error";
4453   sql_statement_info[(uint)SQLCOM_END].m_flags = 0;
4454   sql_statement_info[(uint)SQLCOM_END].m_documentation =
4455       "Invalid SQL queries (syntax error).";
4456 
4457   /* "statement/sql/clone" will mutate to clone plugin statement */
4458   sql_statement_info[(uint)SQLCOM_CLONE].m_flags = PSI_FLAG_MUTABLE;
4459 }
4460 
init_com_statement_info()4461 static void init_com_statement_info() {
4462   uint index;
4463 
4464   for (index = 0; index < (uint)COM_END + 1; index++) {
4465     com_statement_info[index].m_name = command_name[index].str;
4466     com_statement_info[index].m_flags = 0;
4467     com_statement_info[index].m_documentation = PSI_DOCUMENT_ME;
4468   }
4469 
4470   /* "statement/abstract/query" can mutate into "statement/sql/..." */
4471   com_statement_info[(uint)COM_QUERY].m_flags = PSI_FLAG_MUTABLE;
4472   com_statement_info[(uint)COM_QUERY].m_documentation =
4473       "SQL query just received from the network. "
4474       "At this point, the real statement type is unknown, "
4475       "the type will be refined after SQL parsing.";
4476 
4477   /* "statement/com/clone" will mutate to clone plugin statement */
4478   com_statement_info[(uint)COM_CLONE].m_flags = PSI_FLAG_MUTABLE;
4479 }
4480 #endif
4481 
4482 /**
4483   Create a replication file name or base for file names.
4484 
4485   @param     key Instrumentation key used to track allocations
4486   @param[in] opt Value of option, or NULL
4487   @param[in] def Default value if option value is not set.
4488   @param[in] ext Extension to use for the path
4489 
4490   @returns Pointer to string containing the full file path, or NULL if
4491   it was not possible to create the path.
4492  */
rpl_make_log_name(PSI_memory_key key,const char * opt,const char * def,const char * ext)4493 static inline const char *rpl_make_log_name(PSI_memory_key key, const char *opt,
4494                                             const char *def, const char *ext) {
4495   DBUG_TRACE;
4496   DBUG_PRINT("enter", ("opt: %s, def: %s, ext: %s", (opt && opt[0]) ? opt : "",
4497                        def, ext));
4498   char buff[FN_REFLEN];
4499   /*
4500     opt[0] needs to be checked to make sure opt name is not an empty
4501     string, incase it is an empty string default name will be considered
4502   */
4503   const char *base = (opt && opt[0]) ? opt : def;
4504   unsigned int options = MY_REPLACE_EXT | MY_UNPACK_FILENAME | MY_SAFE_PATH;
4505 
4506   /* mysql_real_data_home_ptr may be null if no value of datadir has been
4507      specified through command-line or througha cnf file. If that is the
4508      case we make mysql_real_data_home_ptr point to mysql_real_data_home
4509      which, in that case holds the default path for data-dir.
4510   */
4511 
4512   DBUG_EXECUTE_IF("emulate_empty_datadir_param",
4513                   { mysql_real_data_home_ptr = nullptr; };);
4514 
4515   if (mysql_real_data_home_ptr == nullptr)
4516     mysql_real_data_home_ptr = mysql_real_data_home;
4517 
4518   if (fn_format(buff, base, mysql_real_data_home_ptr, ext, options))
4519     return my_strdup(key, buff, MYF(0));
4520   else
4521     return nullptr;
4522 }
4523 
init_common_variables()4524 int init_common_variables() {
4525   umask(((~my_umask) & 0666));
4526   my_decimal_set_zero(&decimal_zero);  // set decimal_zero constant;
4527   tzset();                             // Set tzname
4528 
4529   max_system_variables.pseudo_thread_id = (my_thread_id)~0;
4530   server_start_time = flush_status_time = my_time(0);
4531 
4532   binlog_filter = new Rpl_filter;
4533   if (!binlog_filter) {
4534     LogErr(ERROR_LEVEL, ER_RPL_BINLOG_FILTERS_OOM, strerror(errno));
4535     return 1;
4536   }
4537 
4538   if (init_thread_environment() || mysql_init_variables()) return 1;
4539 
4540   {
4541     struct tm tm_tmp;
4542     localtime_r(&server_start_time, &tm_tmp);
4543 #ifdef _WIN32
4544     strmake(system_time_zone, _tzname[tm_tmp.tm_isdst != 0 ? 1 : 0],
4545             sizeof(system_time_zone) - 1);
4546 #else
4547     strmake(system_time_zone, tzname[tm_tmp.tm_isdst != 0 ? 1 : 0],
4548             sizeof(system_time_zone) - 1);
4549 #endif
4550   }
4551   /*
4552     We set SYSTEM time zone as reasonable default and
4553     also for failure of my_tz_init() and bootstrap mode.
4554     If user explicitly set time zone with --default-time-zone
4555     option we will change this value in my_tz_init().
4556   */
4557   global_system_variables.time_zone = my_tz_SYSTEM;
4558 
4559 #ifdef HAVE_PSI_INTERFACE
4560   /*
4561     Complete the mysql_bin_log initialization.
4562     Instrumentation keys are known only after the performance schema
4563     initialization, and can not be set in the MYSQL_BIN_LOG constructor (called
4564     before main()).
4565   */
4566   mysql_bin_log.set_psi_keys(
4567       key_BINLOG_LOCK_index, key_BINLOG_LOCK_commit,
4568       key_BINLOG_LOCK_commit_queue, key_BINLOG_LOCK_done,
4569       key_BINLOG_LOCK_flush_queue, key_BINLOG_LOCK_log,
4570       key_BINLOG_LOCK_binlog_end_pos, key_BINLOG_LOCK_sync,
4571       key_BINLOG_LOCK_sync_queue, key_BINLOG_LOCK_xids, key_BINLOG_COND_done,
4572       key_BINLOG_update_cond, key_BINLOG_prep_xids_cond, key_file_binlog,
4573       key_file_binlog_index, key_file_binlog_cache,
4574       key_file_binlog_index_cache);
4575 #endif
4576 
4577   /*
4578     Init mutexes for the global MYSQL_BIN_LOG objects.
4579     As safe_mutex depends on what MY_INIT() does, we can't init the mutexes of
4580     global MYSQL_BIN_LOGs in their constructors, because then they would be
4581     inited before MY_INIT(). So we do it here.
4582   */
4583   mysql_bin_log.init_pthread_objects();
4584 
4585   /* TODO: remove this when my_time_t is 64 bit compatible */
4586   if (!is_time_t_valid_for_timestamp(server_start_time)) {
4587     LogErr(ERROR_LEVEL, ER_UNSUPPORTED_DATE);
4588     return 1;
4589   }
4590 
4591   if (gethostname(glob_hostname, sizeof(glob_hostname)) < 0) {
4592     strmake(glob_hostname, STRING_WITH_LEN("localhost"));
4593     LogErr(WARNING_LEVEL, ER_CALL_ME_LOCALHOST, glob_hostname);
4594     strmake(default_logfile_name, STRING_WITH_LEN("mysql"));
4595   } else
4596     strmake(default_logfile_name, glob_hostname,
4597             sizeof(default_logfile_name) - 5);
4598 
4599   strmake(default_binlogfile_name, STRING_WITH_LEN("binlog"));
4600   if (opt_initialize || opt_initialize_insecure) {
4601     /*
4602       System tables initialization are not binary logged (regardless
4603       --log-bin option).
4604 
4605       Disable binary log while executing any user script sourced while
4606       initializing system except if explicitly requested.
4607     */
4608     opt_bin_log = false;
4609   }
4610 
4611   strmake(pidfile_name, default_logfile_name, sizeof(pidfile_name) - 5);
4612   my_stpcpy(fn_ext(pidfile_name), ".pid");  // Add proper extension
4613 
4614   /*
4615     The default-storage-engine entry in my_long_options should have a
4616     non-null default value. It was earlier intialized as
4617     (longlong)"MyISAM" in my_long_options but this triggered a
4618     compiler error in the Sun Studio 12 compiler. As a work-around we
4619     set the def_value member to 0 in my_long_options and initialize it
4620     to the correct value here.
4621 
4622     From MySQL 5.5 onwards, the default storage engine is InnoDB.
4623   */
4624   default_storage_engine = "InnoDB";
4625   default_tmp_storage_engine = default_storage_engine;
4626 
4627   /*
4628     Add server status variables to the dynamic list of
4629     status variables that is shown by SHOW STATUS.
4630     Later, in plugin_register_builtin_and_init_core_se(),
4631     plugin_register_dynamic_and_init_all() and
4632     mysql_install_plugin(), new entries could be added
4633     to that list.
4634   */
4635   if (add_status_vars(status_vars)) return 1;  // an error was already reported
4636 
4637 #ifndef DBUG_OFF
4638   /*
4639     We have few debug-only commands in com_status_vars, only visible in debug
4640     builds. for simplicity we enable the assert only in debug builds
4641 
4642     There are 8 Com_ variables which don't have corresponding SQLCOM_ values:
4643     (TODO strictly speaking they shouldn't be here, should not have Com_ prefix
4644     that is. Perhaps Stmt_ ? Comstmt_ ? Prepstmt_ ?)
4645 
4646       Com_admin_commands       => com_other
4647       Com_stmt_close           => com_stmt_close
4648       Com_stmt_execute         => com_stmt_execute
4649       Com_stmt_fetch           => com_stmt_fetch
4650       Com_stmt_prepare         => com_stmt_prepare
4651       Com_stmt_reprepare       => com_stmt_reprepare
4652       Com_stmt_reset           => com_stmt_reset
4653       Com_stmt_send_long_data  => com_stmt_send_long_data
4654 
4655     With this correction the number of Com_ variables (number of elements in
4656     the array, excluding the last element - terminator) must match the number
4657     of SQLCOM_ constants.
4658   */
4659   static_assert(sizeof(com_status_vars) / sizeof(com_status_vars[0]) - 1 ==
4660                     SQLCOM_END + 7,
4661                 "");
4662 #endif
4663 
4664   if (get_options(&remaining_argc, &remaining_argv)) return 1;
4665 
4666   /*
4667     The opt_bin_log can be false (binary log is disabled) only if
4668     --skip-log-bin/--disable-log-bin is configured or while the
4669     system is initializing.
4670   */
4671   if (!opt_bin_log) {
4672     /*
4673       The log-slave-updates should be disabled if binary log is disabled
4674       and --log-slave-updates option is not set explicitly on command
4675       line or configuration file.
4676     */
4677     if (!log_slave_updates_supplied) opt_log_slave_updates = false;
4678     /*
4679       The slave-preserve-commit-order should be disabled if binary log is
4680       disabled and --slave-preserve-commit-order option is not set
4681       explicitly on command line or configuration file.
4682     */
4683     if (!slave_preserve_commit_order_supplied)
4684       opt_slave_preserve_commit_order = false;
4685   }
4686 
4687   if (opt_protocol_compression_algorithms) {
4688     if ((opt_protocol_compression_algorithms[0] == 0) ||
4689         (validate_compression_attributes(
4690             std::string(opt_protocol_compression_algorithms), std::string(),
4691             true))) {
4692       /*
4693        --protocol-compression-algorithms is set to invalid value, resetting
4694        its value to default "zlib,zstd,uncompressed"
4695       */
4696       opt_protocol_compression_algorithms =
4697           const_cast<char *>(PROTOCOL_COMPRESSION_DEFAULT_VALUE);
4698       LogErr(WARNING_LEVEL, ER_PROTOCOL_COMPRESSION_RESET_LOG);
4699     }
4700   }
4701   update_parser_max_mem_size();
4702 
4703   if (set_default_auth_plugin(default_auth_plugin,
4704                               strlen(default_auth_plugin))) {
4705     LogErr(ERROR_LEVEL, ER_AUTH_CANT_SET_DEFAULT_PLUGIN);
4706     return 1;
4707   }
4708   set_server_version();
4709 
4710   if (!is_help_or_validate_option()) {
4711     LogErr(INFORMATION_LEVEL, ER_BASEDIR_SET_TO, mysql_home);
4712   }
4713 
4714   if (!opt_validate_config && (opt_initialize || opt_initialize_insecure)) {
4715     LogErr(SYSTEM_LEVEL, ER_STARTING_INIT, my_progname, server_version,
4716            (ulong)getpid());
4717   } else if (!is_help_or_validate_option()) {
4718     LogErr(SYSTEM_LEVEL, ER_STARTING_AS, my_progname, server_version,
4719            (ulong)getpid());
4720   }
4721   if (opt_help && !opt_verbose) unireg_abort(MYSQLD_SUCCESS_EXIT);
4722 
4723   DBUG_PRINT("info", ("%s  Ver %s for %s on %s\n", my_progname, server_version,
4724                       SYSTEM_TYPE, MACHINE_TYPE));
4725 
4726 #ifdef HAVE_LINUX_LARGE_PAGES
4727   /* Initialize large page size */
4728   if (opt_large_pages && (opt_large_page_size = my_get_large_page_size())) {
4729     DBUG_PRINT("info",
4730                ("Large page set, large_page_size = %d", opt_large_page_size));
4731   } else {
4732     opt_large_pages = false;
4733     /*
4734        Either not configured to use large pages or Linux haven't
4735        been compiled with large page support
4736     */
4737   }
4738 #endif /* HAVE_LINUX_LARGE_PAGES */
4739 #ifdef HAVE_SOLARIS_LARGE_PAGES
4740 #define LARGE_PAGESIZE (4 * 1024 * 1024)         /* 4MB */
4741 #define SUPER_LARGE_PAGESIZE (256 * 1024 * 1024) /* 256MB */
4742   if (opt_large_pages) {
4743     /*
4744       tell the kernel that we want to use 4/256MB page for heap storage
4745       and also for the stack. We use 4 MByte as default and if the
4746       super-large-page is set we increase it to 256 MByte. 256 MByte
4747       is for server installations with GBytes of RAM memory where
4748       the MySQL Server will have page caches and other memory regions
4749       measured in a number of GBytes.
4750       We use as big pages as possible which isn't bigger than the above
4751       desired page sizes.
4752     */
4753     int nelem;
4754     size_t max_desired_page_size;
4755     if (opt_super_large_pages)
4756       max_desired_page_size = SUPER_LARGE_PAGESIZE;
4757     else
4758       max_desired_page_size = LARGE_PAGESIZE;
4759     nelem = getpagesizes(NULL, 0);
4760     if (nelem > 0) {
4761       size_t *pagesize = (size_t *)malloc(sizeof(size_t) * nelem);
4762       if (pagesize != NULL && getpagesizes(pagesize, nelem) > 0) {
4763         size_t max_page_size = 0;
4764         for (int i = 0; i < nelem; i++) {
4765           if (pagesize[i] > max_page_size &&
4766               pagesize[i] <= max_desired_page_size)
4767             max_page_size = pagesize[i];
4768         }
4769         free(pagesize);
4770         if (max_page_size > 0) {
4771           struct memcntl_mha mpss;
4772 
4773           mpss.mha_cmd = MHA_MAPSIZE_BSSBRK;
4774           mpss.mha_pagesize = max_page_size;
4775           mpss.mha_flags = 0;
4776           memcntl(NULL, 0, MC_HAT_ADVISE, (caddr_t)&mpss, 0, 0);
4777           mpss.mha_cmd = MHA_MAPSIZE_STACK;
4778           memcntl(NULL, 0, MC_HAT_ADVISE, (caddr_t)&mpss, 0, 0);
4779         }
4780       }
4781     }
4782   }
4783 #endif /* HAVE_SOLARIS_LARGE_PAGES */
4784 
4785   longlong default_value;
4786   sys_var *var;
4787   /* Calculate and update default value for thread_cache_size. */
4788   if ((default_value = 8 + max_connections / 100) > 100) default_value = 100;
4789   var = intern_find_sys_var(STRING_WITH_LEN("thread_cache_size"));
4790   var->update_default(default_value);
4791 
4792   /* Calculate and update default value for host_cache_size. */
4793   if ((default_value = 128 + max_connections) > 628 &&
4794       (default_value = 628 + ((max_connections - 500) / 20)) > 2000)
4795     default_value = 2000;
4796   var = intern_find_sys_var(STRING_WITH_LEN("host_cache_size"));
4797   var->update_default(default_value);
4798 
4799   /* Fix thread_cache_size. */
4800   if (!thread_cache_size_specified &&
4801       (Per_thread_connection_handler::max_blocked_pthreads =
4802            8 + max_connections / 100) > 100)
4803     Per_thread_connection_handler::max_blocked_pthreads = 100;
4804 
4805   /* Fix host_cache_size. */
4806   if (!host_cache_size_specified &&
4807       (host_cache_size = 128 + max_connections) > 628 &&
4808       (host_cache_size = 628 + ((max_connections - 500) / 20)) > 2000)
4809     host_cache_size = 2000;
4810 
4811   /* Fix back_log */
4812   if (back_log == 0 && (back_log = max_connections) > 65535) back_log = 65535;
4813 
4814   unireg_init(opt_specialflag); /* Set up extern variables */
4815   while (!(my_default_lc_messages =
4816                my_locale_by_name(nullptr, lc_messages, strlen(lc_messages)))) {
4817     LogErr(ERROR_LEVEL, ER_FAILED_TO_FIND_LOCALE_NAME, lc_messages);
4818     if (!my_strcasecmp(&my_charset_latin1, lc_messages,
4819                        mysqld_default_locale_name))
4820       return 1;
4821     lc_messages = mysqld_default_locale_name;
4822   }
4823   global_system_variables.lc_messages = my_default_lc_messages;
4824   if (init_errmessage()) /* Read error messages from file */
4825     return 1;
4826   init_client_errs();
4827 
4828   mysql_client_plugin_init();
4829   if (item_create_init()) return 1;
4830   item_init();
4831   range_optimizer_init();
4832   my_string_stack_guard = check_enough_stack_size;
4833   /*
4834     Process a comma-separated character set list and choose
4835     the first available character set. This is mostly for
4836     test purposes, to be able to start "mysqld" even if
4837     the requested character set is not available (see bug#18743).
4838   */
4839   for (;;) {
4840     char *next_character_set_name =
4841         strchr(const_cast<char *>(default_character_set_name), ',');
4842     if (next_character_set_name) *next_character_set_name++ = '\0';
4843     if (!(default_charset_info = get_charset_by_csname(
4844               default_character_set_name, MY_CS_PRIMARY, MYF(MY_WME)))) {
4845       if (next_character_set_name) {
4846         default_character_set_name = next_character_set_name;
4847         default_collation_name = nullptr;  // Ignore collation
4848       } else
4849         return 1;  // Eof of the list
4850     } else {
4851       warn_on_deprecated_charset(nullptr, default_charset_info,
4852                                  default_character_set_name,
4853                                  "--character-set-server");
4854       break;
4855     }
4856   }
4857 
4858   if (default_collation_name) {
4859     CHARSET_INFO *default_collation;
4860     default_collation = get_charset_by_name(default_collation_name, MYF(0));
4861     if (!default_collation) {
4862       LogErr(ERROR_LEVEL, ER_FAILED_TO_FIND_COLLATION_NAME,
4863              default_collation_name);
4864       return 1;
4865     }
4866     if (!my_charset_same(default_charset_info, default_collation)) {
4867       LogErr(ERROR_LEVEL, ER_INVALID_COLLATION_FOR_CHARSET,
4868              default_collation_name, default_charset_info->csname);
4869       return 1;
4870     }
4871     warn_on_deprecated_collation(nullptr, default_collation,
4872                                  "--collation-server");
4873     default_charset_info = default_collation;
4874   }
4875   /* Set collactions that depends on the default collation */
4876   global_system_variables.collation_server = default_charset_info;
4877   global_system_variables.collation_database = default_charset_info;
4878   global_system_variables.default_collation_for_utf8mb4 =
4879       &my_charset_utf8mb4_0900_ai_ci;
4880 
4881   if (is_supported_parser_charset(default_charset_info)) {
4882     global_system_variables.collation_connection = default_charset_info;
4883     global_system_variables.character_set_results = default_charset_info;
4884     global_system_variables.character_set_client = default_charset_info;
4885   } else {
4886     LogErr(INFORMATION_LEVEL, ER_FIXING_CLIENT_CHARSET,
4887            default_charset_info->csname, my_charset_latin1.csname);
4888     global_system_variables.collation_connection = &my_charset_latin1;
4889     global_system_variables.character_set_results = &my_charset_latin1;
4890     global_system_variables.character_set_client = &my_charset_latin1;
4891   }
4892 
4893   if (!(character_set_filesystem = get_charset_by_csname(
4894             character_set_filesystem_name, MY_CS_PRIMARY, MYF(MY_WME))))
4895     return 1;
4896   else
4897     warn_on_deprecated_charset(nullptr, character_set_filesystem,
4898                                character_set_filesystem_name,
4899                                "--character-set-filesystem");
4900   global_system_variables.character_set_filesystem = character_set_filesystem;
4901 
4902   if (lex_init()) {
4903     LogErr(ERROR_LEVEL, ER_OOM);
4904     return 1;
4905   }
4906 
4907   while (!(my_default_lc_time_names = my_locale_by_name(
4908                nullptr, lc_time_names_name, strlen(lc_time_names_name)))) {
4909     LogErr(ERROR_LEVEL, ER_FAILED_TO_FIND_LOCALE_NAME, lc_time_names_name);
4910     if (!my_strcasecmp(&my_charset_latin1, lc_time_names_name,
4911                        mysqld_default_locale_name))
4912       return 1;
4913     lc_time_names_name = mysqld_default_locale_name;
4914   }
4915   global_system_variables.lc_time_names = my_default_lc_time_names;
4916 
4917   /* check log options and issue warnings if needed */
4918   if (opt_general_log && opt_general_logname &&
4919       !(log_output_options & LOG_FILE) && !(log_output_options & LOG_NONE))
4920     LogErr(WARNING_LEVEL, ER_LOG_FILES_GIVEN_LOG_OUTPUT_IS_TABLE,
4921            "--general-log-file option");
4922 
4923   if (opt_slow_log && opt_slow_logname && !(log_output_options & LOG_FILE) &&
4924       !(log_output_options & LOG_NONE))
4925     LogErr(WARNING_LEVEL, ER_LOG_FILES_GIVEN_LOG_OUTPUT_IS_TABLE,
4926            "--slow-query-log-file option");
4927 
4928   if (opt_general_logname &&
4929       !is_valid_log_name(opt_general_logname, strlen(opt_general_logname))) {
4930     LogErr(ERROR_LEVEL, ER_LOG_FILE_INVALID, "--general_log_file",
4931            opt_general_logname);
4932     return 1;
4933   }
4934 
4935   if (opt_slow_logname &&
4936       !is_valid_log_name(opt_slow_logname, strlen(opt_slow_logname))) {
4937     LogErr(ERROR_LEVEL, ER_LOG_FILE_INVALID, "--slow_query_log_file",
4938            opt_slow_logname);
4939     return 1;
4940   }
4941 
4942   set_mysqld_opt_tracking_mode();
4943   if (global_system_variables.transaction_write_set_extraction ==
4944           HASH_ALGORITHM_OFF &&
4945       mysql_bin_log.m_dependency_tracker.m_opt_tracking_mode !=
4946           DEPENDENCY_TRACKING_COMMIT_ORDER) {
4947     LogErr(ERROR_LEVEL,
4948            ER_TX_EXTRACTION_ALGORITHM_FOR_BINLOG_TX_DEPEDENCY_TRACKING,
4949            "XXHASH64 or MURMUR32", "WRITESET or WRITESET_SESSION");
4950     return 1;
4951   } else
4952     mysql_bin_log.m_dependency_tracker.tracking_mode_changed();
4953 
4954 #define FIX_LOG_VAR(VAR, ALT) \
4955   if (!VAR || !*VAR) VAR = ALT;
4956 
4957   FIX_LOG_VAR(opt_general_logname,
4958               make_query_log_name(logname_path, QUERY_LOG_GENERAL));
4959   FIX_LOG_VAR(opt_slow_logname,
4960               make_query_log_name(slow_logname_path, QUERY_LOG_SLOW));
4961 
4962 #if defined(ENABLED_DEBUG_SYNC)
4963   /* Initialize the debug sync facility. See debug_sync.cc. */
4964   if (debug_sync_init()) return 1; /* purecov: tested */
4965 #endif                             /* defined(ENABLED_DEBUG_SYNC) */
4966 
4967   if (opt_validate_config) return 0;
4968 
4969   /* create the data directory if requested */
4970   if (unlikely(opt_initialize) &&
4971       initialize_create_data_directory(mysql_real_data_home))
4972     return 1;
4973 
4974   /*
4975     Ensure that lower_case_table_names is set on system where we have case
4976     insensitive names.  If this is not done the users MyISAM tables will
4977     get corrupted if accesses with names of different case.
4978   */
4979   DBUG_PRINT("info", ("lower_case_table_names: %d", lower_case_table_names));
4980   lower_case_file_system = test_if_case_insensitive(mysql_real_data_home);
4981   if (!lower_case_table_names && lower_case_file_system == 1) {
4982     if (lower_case_table_names_used) {
4983       LogErr(ERROR_LEVEL, ER_LOWER_CASE_TABLE_NAMES_CS_DD_ON_CI_FS_UNSUPPORTED);
4984       return 1;
4985     } else {
4986       LogErr(WARNING_LEVEL, ER_LOWER_CASE_TABLE_NAMES_USING_2,
4987              mysql_real_data_home);
4988       lower_case_table_names = 2;
4989     }
4990   } else if (lower_case_table_names == 2 &&
4991              !(lower_case_file_system =
4992                    (test_if_case_insensitive(mysql_real_data_home) == 1))) {
4993     LogErr(WARNING_LEVEL, ER_LOWER_CASE_TABLE_NAMES_USING_0,
4994            mysql_real_data_home);
4995     lower_case_table_names = 0;
4996   } else {
4997     lower_case_file_system =
4998         (test_if_case_insensitive(mysql_real_data_home) == 1);
4999   }
5000 
5001   /* Reset table_alias_charset, now that lower_case_table_names is set. */
5002   table_alias_charset =
5003       (lower_case_table_names ? &my_charset_utf8_tolower_ci : &my_charset_bin);
5004 
5005   /*
5006     Build do_table and ignore_table rules to hashes
5007     after the resetting of table_alias_charset.
5008   */
5009   if (rpl_global_filter.build_do_table_hash() ||
5010       rpl_global_filter.build_ignore_table_hash()) {
5011     LogErr(ERROR_LEVEL, ER_CANT_HASH_DO_AND_IGNORE_RULES);
5012     return 1;
5013   }
5014 
5015   /*
5016     Reset the P_S view for global replication filter at
5017     the end of server startup.
5018   */
5019 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
5020   rpl_global_filter.wrlock();
5021   rpl_global_filter.reset_pfs_view();
5022   rpl_global_filter.unlock();
5023 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
5024 
5025   if (rpl_channel_filters.build_do_and_ignore_table_hashes()) return 1;
5026 
5027   return 0;
5028 }
5029 
init_thread_environment()5030 static int init_thread_environment() {
5031   mysql_mutex_init(key_LOCK_status, &LOCK_status, MY_MUTEX_INIT_FAST);
5032   mysql_mutex_init(key_LOCK_manager, &LOCK_manager, MY_MUTEX_INIT_FAST);
5033   mysql_mutex_init(key_LOCK_crypt, &LOCK_crypt, MY_MUTEX_INIT_FAST);
5034   mysql_mutex_init(key_LOCK_user_conn, &LOCK_user_conn, MY_MUTEX_INIT_FAST);
5035   mysql_mutex_init(key_LOCK_global_system_variables,
5036                    &LOCK_global_system_variables, MY_MUTEX_INIT_FAST);
5037   mysql_rwlock_init(key_rwlock_LOCK_system_variables_hash,
5038                     &LOCK_system_variables_hash);
5039   mysql_mutex_init(key_LOCK_prepared_stmt_count, &LOCK_prepared_stmt_count,
5040                    MY_MUTEX_INIT_FAST);
5041   mysql_mutex_init(key_LOCK_sql_slave_skip_counter,
5042                    &LOCK_sql_slave_skip_counter, MY_MUTEX_INIT_FAST);
5043   mysql_mutex_init(key_LOCK_slave_net_timeout, &LOCK_slave_net_timeout,
5044                    MY_MUTEX_INIT_FAST);
5045   mysql_mutex_init(key_LOCK_slave_trans_dep_tracker,
5046                    &LOCK_slave_trans_dep_tracker, MY_MUTEX_INIT_FAST);
5047   mysql_mutex_init(key_LOCK_error_messages, &LOCK_error_messages,
5048                    MY_MUTEX_INIT_FAST);
5049   mysql_mutex_init(key_LOCK_uuid_generator, &LOCK_uuid_generator,
5050                    MY_MUTEX_INIT_FAST);
5051   mysql_mutex_init(key_LOCK_sql_rand, &LOCK_sql_rand, MY_MUTEX_INIT_FAST);
5052   mysql_mutex_init(key_LOCK_log_throttle_qni, &LOCK_log_throttle_qni,
5053                    MY_MUTEX_INIT_FAST);
5054   mysql_mutex_init(key_LOCK_default_password_lifetime,
5055                    &LOCK_default_password_lifetime, MY_MUTEX_INIT_FAST);
5056   mysql_mutex_init(key_LOCK_mandatory_roles, &LOCK_mandatory_roles,
5057                    MY_MUTEX_INIT_FAST);
5058   mysql_mutex_init(key_LOCK_password_history, &LOCK_password_history,
5059                    MY_MUTEX_INIT_FAST);
5060   mysql_mutex_init(key_LOCK_password_reuse_interval,
5061                    &LOCK_password_reuse_interval, MY_MUTEX_INIT_FAST);
5062   mysql_rwlock_init(key_rwlock_LOCK_sys_init_connect, &LOCK_sys_init_connect);
5063   mysql_rwlock_init(key_rwlock_LOCK_sys_init_slave, &LOCK_sys_init_slave);
5064   mysql_cond_init(key_COND_manager, &COND_manager);
5065   mysql_mutex_init(key_LOCK_server_started, &LOCK_server_started,
5066                    MY_MUTEX_INIT_FAST);
5067   mysql_cond_init(key_COND_server_started, &COND_server_started);
5068   mysql_mutex_init(key_LOCK_reset_gtid_table, &LOCK_reset_gtid_table,
5069                    MY_MUTEX_INIT_FAST);
5070   mysql_mutex_init(key_LOCK_compress_gtid_table, &LOCK_compress_gtid_table,
5071                    MY_MUTEX_INIT_FAST);
5072   mysql_mutex_init(key_LOCK_collect_instance_log, &LOCK_collect_instance_log,
5073                    MY_MUTEX_INIT_FAST);
5074   mysql_cond_init(key_COND_compress_gtid_table, &COND_compress_gtid_table);
5075   Events::init_mutexes();
5076 #if defined(_WIN32)
5077   mysql_mutex_init(key_LOCK_handler_count, &LOCK_handler_count,
5078                    MY_MUTEX_INIT_FAST);
5079   mysql_cond_init(key_COND_handler_count, &COND_handler_count);
5080   mysql_rwlock_init(key_rwlock_LOCK_named_pipe_full_access_group,
5081                     &LOCK_named_pipe_full_access_group);
5082 #else
5083   mysql_mutex_init(key_LOCK_socket_listener_active,
5084                    &LOCK_socket_listener_active, MY_MUTEX_INIT_FAST);
5085   mysql_cond_init(key_COND_socket_listener_active,
5086                   &COND_socket_listener_active);
5087   mysql_mutex_init(key_LOCK_start_signal_handler, &LOCK_start_signal_handler,
5088                    MY_MUTEX_INIT_FAST);
5089   mysql_cond_init(key_COND_start_signal_handler, &COND_start_signal_handler);
5090 #endif  // _WIN32
5091   /* Parameter for threads created for connections */
5092   (void)my_thread_attr_init(&connection_attrib);
5093   my_thread_attr_setdetachstate(&connection_attrib, MY_THREAD_CREATE_DETACHED);
5094 #ifndef _WIN32
5095   pthread_attr_setscope(&connection_attrib, PTHREAD_SCOPE_SYSTEM);
5096 #endif
5097 
5098   mysql_mutex_init(key_LOCK_keyring_operations, &LOCK_keyring_operations,
5099                    MY_MUTEX_INIT_FAST);
5100   mysql_mutex_init(key_LOCK_tls_ctx_options, &LOCK_tls_ctx_options,
5101                    MY_MUTEX_INIT_FAST);
5102   mysql_mutex_init(key_LOCK_rotate_binlog_master_key,
5103                    &LOCK_rotate_binlog_master_key, MY_MUTEX_INIT_FAST);
5104   mysql_mutex_init(key_LOCK_admin_tls_ctx_options, &LOCK_admin_tls_ctx_options,
5105                    MY_MUTEX_INIT_FAST);
5106   return 0;
5107 }
5108 
5109 #if !defined(__sun)
5110 /* TODO: remove the !defined(__sun) when bug 23285559 is out of the picture */
5111 
5112 static PSI_memory_key key_memory_openssl = PSI_NOT_INSTRUMENTED;
5113 
5114 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
5115 #define FILE_LINE_ARGS
5116 #else
5117 #define FILE_LINE_ARGS , const char *, int
5118 #endif
5119 
my_openssl_malloc(size_t size FILE_LINE_ARGS)5120 static void *my_openssl_malloc(size_t size FILE_LINE_ARGS) {
5121   return my_malloc(key_memory_openssl, size, MYF(MY_WME));
5122 }
my_openssl_realloc(void * ptr,size_t size FILE_LINE_ARGS)5123 static void *my_openssl_realloc(void *ptr, size_t size FILE_LINE_ARGS) {
5124   return my_realloc(key_memory_openssl, ptr, size, MYF(MY_WME));
5125 }
my_openssl_free(void * ptr FILE_LINE_ARGS)5126 static void my_openssl_free(void *ptr FILE_LINE_ARGS) { return my_free(ptr); }
5127 #endif /* !defined(__sun) */
5128 
init_ssl()5129 static void init_ssl() {
5130 #if !defined(__sun)
5131 #if defined(HAVE_PSI_MEMORY_INTERFACE)
5132   static PSI_memory_info all_openssl_memory[] = {
5133       {&key_memory_openssl, "openssl_malloc", 0, 0,
5134        "All memory used by openSSL"}};
5135   mysql_memory_register("mysqld_openssl", all_openssl_memory,
5136                         (int)array_elements(all_openssl_memory));
5137 #endif /* defined(HAVE_PSI_MEMORY_INTERFACE) */
5138   int ret = CRYPTO_set_mem_functions(my_openssl_malloc, my_openssl_realloc,
5139                                      my_openssl_free);
5140   if (ret == 0)
5141     LogErr(WARNING_LEVEL, ER_SSL_MEMORY_INSTRUMENTATION_INIT_FAILED,
5142            "CRYPTO_set_mem_functions");
5143 #endif /* !defined(__sun) */
5144   ssl_start();
5145 }
5146 
init_ssl_communication()5147 static int init_ssl_communication() {
5148 #if !defined(XTRABACKUP)
5149   char ssl_err_string[OPENSSL_ERROR_LENGTH] = {'\0'};
5150   int ret_fips_mode = set_fips_mode(opt_ssl_fips_mode, ssl_err_string);
5151   if (ret_fips_mode != 1) {
5152     LogErr(ERROR_LEVEL, ER_SSL_FIPS_MODE_ERROR, ssl_err_string);
5153     return 1;
5154   }
5155   if (TLS_channel::singleton_init(&mysql_main, mysql_main_channel, opt_use_ssl,
5156                                   &server_main_callback, opt_initialize))
5157     return 1;
5158 
5159   /*
5160     The default value of --admin-ssl is ON. If it is set
5161     to off, we should treat it as an explicit attempt to
5162     set TLS off for admin channel and thereby not use
5163     main channel's TLS configuration.
5164   */
5165   if (!opt_use_admin_ssl) g_admin_ssl_configured = true;
5166 
5167   bool initialize_admin_tls =
5168       (!opt_initialize && (my_admin_bind_addr_str != nullptr))
5169           ? opt_use_admin_ssl
5170           : false;
5171 
5172   Ssl_init_callback_server_admin server_admin_callback;
5173   if (TLS_channel::singleton_init(&mysql_admin, mysql_admin_channel,
5174                                   initialize_admin_tls, &server_admin_callback,
5175                                   opt_initialize))
5176     return 1;
5177 
5178   if (initialize_admin_tls && !g_admin_ssl_configured) {
5179     Lock_and_access_ssl_acceptor_context context(mysql_main);
5180     if (context.have_ssl())
5181       LogErr(SYSTEM_LEVEL, ER_TLS_CONFIGURATION_REUSED,
5182              mysql_admin_channel.c_str(), mysql_main_channel.c_str());
5183   }
5184 #endif
5185 
5186 #if OPENSSL_VERSION_NUMBER < 0x10100000L
5187   ERR_remove_thread_state(0);
5188 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
5189 
5190   if (init_rsa_keys()) return 1;
5191   return 0;
5192 }
5193 
end_ssl()5194 static void end_ssl() {
5195   TLS_channel::singleton_deinit(mysql_main);
5196   TLS_channel::singleton_deinit(mysql_admin);
5197   deinit_rsa_keys();
5198 }
5199 
5200 /**
5201   Generate a UUID and save it into server_uuid variable.
5202 
5203   @return Retur 0 or 1 if an error occurred.
5204  */
generate_server_uuid()5205 static int generate_server_uuid() {
5206   THD *thd;
5207   Item_func_uuid *func_uuid;
5208   String uuid;
5209 
5210   /*
5211     To be able to run this from boot, we allocate a temporary THD
5212    */
5213   if (!(thd = new THD)) {
5214     LogErr(ERROR_LEVEL, ER_NO_THD_NO_UUID);
5215     return 1;
5216   }
5217   thd->thread_stack = (char *)&thd;
5218   thd->store_globals();
5219 
5220   /*
5221     Initialize the variables which are used during "uuid generator
5222     initialization" with values that should normally differ between
5223     mysqlds on the same host. This avoids that another mysqld started
5224     at the same time on the same host get the same "server_uuid".
5225   */
5226 
5227   const time_t save_server_start_time = server_start_time;
5228   server_start_time += ((ulonglong)current_pid << 48) + current_pid;
5229   thd->status_var.bytes_sent = (ulonglong)thd;
5230 
5231   lex_start(thd);
5232   func_uuid = new (thd->mem_root) Item_func_uuid();
5233   func_uuid->fixed = true;
5234   func_uuid->val_str(&uuid);
5235 
5236   // Restore global variables used for salting
5237   server_start_time = save_server_start_time;
5238 
5239   delete thd;
5240 
5241   strncpy(server_uuid, uuid.c_ptr(), UUID_LENGTH);
5242   DBUG_EXECUTE_IF("server_uuid_deterministic",
5243                   memcpy(server_uuid, "00000000-1111-0000-1111-000000000000",
5244                          UUID_LENGTH););
5245   server_uuid[UUID_LENGTH] = '\0';
5246   return 0;
5247 }
5248 
5249 /**
5250   Save all options which was auto-generated by server-self into the given file.
5251 
5252   @param fname The name of the file in which the auto-generated options will b
5253   e saved.
5254 
5255   @return Return 0 or 1 if an error occurred.
5256  */
flush_auto_options(const char * fname)5257 static int flush_auto_options(const char *fname) {
5258   File fd;
5259   IO_CACHE io_cache;
5260   int result = 0;
5261 
5262   if ((fd = my_open(fname, O_CREAT | O_RDWR, MYF(MY_WME))) < 0) {
5263     LogErr(ERROR_LEVEL, ER_AUTO_OPTIONS_FAILED, "file", fname, my_errno());
5264     return 1;
5265   }
5266 
5267   if (init_io_cache(&io_cache, fd, IO_SIZE * 2, WRITE_CACHE, 0L, false,
5268                     MYF(MY_WME))) {
5269     LogErr(ERROR_LEVEL, ER_AUTO_OPTIONS_FAILED, "a cache on ", fname,
5270            my_errno());
5271     my_close(fd, MYF(MY_WME));
5272     return 1;
5273   }
5274 
5275   my_b_seek(&io_cache, 0L);
5276   my_b_printf(&io_cache, "%s\n", "[auto]");
5277   my_b_printf(&io_cache, "server-uuid=%s\n", server_uuid);
5278 
5279   if (flush_io_cache(&io_cache) || my_sync(fd, MYF(MY_WME))) result = 1;
5280 
5281   my_close(fd, MYF(MY_WME));
5282   end_io_cache(&io_cache);
5283   return result;
5284 }
5285 
5286 /**
5287   File 'auto.cnf' resides in the data directory to hold values of options that
5288   server evaluates itself and that needs to be durable to sustain the server
5289   restart. There is only a section ['auto'] in the file. All these options are
5290   in the section. Only one option exists now, it is server_uuid.
5291   Note, the user may not supply any literal value to these auto-options, and
5292   only allowed to trigger (re)evaluation.
5293   For instance, 'server_uuid' value will be evaluated and stored if there is
5294   no corresponding line in the file.
5295   Because of the specifics of the auto-options, they need a seperate storage.
5296   Meanwhile, it is the 'auto.cnf' that has the same structure as 'my.cnf'.
5297 
5298   @todo consider to implement sql-query-able persistent storage by WL#5279.
5299   @return Return 0 or 1 if an error occurred.
5300  */
init_server_auto_options()5301 static int init_server_auto_options() {
5302   bool flush = false;
5303   char fname[FN_REFLEN];
5304   char name[] = "auto";
5305   char *name_ptr = name;
5306   const char *groups[] = {"auto", nullptr};
5307   char *uuid = nullptr;
5308   my_option auto_options[] = {
5309       {"server-uuid", 0, "", &uuid, &uuid, nullptr, GET_STR, REQUIRED_ARG, 0, 0,
5310        0, nullptr, 0, nullptr},
5311       {nullptr, 0, nullptr, nullptr, nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0,
5312        0, nullptr, 0, nullptr}};
5313 
5314   DBUG_TRACE;
5315 
5316   if (nullptr == fn_format(fname, "auto.cnf", mysql_data_home, "",
5317                            MY_UNPACK_FILENAME | MY_SAFE_PATH))
5318     return 1;
5319 
5320   /* load_defaults require argv[0] is not null */
5321   char **argv = &name_ptr;
5322   int argc = 1;
5323   if (!check_file_permissions(fname, false)) {
5324     /*
5325       Found a world writable file hence removing it as it is dangerous to write
5326       a new UUID into the same file.
5327      */
5328     my_delete(fname, MYF(MY_WME));
5329     LogErr(WARNING_LEVEL, ER_WRITABLE_CONFIG_REMOVED, fname);
5330   }
5331 
5332   /* load all options in 'auto.cnf'. */
5333   MEM_ROOT alloc{PSI_NOT_INSTRUMENTED, 512};
5334   if (my_load_defaults(fname, groups, &argc, &argv, &alloc, nullptr)) return 1;
5335 
5336   if (handle_options(&argc, &argv, auto_options, mysqld_get_one_option))
5337     return 1;
5338 
5339   DBUG_PRINT("info", ("uuid=%p=%s server_uuid=%s", uuid, uuid, server_uuid));
5340   if (uuid) {
5341     if (!binary_log::Uuid::is_valid(uuid, binary_log::Uuid::TEXT_LENGTH)) {
5342       LogErr(ERROR_LEVEL, ER_UUID_INVALID);
5343       goto err;
5344     }
5345     /*
5346       Uuid::is_valid() cannot do strict check on the length as it will be
5347       called by GTID::is_valid() as well (GTID = UUID:seq_no). We should
5348       explicitly add the *length check* here in this function.
5349 
5350       If UUID length is less than '36' (UUID_LENGTH), that error case would have
5351       got caught in above is_valid check. The below check is to make sure that
5352       length is not greater than UUID_LENGTH i.e., there are no extra characters
5353       (Garbage) at the end of the valid UUID.
5354     */
5355     if (strlen(uuid) > UUID_LENGTH) {
5356       LogErr(ERROR_LEVEL, ER_UUID_SCRUB, UUID_LENGTH);
5357       goto err;
5358     }
5359     strcpy(server_uuid, uuid);
5360   } else {
5361     DBUG_PRINT("info", ("generating server_uuid"));
5362     flush = true;
5363     /* server_uuid will be set in the function */
5364     if (generate_server_uuid()) goto err;
5365     DBUG_PRINT("info", ("generated server_uuid=%s", server_uuid));
5366     if (opt_initialize || opt_initialize_insecure) {
5367       LogErr(INFORMATION_LEVEL, ER_CREATING_NEW_UUID_FIRST_START, server_uuid);
5368 
5369     } else {
5370       LogErr(WARNING_LEVEL, ER_CREATING_NEW_UUID, server_uuid);
5371     }
5372   }
5373 
5374   if (flush) return flush_auto_options(fname);
5375   return 0;
5376 err:
5377   return 1;
5378 }
5379 
initialize_storage_engine(const char * se_name,const char * se_kind,plugin_ref * dest_plugin)5380 static bool initialize_storage_engine(const char *se_name, const char *se_kind,
5381                                       plugin_ref *dest_plugin) {
5382   LEX_CSTRING name = {se_name, strlen(se_name)};
5383   plugin_ref plugin;
5384   handlerton *hton;
5385   if ((plugin = ha_resolve_by_name(nullptr, &name, false)))
5386     hton = plugin_data<handlerton *>(plugin);
5387   else {
5388     LogErr(ERROR_LEVEL, ER_UNKNOWN_UNSUPPORTED_STORAGE_ENGINE, se_name);
5389     return true;
5390   }
5391   if (!ha_storage_engine_is_enabled(hton)) {
5392     if (!opt_initialize) {
5393       LogErr(ERROR_LEVEL, ER_DEFAULT_SE_UNAVAILABLE, se_kind, se_name);
5394       return true;
5395     }
5396     DBUG_ASSERT(*dest_plugin);
5397   } else {
5398     /*
5399       Need to unlock as global_system_variables.table_plugin
5400       was acquired during plugin_register_builtin_and_init_core_se()
5401     */
5402     plugin_ref old_dest_plugin = *dest_plugin;
5403     *dest_plugin = plugin;
5404     plugin_unlock(nullptr, old_dest_plugin);
5405   }
5406   return false;
5407 }
5408 
setup_error_log()5409 static void setup_error_log() {
5410 /* Setup logs */
5411 
5412 /*
5413   Enable old-fashioned error log, except when the user has requested
5414   help information. Since the implementation of plugin server
5415   variables the help output is now written much later.
5416 
5417   log_error_dest can be:
5418   disabled_my_option     --log-error was not used or --log-error=
5419   ""                     --log-error without arguments (no '=')
5420   filename               --log-error=filename
5421 */
5422 #ifdef _WIN32
5423   /*
5424     Enable the error log file only if console option is not specified
5425     and --help is not used.
5426   */
5427   bool log_errors_to_file = !is_help_or_validate_option() && !opt_console;
5428 #else
5429   /*
5430     Enable the error log file only if --log-error=filename or --log-error
5431     was used. Logging to file is disabled by default unlike on Windows.
5432   */
5433   bool log_errors_to_file =
5434       !is_help_or_validate_option() && (log_error_dest != disabled_my_option);
5435 #endif
5436 
5437   enum log_error_stage les = LOG_ERROR_STAGE_BUFFERING_UNIPLEX;
5438 
5439   if (log_errors_to_file) {
5440     // Construct filename if no filename was given by the user.
5441     if (!log_error_dest[0] || log_error_dest == disabled_my_option) {
5442 #ifdef _WIN32
5443       const char *filename = pidfile_name;
5444 #else
5445       const char *filename = default_logfile_name;
5446 #endif
5447       fn_format(errorlog_filename_buff, filename, mysql_real_data_home, ".err",
5448                 MY_REPLACE_EXT | /* replace '.<domain>' by '.err', bug#4997 */
5449                     MY_REPLACE_DIR);
5450     } else
5451       fn_format(errorlog_filename_buff, log_error_dest, mysql_data_home, ".err",
5452                 MY_UNPACK_FILENAME);
5453     /*
5454       log_error_dest may have been set to disabled_my_option or "" if no
5455       argument was passed, but we need to show the real name in SHOW VARIABLES.
5456     */
5457     log_error_dest = errorlog_filename_buff;
5458 
5459 #ifndef _WIN32
5460     // Create backup stream to stdout if deamonizing and connected to tty
5461     if (opt_daemonize && isatty(STDOUT_FILENO)) {
5462       nstdout = fdopen(dup(STDOUT_FILENO), "a");
5463       if (nstdout == nullptr) {
5464         LogErr(ERROR_LEVEL, ER_DUP_FD_OPEN_FAILED, "stdout", strerror(errno));
5465         unireg_abort(MYSQLD_ABORT_EXIT);
5466       }
5467       // Display location of error log file on stdout if connected to tty
5468       fprintf(nstdout, "mysqld will log errors to %s\n",
5469               errorlog_filename_buff);
5470     }
5471 #endif /* ndef _WIN32 */
5472 
5473     if (open_error_log(errorlog_filename_buff, false))
5474       unireg_abort(MYSQLD_ABORT_EXIT);
5475 
5476 #ifdef _WIN32
5477       // FreeConsole();        // Remove window
5478 #endif /* _WIN32 */
5479   } else {
5480     // We are logging to stderr and SHOW VARIABLES should reflect that.
5481     log_error_dest = "stderr";
5482 
5483     /*
5484       We have no known file-name, and a non-standard logging pipeline,
5485       so output of multiple log-writers may be multi-plexed to stderr.
5486       This can result in false positives, but since we're only using
5487       this to turn off some optimizations, this seems acceptable for now.
5488       With regard to the pipeline, what matters is that a non-standard
5489       set-up was requested, not that it is actually active at this point
5490       (which it wouldn't be, we do not try to apply a user-supplied
5491       configuration until external components are available).
5492     */
5493     if ((opt_log_error_services == nullptr) ||
5494         (0 != strcmp(LOG_ERROR_SERVICES_DEFAULT, opt_log_error_services)))
5495       les = LOG_ERROR_STAGE_BUFFERING_MULTIPLEX;
5496   }
5497 
5498   log_error_stage_set(les);
5499 }
5500 
init_server_components()5501 static int init_server_components() {
5502   DBUG_TRACE;
5503   /*
5504     We need to call each of these following functions to ensure that
5505     all things are initialized so that unireg_abort() doesn't fail
5506   */
5507   mdl_init();
5508   partitioning_init();
5509   if (table_def_init() | hostname_cache_init(host_cache_size))
5510     unireg_abort(MYSQLD_ABORT_EXIT);
5511 
5512   /*
5513     Timers not needed if only starting with --help.
5514   */
5515   if (!is_help_or_validate_option()) {
5516     if (my_timer_initialize())
5517       LogErr(ERROR_LEVEL, ER_CANT_INIT_TIMER, errno);
5518     else
5519       have_statement_timeout = SHOW_OPTION_YES;
5520   }
5521 
5522   randominit(&sql_rand, (ulong)server_start_time, (ulong)server_start_time / 2);
5523   setup_fpu();
5524   init_slave_list();
5525 
5526   setup_error_log();  // opens the log if needed
5527 
5528   enter_cond_hook = thd_enter_cond;
5529   exit_cond_hook = thd_exit_cond;
5530   enter_stage_hook = thd_enter_stage;
5531   set_waiting_for_disk_space_hook = thd_set_waiting_for_disk_space;
5532   is_killed_hook = thd_killed;
5533 
5534   if (transaction_cache_init()) {
5535     LogErr(ERROR_LEVEL, ER_OOM);
5536     unireg_abort(MYSQLD_ABORT_EXIT);
5537   }
5538 
5539   if (MDL_context_backup_manager::init()) {
5540     LogErr(ERROR_LEVEL, ER_OOM);
5541     unireg_abort(MYSQLD_ABORT_EXIT);
5542   }
5543 
5544   /*
5545     initialize delegates for extension observers, errors have already
5546     been reported in the function
5547   */
5548   if (delegates_init()) unireg_abort(MYSQLD_ABORT_EXIT);
5549 
5550   /* need to configure logging before initializing storage engines */
5551   if (opt_log_slave_updates && !opt_bin_log) {
5552     LogErr(WARNING_LEVEL, ER_NEED_LOG_BIN, "--log-slave-updates");
5553   }
5554   if (binlog_format_used && !opt_bin_log)
5555     LogErr(WARNING_LEVEL, ER_NEED_LOG_BIN, "--binlog-format");
5556 
5557   /* Check that we have not let the format to unspecified at this point */
5558   DBUG_ASSERT((uint)global_system_variables.binlog_format <=
5559               array_elements(binlog_format_names) - 1);
5560 
5561   opt_server_id_mask = ~ulong(0);
5562   opt_server_id_mask =
5563       (opt_server_id_bits == 32) ? ~ulong(0) : (1 << opt_server_id_bits) - 1;
5564   if (server_id != (server_id & opt_server_id_mask)) {
5565     LogErr(ERROR_LEVEL, ER_SERVERID_TOO_LARGE);
5566     unireg_abort(MYSQLD_ABORT_EXIT);
5567   }
5568 
5569   if (opt_bin_log) {
5570     /* Reports an error and aborts, if the --log-bin's path
5571        is a directory.*/
5572     if (opt_bin_logname &&
5573         opt_bin_logname[strlen(opt_bin_logname) - 1] == FN_LIBCHAR) {
5574       LogErr(ERROR_LEVEL, ER_NEED_FILE_INSTEAD_OF_DIR, "--log-bin",
5575              opt_bin_logname);
5576       unireg_abort(MYSQLD_ABORT_EXIT);
5577     }
5578 
5579     /* Reports an error and aborts, if the --log-bin-index's path
5580        is a directory.*/
5581     if (opt_binlog_index_name &&
5582         opt_binlog_index_name[strlen(opt_binlog_index_name) - 1] ==
5583             FN_LIBCHAR) {
5584       LogErr(ERROR_LEVEL, ER_NEED_FILE_INSTEAD_OF_DIR, "--log-bin-index",
5585              opt_binlog_index_name);
5586       unireg_abort(MYSQLD_ABORT_EXIT);
5587     }
5588 
5589     char buf[FN_REFLEN];
5590     const char *ln;
5591     if (log_bin_supplied) {
5592       /*
5593         Binary log basename defaults to "`hostname`-bin" name prefix
5594         if --log-bin is used without argument.
5595       */
5596       ln = mysql_bin_log.generate_name(opt_bin_logname, "-bin", buf);
5597     } else {
5598       /*
5599         Binary log basename defaults to "binlog" name prefix
5600         if --log-bin is not used.
5601       */
5602       ln = mysql_bin_log.generate_name(opt_bin_logname, "", buf);
5603     }
5604 
5605     if (!opt_bin_logname && !opt_binlog_index_name && log_bin_supplied) {
5606       /*
5607         User didn't give us info to name the binlog index file.
5608         Picking `hostname`-bin.index like did in 4.x, causes replication to
5609         fail if the hostname is changed later. So, we would like to instead
5610         require a name. But as we don't want to break many existing setups, we
5611         only give warning, not error.
5612       */
5613       LogErr(INFORMATION_LEVEL, ER_LOG_BIN_BETTER_WITH_NAME, ln);
5614     }
5615     if (ln == buf) {
5616       my_free(opt_bin_logname);
5617       opt_bin_logname = my_strdup(key_memory_opt_bin_logname, buf, MYF(0));
5618     }
5619 
5620     /*
5621       Skip opening the index file if we start with --help. This is necessary
5622       to avoid creating the file in an otherwise empty datadir, which will
5623       cause a succeeding 'mysqld --initialize' to fail.
5624     */
5625     if (!is_help_or_validate_option() &&
5626         mysql_bin_log.open_index_file(opt_binlog_index_name, ln, true)) {
5627       unireg_abort(MYSQLD_ABORT_EXIT);
5628     }
5629   }
5630 
5631   if (opt_bin_log) {
5632     /*
5633       opt_bin_logname[0] needs to be checked to make sure opt binlog name is
5634       not an empty string, incase it is an empty string default file
5635       extension will be passed
5636      */
5637     if (log_bin_supplied) {
5638       log_bin_basename = rpl_make_log_name(
5639           key_memory_MYSQL_BIN_LOG_basename, opt_bin_logname,
5640           default_logfile_name,
5641           (opt_bin_logname && opt_bin_logname[0]) ? "" : "-bin");
5642     } else {
5643       log_bin_basename =
5644           rpl_make_log_name(key_memory_MYSQL_BIN_LOG_basename, opt_bin_logname,
5645                             default_binlogfile_name, "");
5646     }
5647 
5648     log_bin_index =
5649         rpl_make_log_name(key_memory_MYSQL_BIN_LOG_index, opt_binlog_index_name,
5650                           log_bin_basename, ".index");
5651 
5652     if ((!opt_binlog_index_name || !opt_binlog_index_name[0]) &&
5653         log_bin_index) {
5654       strmake(default_binlog_index_name,
5655               log_bin_index + dirname_length(log_bin_index),
5656               FN_REFLEN + index_ext_length - 1);
5657       opt_binlog_index_name = default_binlog_index_name;
5658     }
5659 
5660     if (log_bin_basename == nullptr || log_bin_index == nullptr) {
5661       LogErr(ERROR_LEVEL, ER_RPL_CANT_MAKE_PATHS, (int)FN_REFLEN, (int)FN_LEN);
5662       unireg_abort(MYSQLD_ABORT_EXIT);
5663     }
5664   }
5665 
5666   DBUG_PRINT("debug",
5667              ("opt_bin_logname: %s, opt_relay_logname: %s, pidfile_name: %s",
5668               opt_bin_logname, opt_relay_logname, pidfile_name));
5669 
5670   /*
5671     opt_relay_logname[0] needs to be checked to make sure opt relaylog name is
5672     not an empty string, incase it is an empty string default file
5673     extension will be passed
5674    */
5675   relay_log_basename = rpl_make_log_name(
5676       key_memory_MYSQL_RELAY_LOG_basename, opt_relay_logname,
5677       default_logfile_name,
5678       (opt_relay_logname && opt_relay_logname[0]) ? "" : relay_ext);
5679 
5680   if (!opt_relay_logname || !opt_relay_logname[0]) {
5681     if (relay_log_basename) {
5682       strmake(default_relaylogfile_name,
5683               relay_log_basename + dirname_length(relay_log_basename),
5684               FN_REFLEN + relay_ext_length - 1);
5685       opt_relay_logname = default_relaylogfile_name;
5686     }
5687   } else
5688     opt_relay_logname_supplied = true;
5689 
5690   if (relay_log_basename != nullptr)
5691     relay_log_index = rpl_make_log_name(key_memory_MYSQL_RELAY_LOG_index,
5692                                         opt_relaylog_index_name,
5693                                         relay_log_basename, ".index");
5694 
5695   if (!opt_relaylog_index_name || !opt_relaylog_index_name[0]) {
5696     if (relay_log_index) {
5697       strmake(default_relaylog_index_name,
5698               relay_log_index + dirname_length(relay_log_index),
5699               FN_REFLEN + relay_ext_length + index_ext_length - 1);
5700       opt_relaylog_index_name = default_relaylog_index_name;
5701     }
5702   } else
5703     opt_relaylog_index_name_supplied = true;
5704 
5705   if (relay_log_basename == nullptr || relay_log_index == nullptr) {
5706     LogErr(ERROR_LEVEL, ER_RPL_CANT_MAKE_PATHS, (int)FN_REFLEN, (int)FN_LEN);
5707     unireg_abort(MYSQLD_ABORT_EXIT);
5708   }
5709 
5710   if (log_bin_basename != nullptr &&
5711       !strcmp(log_bin_basename, relay_log_basename)) {
5712     const int bin_ext_length = 4;
5713     char default_binlogfile_name_from_hostname[FN_REFLEN + bin_ext_length];
5714     /* Generate default bin log file name. */
5715     strmake(default_binlogfile_name_from_hostname, default_logfile_name,
5716             FN_REFLEN - 1);
5717     strcat(default_binlogfile_name_from_hostname, "-bin");
5718 
5719     if (!default_relaylogfile_name[0]) {
5720       /* Generate default relay log file name. */
5721       strmake(default_relaylogfile_name, default_logfile_name, FN_REFLEN - 1);
5722       strcat(default_relaylogfile_name, relay_ext);
5723     }
5724     /*
5725       Reports an error and aborts, if the same base name is specified
5726       for both binary and relay logs.
5727     */
5728     LogErr(ERROR_LEVEL, ER_RPL_CANT_HAVE_SAME_BASENAME, log_bin_basename,
5729            "--log-bin", default_binlogfile_name,
5730            default_binlogfile_name_from_hostname, "--relay-log",
5731            default_relaylogfile_name);
5732     unireg_abort(MYSQLD_ABORT_EXIT);
5733   }
5734 
5735   if (global_system_variables.binlog_row_value_options != 0) {
5736     const char *msg = nullptr;
5737     longlong err = ER_BINLOG_ROW_VALUE_OPTION_IGNORED;
5738     if (!opt_bin_log)
5739       msg = "the binary log is disabled";
5740     else if (global_system_variables.binlog_format == BINLOG_FORMAT_STMT)
5741       msg = "binlog_format=STATEMENT";
5742     else if (log_bin_use_v1_row_events) {
5743       msg = "binlog_row_value_options=PARTIAL_JSON";
5744       err = ER_BINLOG_USE_V1_ROW_EVENTS_IGNORED;
5745     } else if (global_system_variables.binlog_row_image ==
5746                BINLOG_ROW_IMAGE_FULL) {
5747       msg = "binlog_row_image=FULL";
5748       err = ER_BINLOG_ROW_VALUE_OPTION_USED_ONLY_FOR_AFTER_IMAGES;
5749     }
5750     if (msg) {
5751       switch (err) {
5752         case ER_BINLOG_ROW_VALUE_OPTION_IGNORED:
5753         case ER_BINLOG_ROW_VALUE_OPTION_USED_ONLY_FOR_AFTER_IMAGES:
5754           LogErr(WARNING_LEVEL, err, msg, "PARTIAL_JSON");
5755           break;
5756         case ER_BINLOG_USE_V1_ROW_EVENTS_IGNORED:
5757           LogErr(WARNING_LEVEL, err, msg);
5758           break;
5759         default:
5760           DBUG_ASSERT(0); /* purecov: deadcode */
5761       }
5762     }
5763   }
5764 
5765   /* call ha_init_key_cache() on all key caches to init them */
5766   process_key_caches(&ha_init_key_cache);
5767 
5768   /* Allow storage engine to give real error messages */
5769   if (ha_init_errors()) return 1;
5770 
5771   if (gtid_server_init()) {
5772     LogErr(ERROR_LEVEL, ER_CANT_INITIALIZE_GTID);
5773     unireg_abort(MYSQLD_ABORT_EXIT);
5774   }
5775 
5776   if (opt_log_slave_updates && replicate_same_server_id) {
5777     if (opt_bin_log && global_gtid_mode.get() != Gtid_mode::ON) {
5778       LogErr(ERROR_LEVEL, ER_RPL_INFINITY_DENIED);
5779       unireg_abort(MYSQLD_ABORT_EXIT);
5780     } else
5781       LogErr(WARNING_LEVEL, ER_RPL_INFINITY_IGNORED);
5782   }
5783 
5784   {
5785     /*
5786       We have to call a function in log_resource.cc, or its references
5787       won't be visible to plugins.
5788     */
5789 #ifndef DBUG_OFF
5790     int dummy =
5791 #endif
5792         Log_resource::dummy_function_to_ensure_we_are_linked_into_the_server();
5793     DBUG_ASSERT(dummy == 1);
5794   }
5795 
5796   /*
5797     We need to initialize the UDF globals early before reading the proc table
5798     and before the server component initialization to allow other components
5799     to register their UDFs at init time and de-register them at deinit time.
5800   */
5801   udf_init_globals();
5802 
5803   /*
5804     Set tc_log to point to TC_LOG_DUMMY early in order to allow plugin_init()
5805     to commit attachable transaction after reading from mysql.plugin table.
5806     If necessary tc_log will be adjusted to point to correct TC_LOG instance
5807     later.
5808   */
5809   tc_log = &tc_log_dummy;
5810 
5811   /* This limits ability to configure SSL library through config options */
5812   init_ssl();
5813 
5814   /*Load early plugins */
5815   if (plugin_register_early_plugins(&remaining_argc, remaining_argv,
5816                                     (is_help_or_validate_option())
5817                                         ? PLUGIN_INIT_SKIP_INITIALIZATION
5818                                         : 0)) {
5819     LogErr(ERROR_LEVEL, ER_CANT_INITIALIZE_EARLY_PLUGINS);
5820     unireg_abort(1);
5821   }
5822 
5823   /* Load builtin plugins, initialize MyISAM, CSV and InnoDB */
5824   if (plugin_register_builtin_and_init_core_se(&remaining_argc,
5825                                                remaining_argv)) {
5826     if (!opt_validate_config)
5827       LogErr(ERROR_LEVEL, ER_CANT_INITIALIZE_BUILTIN_PLUGINS);
5828     unireg_abort(1);
5829   }
5830 
5831   /*
5832     Needs to be done before dd::init() which runs DDL commands (for real)
5833     during instance initialization.
5834   */
5835   init_sql_command_flags();
5836 
5837   /*
5838     plugin_register_dynamic_and_init_all() needs DD initialized.
5839     Initialize DD to create data directory using current server.
5840   */
5841   if (opt_initialize) {
5842     if (!is_help_or_validate_option()) {
5843       if (dd::init(dd::enum_dd_init_type::DD_INITIALIZE)) {
5844         LogErr(ERROR_LEVEL, ER_DD_INIT_FAILED);
5845         unireg_abort(1);
5846       }
5847 
5848       if (dd::init(dd::enum_dd_init_type::DD_INITIALIZE_SYSTEM_VIEWS)) {
5849         LogErr(ERROR_LEVEL, ER_SYSTEM_VIEW_INIT_FAILED);
5850         unireg_abort(1);
5851       }
5852     }
5853   } else {
5854     /*
5855       Initialize DD in case of upgrade and normal normal server restart.
5856       It is detected if we are starting on old data directory or current
5857       data directory. If it is old data directory, DD tables are created.
5858       If server is starting on data directory with DD tables, DD is initialized.
5859     */
5860     if (!is_help_or_validate_option() &&
5861         dd::init(dd::enum_dd_init_type::DD_RESTART_OR_UPGRADE)) {
5862       LogErr(ERROR_LEVEL, ER_DD_INIT_FAILED);
5863 
5864       /* If clone recovery fails, we rollback the files to previous
5865       dataset and attempt to restart server. */
5866       int exit_code =
5867           clone_recovery_error ? MYSQLD_RESTART_EXIT : MYSQLD_ABORT_EXIT;
5868       unireg_abort(exit_code);
5869     }
5870   }
5871 
5872   /*
5873    During plugin initialization, a plugin may expect (depending on what the
5874    plugin actually does) to find a functional server, including:
5875    - mysql system tables
5876    - information schema tables
5877    - performance schema tables
5878    - data dictionary
5879    - components / services, including the registry service
5880    During the server installation, all these parts are not available yet, as
5881    they are created during the installation process with mysqld --initialize.
5882 
5883    As a result, plugins are not loaded during mysqld --initialize, so that
5884    the server install can proceed and complete before any plugin is loaded
5885    through any config file or pre-programmed command line.
5886   */
5887   int flags = 0;
5888 
5889   if (opt_noacl) flags |= PLUGIN_INIT_SKIP_PLUGIN_TABLE;
5890   if (is_help_or_validate_option())
5891     flags |= PLUGIN_INIT_SKIP_INITIALIZATION | PLUGIN_INIT_SKIP_PLUGIN_TABLE;
5892   if (opt_initialize) flags |= PLUGIN_INIT_SKIP_DYNAMIC_LOADING;
5893 
5894   /*
5895     In the case of upgrade, we need to delay initialization of plugins that
5896     depend on e.g. mysql tables that will be changed during upgrade.
5897   */
5898   if (!is_help_or_validate_option() && !opt_initialize &&
5899       !dd::upgrade::no_server_upgrade_required() &&
5900       opt_upgrade_mode != UPGRADE_MINIMAL)
5901     flags |= PLUGIN_INIT_DELAY_UNTIL_AFTER_UPGRADE;
5902 
5903   if (plugin_register_dynamic_and_init_all(&remaining_argc, remaining_argv,
5904                                            flags)) {
5905     // Delete all DD tables in case of error in initializing plugins.
5906     if (dd::upgrade_57::in_progress())
5907       (void)dd::init(dd::enum_dd_init_type::DD_DELETE);
5908 
5909     if (!opt_validate_config)
5910       LogErr(ERROR_LEVEL, ER_CANT_INITIALIZE_DYNAMIC_PLUGINS);
5911     unireg_abort(MYSQLD_ABORT_EXIT);
5912   }
5913   dynamic_plugins_are_initialized =
5914       true; /* Don't separate from init function */
5915 
5916   LEX_CSTRING plugin_name = {STRING_WITH_LEN("thread_pool")};
5917   if (Connection_handler_manager::thread_handling !=
5918           Connection_handler_manager::SCHEDULER_ONE_THREAD_PER_CONNECTION ||
5919       plugin_is_ready(plugin_name, MYSQL_DAEMON_PLUGIN)) {
5920     auto res_grp_mgr = resourcegroups::Resource_group_mgr::instance();
5921     res_grp_mgr->disable_resource_group();
5922     res_grp_mgr->set_unsupport_reason("Thread pool plugin enabled");
5923   }
5924 
5925 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
5926   /*
5927     A value of the variable dd_upgrade_flag is reset after
5928     dd::init(dd::enum_dd_init_type::DD_POPULATE_UPGRADE) returned.
5929     So make its copy to call init_pfs_tables() with right argument value later.
5930   */
5931   bool dd_upgrade_was_initiated = dd::upgrade_57::in_progress();
5932 #endif
5933 
5934   if (!is_help_or_validate_option() && dd::upgrade_57::in_progress()) {
5935     // Populate DD tables with meta data from 5.7
5936     if (dd::init(dd::enum_dd_init_type::DD_POPULATE_UPGRADE)) {
5937       LogErr(ERROR_LEVEL, ER_DD_POPULATING_TABLES_FAILED);
5938       unireg_abort(1);
5939     }
5940     // Run after_dd_upgrade hook
5941     if (RUN_HOOK(server_state, after_dd_upgrade_from_57, (nullptr)))
5942       unireg_abort(MYSQLD_ABORT_EXIT);
5943   }
5944 
5945   /*
5946     Store server and plugin IS tables metadata into new DD.
5947     This is done after all the plugins are registered.
5948   */
5949   if (!is_help_or_validate_option() && !opt_initialize &&
5950       !dd::upgrade_57::in_progress() &&
5951       dd::init(dd::enum_dd_init_type::DD_UPDATE_I_S_METADATA)) {
5952     LogErr(ERROR_LEVEL, ER_DD_UPDATING_PLUGIN_MD_FAILED);
5953     unireg_abort(MYSQLD_ABORT_EXIT);
5954   }
5955 
5956 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
5957   if (!is_help_or_validate_option()) {
5958     /*
5959       Initialize the cost model, but delete it after the pfs is initialized.
5960       Cost model is needed while dropping and creating pfs tables to
5961       update metadata of referencing views (if there are any).
5962     */
5963     init_optimizer_cost_module(true);
5964 
5965     bool st;
5966     if (opt_initialize || dd_upgrade_was_initiated)
5967       st = dd::performance_schema::init_pfs_tables(
5968           dd::enum_dd_init_type::DD_INITIALIZE);
5969     else
5970       st = dd::performance_schema::init_pfs_tables(
5971           dd::enum_dd_init_type::DD_RESTART_OR_UPGRADE);
5972 
5973     /* Now that the pfs is initialized, delete the cost model. */
5974     delete_optimizer_cost_module();
5975 
5976     if (st) {
5977       LogErr(ERROR_LEVEL, ER_PERFSCHEMA_TABLES_INIT_FAILED);
5978       unireg_abort(1);
5979     }
5980   }
5981 #endif
5982 
5983   bool recreate_non_dd_based_system_view = dd::upgrade::I_S_upgrade_required();
5984   if (!is_help_or_validate_option() && !opt_initialize &&
5985       !dd::upgrade::no_server_upgrade_required()) {
5986     if (opt_upgrade_mode == UPGRADE_MINIMAL)
5987       LogErr(WARNING_LEVEL, ER_SERVER_UPGRADE_SKIP);
5988     else {
5989       init_optimizer_cost_module(true);
5990       if (bootstrap::run_bootstrap_thread(nullptr, nullptr,
5991                                           &dd::upgrade::upgrade_system_schemas,
5992                                           SYSTEM_THREAD_SERVER_UPGRADE)) {
5993         LogErr(ERROR_LEVEL, ER_SERVER_UPGRADE_FAILED);
5994         unireg_abort(MYSQLD_ABORT_EXIT);
5995       }
5996       delete_optimizer_cost_module();
5997       recreate_non_dd_based_system_view = true;
5998 
5999       /*
6000         When upgrade is finished, we need to initialize the plugins that
6001         had their initialization delayed due to dependencies on the
6002         environment.
6003 
6004         TODO: Provide a better long term solution by re-ordering startup
6005               sequence and rewriting the way we create and upgrade server
6006               resources needed by plugins.
6007       */
6008       if (dd::upgrade::plugin_initialize_delayed_after_upgrade()) {
6009         unireg_abort(MYSQLD_ABORT_EXIT);
6010       }
6011     }
6012   }
6013 
6014   /*
6015     Re-create non DD based system views after a) if we upgraded system
6016     schemas b) I_S system view version is changed and server system views
6017     were recreated. c) If the database was upgraded. We do not update this
6018     in upgrade-minimal mode.
6019    */
6020   if (!is_help_or_validate_option() && !opt_initialize &&
6021       opt_upgrade_mode != UPGRADE_MINIMAL &&
6022       recreate_non_dd_based_system_view) {
6023     if (dd::init(
6024             dd::enum_dd_init_type::DD_INITIALIZE_NON_DD_BASED_SYSTEM_VIEWS)) {
6025       LogErr(ERROR_LEVEL, ER_SYSTEM_VIEW_INIT_FAILED);
6026       unireg_abort(MYSQLD_ABORT_EXIT);
6027     }
6028   }
6029 
6030   auto res_grp_mgr = resourcegroups::Resource_group_mgr::instance();
6031   // Initialize the Resource group subsystem.
6032   if (!is_help_or_validate_option() && !opt_initialize) {
6033     if (res_grp_mgr->post_init()) {
6034       LogErr(ERROR_LEVEL, ER_RESOURCE_GROUP_POST_INIT_FAILED);
6035       unireg_abort(MYSQLD_ABORT_EXIT);
6036     }
6037   }
6038 
6039   Session_tracker session_track_system_variables_check;
6040   LEX_STRING var_list;
6041   char *tmp_str;
6042   size_t len = strlen(global_system_variables.track_sysvars_ptr);
6043   tmp_str = (char *)my_malloc(PSI_NOT_INSTRUMENTED, len * sizeof(char) + 2,
6044                               MYF(MY_WME));
6045   strcpy(tmp_str, global_system_variables.track_sysvars_ptr);
6046   var_list.length = len;
6047   var_list.str = tmp_str;
6048   if (session_track_system_variables_check.server_boot_verify(
6049           system_charset_info, var_list)) {
6050     LogErr(ERROR_LEVEL, ER_TRACK_VARIABLES_BOGUS);
6051     if (tmp_str) my_free(tmp_str);
6052     unireg_abort(MYSQLD_ABORT_EXIT);
6053   }
6054   if (tmp_str) my_free(tmp_str);
6055 
6056   // Validate the configuration if --validate-config was specified.
6057   if (opt_validate_config && (remaining_argc > 1)) {
6058     bool saved_getopt_skip_unknown = my_getopt_skip_unknown;
6059     struct my_option no_opts[] = {{nullptr, 0, nullptr, nullptr, nullptr,
6060                                    nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0,
6061                                    nullptr, 0, nullptr}};
6062 
6063     my_getopt_skip_unknown = false;
6064 
6065     if (handle_options(&remaining_argc, &remaining_argv, no_opts,
6066                        mysqld_get_one_option))
6067       unireg_abort(MYSQLD_ABORT_EXIT);
6068     my_getopt_skip_unknown = saved_getopt_skip_unknown;
6069   }
6070 
6071   if (is_help_or_validate_option()) unireg_abort(MYSQLD_SUCCESS_EXIT);
6072 
6073   /* if the errmsg.sys is not loaded, terminate to maintain behaviour */
6074   if (!my_default_lc_messages->errmsgs->is_loaded()) {
6075     LogErr(ERROR_LEVEL, ER_CANT_READ_ERRMSGS);
6076     unireg_abort(MYSQLD_ABORT_EXIT);
6077   }
6078 
6079   /* We have to initialize the storage engines before CSV logging */
6080   if (ha_init()) {
6081     LogErr(ERROR_LEVEL, ER_CANT_INIT_DBS);
6082     unireg_abort(MYSQLD_ABORT_EXIT);
6083   }
6084 
6085   /* Initialize ndbinfo tables in DD */
6086   if (dd::ndbinfo::init_schema_and_tables(opt_upgrade_mode)) {
6087     LogErr(ERROR_LEVEL, ER_NDBINFO_UPGRADING_SCHEMA_FAIL);
6088     unireg_abort(1);
6089   }
6090 
6091   if (opt_initialize) log_output_options = LOG_FILE;
6092 
6093   /*
6094     Issue a warning if there were specified additional options to the
6095     log-output along with NONE. Probably this wasn't what user wanted.
6096   */
6097   if ((log_output_options & LOG_NONE) && (log_output_options & ~LOG_NONE))
6098     LogErr(WARNING_LEVEL, ER_LOG_OUTPUT_CONTRADICTORY);
6099 
6100   if (log_output_options & LOG_TABLE) {
6101     /* Fall back to log files if the csv engine is not loaded. */
6102     LEX_CSTRING csv_name = {STRING_WITH_LEN("csv")};
6103     if (!plugin_is_ready(csv_name, MYSQL_STORAGE_ENGINE_PLUGIN)) {
6104       LogErr(ERROR_LEVEL, ER_NO_CSV_NO_LOG_TABLES);
6105       log_output_options = (log_output_options & ~LOG_TABLE) | LOG_FILE;
6106     }
6107   }
6108 
6109   query_logger.set_handlers(log_output_options);
6110 
6111   // Open slow log file if enabled.
6112   query_logger.set_log_file(QUERY_LOG_SLOW);
6113   if (opt_slow_log && query_logger.reopen_log_file(QUERY_LOG_SLOW))
6114     opt_slow_log = false;
6115 
6116   // Open general log file if enabled.
6117   query_logger.set_log_file(QUERY_LOG_GENERAL);
6118   if (opt_general_log && query_logger.reopen_log_file(QUERY_LOG_GENERAL))
6119     opt_general_log = false;
6120 
6121   /*
6122     Set the default storage engines
6123   */
6124   if (initialize_storage_engine(default_storage_engine, "",
6125                                 &global_system_variables.table_plugin))
6126     unireg_abort(MYSQLD_ABORT_EXIT);
6127   if (initialize_storage_engine(default_tmp_storage_engine, " temp",
6128                                 &global_system_variables.temp_table_plugin))
6129     unireg_abort(MYSQLD_ABORT_EXIT);
6130 
6131   if (!opt_initialize && !opt_noacl) {
6132     set_externally_disabled_storage_engine_names(opt_disabled_storage_engines);
6133 
6134     // Log warning if default_storage_engine is a disabled storage engine.
6135     handlerton *default_se_handle =
6136         plugin_data<handlerton *>(global_system_variables.table_plugin);
6137     if (ha_is_storage_engine_disabled(default_se_handle))
6138       LogErr(WARNING_LEVEL, ER_DISABLED_STORAGE_ENGINE_AS_DEFAULT,
6139              "default_storage_engine", default_storage_engine);
6140 
6141     // Log warning if default_tmp_storage_engine is a disabled storage engine.
6142     handlerton *default_tmp_se_handle =
6143         plugin_data<handlerton *>(global_system_variables.temp_table_plugin);
6144     if (ha_is_storage_engine_disabled(default_tmp_se_handle))
6145       LogErr(WARNING_LEVEL, ER_DISABLED_STORAGE_ENGINE_AS_DEFAULT,
6146              "default_tmp_storage_engine", default_tmp_storage_engine);
6147   }
6148 
6149   if (total_ha_2pc > 1 || (1 == total_ha_2pc && opt_bin_log)) {
6150     if (opt_bin_log)
6151       tc_log = &mysql_bin_log;
6152     else
6153       tc_log = &tc_log_mmap;
6154   }
6155 
6156   if (Recovered_xa_transactions::init()) {
6157     LogErr(ERROR_LEVEL, ER_OOM);
6158     unireg_abort(MYSQLD_ABORT_EXIT);
6159   }
6160 
6161   if (tc_log->open(opt_bin_log ? opt_bin_logname : opt_tc_log_file)) {
6162     LogErr(ERROR_LEVEL, ER_CANT_INIT_TC_LOG);
6163     unireg_abort(MYSQLD_ABORT_EXIT);
6164   }
6165   (void)RUN_HOOK(server_state, before_recovery, (nullptr));
6166   if (ha_recover(nullptr)) {
6167     unireg_abort(MYSQLD_ABORT_EXIT);
6168   }
6169 
6170   if (dd::reset_tables_and_tablespaces()) {
6171     unireg_abort(MYSQLD_ABORT_EXIT);
6172   }
6173   ha_post_recover();
6174 
6175   /*
6176     Add prepared XA transactions into the cache of XA transactions and acquire
6177     mdl lock for every table involved in any of these prepared XA transactions.
6178     This step moved away from the function ha_recover() in order to avoid
6179     possible suspending on acquiring EXLUSIVE mdl lock on tables inside the
6180     function dd::reset_tables_and_tablespaces() when table cache being reset.
6181   */
6182   if (Recovered_xa_transactions::instance()
6183           .recover_prepared_xa_transactions()) {
6184     unireg_abort(MYSQLD_ABORT_EXIT);
6185   }
6186 
6187   if (global_gtid_mode.get() == Gtid_mode::ON &&
6188       _gtid_consistency_mode != GTID_CONSISTENCY_MODE_ON) {
6189     LogErr(ERROR_LEVEL, ER_RPL_GTID_MODE_REQUIRES_ENFORCE_GTID_CONSISTENCY_ON);
6190     unireg_abort(MYSQLD_ABORT_EXIT);
6191   }
6192 
6193   /*
6194     Each server should have one UUID. We will create it automatically, if it
6195     does not exist. It should be initialized before opening binlog file. Because
6196     server's uuid will be stored into the new binlog file.
6197   */
6198   if (init_server_auto_options()) {
6199     LogErr(ERROR_LEVEL, ER_CANT_CREATE_UUID);
6200     unireg_abort(MYSQLD_ABORT_EXIT);
6201   }
6202 
6203   if (rpl_encryption.initialize()) {
6204     LogErr(ERROR_LEVEL, ER_SERVER_RPL_ENCRYPTION_UNABLE_TO_INITIALIZE);
6205     unireg_abort(MYSQLD_ABORT_EXIT);
6206   }
6207 
6208   if (opt_bin_log) {
6209     /*
6210       Configures what object is used by the current log to store processed
6211       gtid(s). This is necessary in the MYSQL_BIN_LOG::MYSQL_BIN_LOG to
6212       corretly compute the set of previous gtids.
6213     */
6214     DBUG_ASSERT(!mysql_bin_log.is_relay_log);
6215     mysql_mutex_t *log_lock = mysql_bin_log.get_log_lock();
6216     mysql_mutex_lock(log_lock);
6217 
6218     if (mysql_bin_log.open_binlog(opt_bin_logname, nullptr, max_binlog_size,
6219                                   false, true /*need_lock_index=true*/,
6220                                   true /*need_sid_lock=true*/, nullptr)) {
6221       mysql_mutex_unlock(log_lock);
6222       unireg_abort(MYSQLD_ABORT_EXIT);
6223     }
6224     mysql_mutex_unlock(log_lock);
6225   }
6226 
6227   /*
6228     When we pass non-zero values for both expire_logs_days and
6229     binlog_expire_logs_seconds at the server start-up, the value of
6230     expire_logs_days will be ignored and only binlog_expire_logs_seconds
6231     will be used.
6232   */
6233   if (binlog_expire_logs_seconds_supplied && expire_logs_days_supplied) {
6234     if (binlog_expire_logs_seconds != 0 && expire_logs_days != 0) {
6235       LogErr(WARNING_LEVEL, ER_EXPIRE_LOGS_DAYS_IGNORED);
6236       expire_logs_days = 0;
6237     }
6238   } else if (expire_logs_days_supplied)
6239     binlog_expire_logs_seconds = 0;
6240   DBUG_ASSERT(expire_logs_days == 0 || binlog_expire_logs_seconds == 0);
6241 
6242   if (opt_bin_log) {
6243     if (expire_logs_days > 0 || binlog_expire_logs_seconds > 0) {
6244       time_t purge_time = my_time(0) - binlog_expire_logs_seconds -
6245                           expire_logs_days * 24 * 60 * 60;
6246       DBUG_EXECUTE_IF("expire_logs_always_at_start",
6247                       { purge_time = my_time(0); });
6248       mysql_bin_log.purge_logs_before_date(purge_time, true);
6249     }
6250   } else {
6251     if (binlog_expire_logs_seconds_supplied)
6252       LogErr(WARNING_LEVEL, ER_NEED_LOG_BIN, "--binlog-expire-logs-seconds");
6253     if (expire_logs_days_supplied)
6254       LogErr(WARNING_LEVEL, ER_NEED_LOG_BIN, "--expire_logs_days");
6255   }
6256 
6257   if (opt_myisam_log) (void)mi_log(1);
6258 
6259 #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
6260   if (locked_in_memory && !getuid()) {
6261     if (setreuid((uid_t)-1, 0) == -1) {  // this should never happen
6262       LogErr(ERROR_LEVEL, ER_FAIL_SETREUID, strerror(errno));
6263       unireg_abort(MYSQLD_ABORT_EXIT);
6264     }
6265     if (mlockall(MCL_CURRENT)) {
6266       LogErr(WARNING_LEVEL, ER_FAILED_TO_LOCK_MEM,
6267              errno); /* purecov: inspected */
6268       locked_in_memory = false;
6269     }
6270 #ifndef _WIN32
6271     if (!user_info.IsVoid()) set_user(mysqld_user, user_info);
6272 #endif
6273   } else
6274 #endif
6275     locked_in_memory = false;
6276 
6277   /* Initialize the optimizer cost module */
6278   init_optimizer_cost_module(true);
6279   ft_init_stopwords();
6280 
6281   init_max_user_conn();
6282 
6283   return 0;
6284 }
6285 
6286 #ifdef _WIN32
6287 
handle_shutdown_and_restart(void * arg)6288 extern "C" void *handle_shutdown_and_restart(void *arg) {
6289   MSG msg;
6290   HANDLE event_handles[2];
6291   event_handles[0] = hEventShutdown;
6292   event_handles[1] = hEventRestart;
6293 
6294   my_thread_init();
6295   /* This call should create the message queue for this thread. */
6296   PeekMessage(&msg, NULL, 1, 65534, PM_NOREMOVE);
6297   DWORD ret_code = WaitForMultipleObjects(
6298       2, static_cast<HANDLE *>(event_handles), FALSE, INFINITE);
6299 
6300   if (ret_code == WAIT_OBJECT_0 || ret_code == WAIT_OBJECT_0 + 1) {
6301     if (ret_code == WAIT_OBJECT_0)
6302       LogErr(SYSTEM_LEVEL, ER_NORMAL_SERVER_SHUTDOWN, my_progname);
6303     else
6304       signal_hand_thr_exit_code = MYSQLD_RESTART_EXIT;
6305 
6306     set_connection_events_loop_aborted(true);
6307     close_connections();
6308     my_thread_end();
6309     my_thread_exit(0);
6310   }
6311   return 0;
6312 }
6313 
create_shutdown_and_restart_thread()6314 static void create_shutdown_and_restart_thread() {
6315   DBUG_TRACE;
6316 
6317   const char *errmsg;
6318   my_thread_attr_t thr_attr;
6319   SECURITY_ATTRIBUTES *shutdown_sec_attr;
6320 
6321   my_security_attr_create(&shutdown_sec_attr, &errmsg, GENERIC_ALL,
6322                           SYNCHRONIZE | EVENT_MODIFY_STATE);
6323 
6324   if (!opt_no_monitor) {
6325     snprintf(shutdown_event_name, sizeof(shutdown_event_name),
6326              "mysqld%s_shutdown", get_monitor_pid());
6327   }
6328 
6329   hEventShutdown =
6330       CreateEvent(shutdown_sec_attr, FALSE, FALSE, shutdown_event_name);
6331   hEventRestart = CreateEvent(0, FALSE, FALSE, restart_event_name);
6332 
6333   my_thread_attr_init(&thr_attr);
6334 
6335   if (my_thread_create(&shutdown_restart_thr_handle, &thr_attr,
6336                        handle_shutdown_and_restart, 0))
6337     LogErr(WARNING_LEVEL, ER_CANT_CREATE_SHUTDOWN_THREAD, errno);
6338 
6339   my_security_attr_free(shutdown_sec_attr);
6340   my_thread_attr_destroy(&thr_attr);
6341 }
6342 #endif /* _WIN32 */
6343 
6344 #ifndef DBUG_OFF
6345 /*
6346   Debugging helper function to keep the locale database
6347   (see sql_locale.cc) and max_month_name_length and
6348   max_day_name_length variable values in consistent state.
6349 */
test_lc_time_sz()6350 static void test_lc_time_sz() {
6351   DBUG_TRACE;
6352   for (MY_LOCALE **loc = my_locales; *loc; loc++) {
6353     size_t max_month_len = 0;
6354     size_t max_day_len = 0;
6355     for (const char **month = (*loc)->month_names->type_names; *month;
6356          month++) {
6357       max_month_len = std::max(
6358           max_month_len, my_numchars_mb(&my_charset_utf8_general_ci, *month,
6359                                         *month + strlen(*month)));
6360     }
6361     for (const char **day = (*loc)->day_names->type_names; *day; day++) {
6362       max_day_len =
6363           std::max(max_day_len, my_numchars_mb(&my_charset_utf8_general_ci,
6364                                                *day, *day + strlen(*day)));
6365     }
6366     if ((*loc)->max_month_name_length != max_month_len ||
6367         (*loc)->max_day_name_length != max_day_len) {
6368       DBUG_PRINT("Wrong max day name(or month name) length for locale:",
6369                  ("%s", (*loc)->name));
6370       DBUG_ASSERT(0);
6371     }
6372   }
6373 }
6374 #endif  // DBUG_OFF
6375 
6376 /*
6377   @brief : Set opt_super_readonly to user supplied value before
6378            enabling communication channels to accept user connections
6379 */
6380 
set_super_read_only_post_init()6381 static void set_super_read_only_post_init() {
6382   opt_super_readonly = super_read_only;
6383 }
6384 
calculate_mysql_home_from_my_progname()6385 static void calculate_mysql_home_from_my_progname() {
6386   const std::string runtime_output_directory_addon{
6387       "/runtime_output_directory/"};
6388 #if defined(_WIN32) || defined(APPLE_XCODE)
6389   /* Allow Win32 users to move MySQL anywhere */
6390   char prg_dev[LIBLEN];
6391   my_path(prg_dev, my_progname, nullptr);
6392 
6393   // On windows or Xcode the basedir will always be one level up from where
6394   // the executable is located. E.g. <basedir>/bin/mysqld.exe in a
6395   // package, or <basedir>/runtime_output_directory/<buildconfig>/mysqld.exe
6396   // for a sandbox build.
6397   strcat(prg_dev, "/../");  // Remove containing directory to get base dir
6398   cleanup_dirname(mysql_home, prg_dev);
6399 
6400   // New layout: <cmake_binary_dir>/runtime_output_directory/<buildconfig>/
6401   char cmake_binary_dir[FN_REFLEN];
6402   size_t dlen = 0;
6403   dirname_part(cmake_binary_dir, mysql_home, &dlen);
6404   if (dlen > runtime_output_directory_addon.length() &&
6405       (!strcmp(
6406            cmake_binary_dir + (dlen - runtime_output_directory_addon.length()),
6407            runtime_output_directory_addon.c_str()) ||
6408        !strcmp(
6409            cmake_binary_dir + (dlen - runtime_output_directory_addon.length()),
6410            "\\runtime_output_directory\\"))) {
6411     mysql_home[strlen(mysql_home) - 1] = '\0';  // remove trailing
6412     dirname_part(cmake_binary_dir, mysql_home, &dlen);
6413     strmake(mysql_home, cmake_binary_dir, sizeof(mysql_home) - 1);
6414   }
6415   // The sql_print_information below outputs nothing ??
6416   // fprintf(stderr, "mysql_home %s\n", mysql_home);
6417   // fflush(stderr);
6418 #else
6419   const char *tmpenv = getenv("MY_BASEDIR_VERSION");
6420   if (tmpenv != nullptr) {
6421     strmake(mysql_home, tmpenv, sizeof(mysql_home) - 1);
6422   } else {
6423     char progdir[FN_REFLEN];
6424     size_t dlen = 0;
6425     dirname_part(progdir, my_progname, &dlen);
6426     if (dlen > runtime_output_directory_addon.length() &&
6427         !strcmp(progdir + (dlen - runtime_output_directory_addon.length()),
6428                 runtime_output_directory_addon.c_str())) {
6429       char cmake_binary_dir[FN_REFLEN];
6430       progdir[strlen(progdir) - 1] = '\0';  // remove trailing "/"
6431       dirname_part(cmake_binary_dir, progdir, &dlen);
6432       strmake(mysql_home, cmake_binary_dir, sizeof(mysql_home) - 1);
6433     } else {
6434       strcat(progdir, "/../");
6435       cleanup_dirname(mysql_home, progdir);
6436     }
6437   }
6438 #endif
6439   mysql_home_ptr = mysql_home;
6440 }
6441 
6442 #ifdef _WIN32
win_main(int argc,char ** argv)6443 int win_main(int argc, char **argv)
6444 #else
6445 int mysqld_main(int argc, char **argv)
6446 #endif
6447 {
6448   // Substitute the full path to the executable in argv[0]
6449   substitute_progpath(argv);
6450   sysd::notify_connect();
6451   sysd::notify("STATUS=Server startup in progress\n");
6452 
6453   /*
6454     Perform basic thread library and malloc initialization,
6455     to be able to read defaults files and parse options.
6456   */
6457   my_progname = argv[0];
6458   calculate_mysql_home_from_my_progname();
6459 
6460 #ifndef _WIN32
6461 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
6462   pre_initialize_performance_schema();
6463 #endif /*WITH_PERFSCHEMA_STORAGE_ENGINE */
6464   // For windows, my_init() is called from the win specific mysqld_main
6465   if (my_init())  // init my_sys library & pthreads
6466   {
6467     LogErr(ERROR_LEVEL, ER_MYINIT_FAILED);
6468     flush_error_log_messages();
6469     return 1;
6470   }
6471 #endif /* _WIN32 */
6472 
6473   orig_argc = argc;
6474   orig_argv = argv;
6475   my_getopt_use_args_separator = true;
6476   my_defaults_read_login_file = false;
6477   if (load_defaults(MYSQL_CONFIG_NAME, load_default_groups, &argc, &argv,
6478                     &argv_alloc)) {
6479     flush_error_log_messages();
6480     return 1;
6481   }
6482 
6483   /* Set data dir directory paths */
6484   strmake(mysql_real_data_home, get_relative_path(MYSQL_DATADIR),
6485           sizeof(mysql_real_data_home) - 1);
6486 
6487   /*
6488    Initialize variables cache for persisted variables, load persisted
6489    config file and append read only persisted variables to command line
6490    options if present.
6491   */
6492   if (persisted_variables_cache.init(&argc, &argv) ||
6493       persisted_variables_cache.load_persist_file() ||
6494       persisted_variables_cache.append_read_only_variables(&argc, &argv)) {
6495     flush_error_log_messages();
6496     return 1;
6497   }
6498   my_getopt_use_args_separator = false;
6499   remaining_argc = argc;
6500   remaining_argv = argv;
6501 
6502   init_variable_default_paths();
6503 
6504   /* Must be initialized early for comparison of options name */
6505   system_charset_info = &my_charset_utf8_general_ci;
6506 
6507   /* Write mysys error messages to the error log. */
6508   local_message_hook = error_log_print;
6509 
6510   int heo_error;
6511 
6512 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
6513   /*
6514     Initialize the array of performance schema instrument configurations.
6515   */
6516   init_pfs_instrument_array();
6517 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
6518 
6519   heo_error = handle_early_options();
6520 
6521   init_sql_statement_names();
6522   sys_var_init();
6523   ulong requested_open_files = 0;
6524 
6525   //  Init error log subsystem. This does not actually open the log yet.
6526   if (init_error_log()) unireg_abort(MYSQLD_ABORT_EXIT);
6527   if (!opt_validate_config) adjust_related_options(&requested_open_files);
6528 
6529 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
6530   if (heo_error == 0) {
6531     if (!is_help_or_validate_option() && !opt_initialize) {
6532       int pfs_rc;
6533       /* Add sizing hints from the server sizing parameters. */
6534       pfs_param.m_hints.m_table_definition_cache = table_def_size;
6535       pfs_param.m_hints.m_table_open_cache = table_cache_size;
6536       pfs_param.m_hints.m_max_connections = max_connections;
6537       pfs_param.m_hints.m_open_files_limit = requested_open_files;
6538       pfs_param.m_hints.m_max_prepared_stmt_count = max_prepared_stmt_count;
6539 
6540       pfs_rc = initialize_performance_schema(
6541           &pfs_param, &psi_thread_hook, &psi_mutex_hook, &psi_rwlock_hook,
6542           &psi_cond_hook, &psi_file_hook, &psi_socket_hook, &psi_table_hook,
6543           &psi_mdl_hook, &psi_idle_hook, &psi_stage_hook, &psi_statement_hook,
6544           &psi_transaction_hook, &psi_memory_hook, &psi_error_hook,
6545           &psi_data_lock_hook, &psi_system_hook, &psi_tls_channel_hook);
6546       if ((pfs_rc != 0) && pfs_param.m_enabled) {
6547         pfs_param.m_enabled = false;
6548         LogErr(WARNING_LEVEL, ER_PERFSCHEMA_INIT_FAILED);
6549       }
6550     }
6551   }
6552 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
6553 
6554 #ifdef WITH_LOCK_ORDER
6555   if (heo_error == 0) {
6556     if (lo_param.m_enabled && !opt_help && !opt_initialize) {
6557       int lo_rc;
6558       lo_rc = LO_init(&lo_param, &psi_thread_hook, &psi_mutex_hook,
6559                       &psi_rwlock_hook, &psi_cond_hook, &psi_file_hook,
6560                       &psi_socket_hook, &psi_table_hook, &psi_mdl_hook,
6561                       &psi_idle_hook, &psi_stage_hook, &psi_statement_hook,
6562                       &psi_transaction_hook, &psi_memory_hook);
6563       if (lo_rc != 0) {
6564         LogErr(WARNING_LEVEL, ER_LOCK_ORDER_INIT_FAILED);
6565       }
6566     }
6567   }
6568 #endif /* WITH_LOCK_ORDER */
6569 
6570   /*
6571     Other provider of the instrumentation interface should
6572     initialize PSI_hook here:
6573     - HAVE_PSI_INTERFACE is for the instrumentation interface
6574     - WITH_PERFSCHEMA_STORAGE_ENGINE is for one implementation
6575       of the interface,
6576     but there could be alternate implementations, which is why
6577     these two defines are kept separate.
6578   */
6579 
6580 #ifdef HAVE_PSI_INTERFACE
6581   /*
6582     Obtain the current performance schema instrumentation interface,
6583     if available.
6584   */
6585 
6586   void *service;
6587 
6588   if (psi_thread_hook != nullptr) {
6589     service = psi_thread_hook->get_interface(PSI_CURRENT_THREAD_VERSION);
6590     if (service != nullptr) {
6591       set_psi_thread_service(service);
6592     }
6593   }
6594 
6595   if (psi_mutex_hook != nullptr) {
6596     service = psi_mutex_hook->get_interface(PSI_CURRENT_MUTEX_VERSION);
6597     if (service != nullptr) {
6598       set_psi_mutex_service(service);
6599     }
6600   }
6601 
6602   if (psi_rwlock_hook != nullptr) {
6603     service = psi_rwlock_hook->get_interface(PSI_CURRENT_RWLOCK_VERSION);
6604     if (service != nullptr) {
6605       set_psi_rwlock_service(service);
6606     }
6607   }
6608 
6609   if (psi_cond_hook != nullptr) {
6610     service = psi_cond_hook->get_interface(PSI_CURRENT_COND_VERSION);
6611     if (service != nullptr) {
6612       set_psi_cond_service(service);
6613     }
6614   }
6615 
6616   if (psi_file_hook != nullptr) {
6617     service = psi_file_hook->get_interface(PSI_CURRENT_FILE_VERSION);
6618     if (service != nullptr) {
6619       set_psi_file_service(service);
6620     }
6621   }
6622 
6623   if (psi_socket_hook != nullptr) {
6624     service = psi_socket_hook->get_interface(PSI_CURRENT_SOCKET_VERSION);
6625     if (service != nullptr) {
6626       set_psi_socket_service(service);
6627     }
6628   }
6629 
6630   if (psi_table_hook != nullptr) {
6631     service = psi_table_hook->get_interface(PSI_CURRENT_TABLE_VERSION);
6632     if (service != nullptr) {
6633       set_psi_table_service(service);
6634     }
6635   }
6636 
6637   if (psi_mdl_hook != nullptr) {
6638     service = psi_mdl_hook->get_interface(PSI_CURRENT_MDL_VERSION);
6639     if (service != nullptr) {
6640       set_psi_mdl_service(service);
6641     }
6642   }
6643 
6644   if (psi_idle_hook != nullptr) {
6645     service = psi_idle_hook->get_interface(PSI_CURRENT_IDLE_VERSION);
6646     if (service != nullptr) {
6647       set_psi_idle_service(service);
6648     }
6649   }
6650 
6651   if (psi_stage_hook != nullptr) {
6652     service = psi_stage_hook->get_interface(PSI_CURRENT_STAGE_VERSION);
6653     if (service != nullptr) {
6654       set_psi_stage_service(service);
6655     }
6656   }
6657 
6658   if (psi_statement_hook != nullptr) {
6659     service = psi_statement_hook->get_interface(PSI_CURRENT_STATEMENT_VERSION);
6660     if (service != nullptr) {
6661       set_psi_statement_service(service);
6662     }
6663   }
6664 
6665   if (psi_transaction_hook != nullptr) {
6666     service =
6667         psi_transaction_hook->get_interface(PSI_CURRENT_TRANSACTION_VERSION);
6668     if (service != nullptr) {
6669       set_psi_transaction_service(service);
6670     }
6671   }
6672 
6673   if (psi_memory_hook != nullptr) {
6674     service = psi_memory_hook->get_interface(PSI_CURRENT_MEMORY_VERSION);
6675     if (service != nullptr) {
6676       set_psi_memory_service(service);
6677     }
6678   }
6679 
6680   if (psi_error_hook != nullptr) {
6681     service = psi_error_hook->get_interface(PSI_CURRENT_ERROR_VERSION);
6682     if (service != nullptr) {
6683       set_psi_error_service(service);
6684     }
6685   }
6686 
6687   if (psi_data_lock_hook != nullptr) {
6688     service = psi_data_lock_hook->get_interface(PSI_CURRENT_DATA_LOCK_VERSION);
6689     if (service != nullptr) {
6690       set_psi_data_lock_service(service);
6691     }
6692   }
6693 
6694   if (psi_system_hook != nullptr) {
6695     service = psi_system_hook->get_interface(PSI_CURRENT_SYSTEM_VERSION);
6696     if (service != nullptr) {
6697       set_psi_system_service(service);
6698     }
6699   }
6700 
6701   if (psi_tls_channel_hook != nullptr) {
6702     service =
6703         psi_tls_channel_hook->get_interface(PSI_CURRENT_TLS_CHANNEL_VERSION);
6704     if (service != nullptr) {
6705       set_psi_tls_channel_service(service);
6706     }
6707   }
6708 
6709   /*
6710     Now that we have parsed the command line arguments, and have initialized
6711     the performance schema itself, the next step is to register all the
6712     server instruments.
6713   */
6714   init_server_psi_keys();
6715 
6716   /*
6717     Now that some instrumentation is in place,
6718     recreate objects which were initialised early,
6719     so that they are instrumented as well.
6720   */
6721   my_thread_global_reinit();
6722 #endif /* HAVE_PSI_INTERFACE */
6723 
6724   /*
6725     Initialize Components core subsystem early on, once we have PSI, which it
6726     uses. This part doesn't use any more MySQL-specific functionalities but
6727     error logging and PFS.
6728   */
6729   if (component_infrastructure_init()) unireg_abort(MYSQLD_ABORT_EXIT);
6730 
6731     /*
6732       Initialize Performance Schema component services.
6733     */
6734 #ifdef HAVE_PSI_THREAD_INTERFACE
6735   if (!is_help_or_validate_option() && !opt_initialize) {
6736     register_pfs_notification_service();
6737     register_pfs_resource_group_service();
6738   }
6739 #endif
6740 
6741   // Initialize the resource group subsystem.
6742   auto res_grp_mgr = resourcegroups::Resource_group_mgr::instance();
6743   if (!is_help_or_validate_option() && !opt_initialize) {
6744     if (res_grp_mgr->init()) {
6745       LogErr(ERROR_LEVEL, ER_RESOURCE_GROUP_SUBSYSTEM_INIT_FAILED);
6746       unireg_abort(MYSQLD_ABORT_EXIT);
6747     }
6748   }
6749 
6750 #ifdef HAVE_PSI_THREAD_INTERFACE
6751   /* Instrument the main thread */
6752   PSI_thread *psi = PSI_THREAD_CALL(new_thread)(key_thread_main, nullptr, 0);
6753   PSI_THREAD_CALL(set_thread_os_id)(psi);
6754   PSI_THREAD_CALL(set_thread)(psi);
6755 #endif /* HAVE_PSI_THREAD_INTERFACE */
6756 
6757   /* Initialize audit interface globals. Audit plugins are inited later. */
6758   mysql_audit_initialize();
6759 
6760   Srv_session::module_init();
6761 
6762   /*
6763     Perform basic query log initialization. Should be called after
6764     MY_INIT, as it initializes mutexes.
6765   */
6766   query_logger.init();
6767 
6768   if (heo_error) {
6769     /*
6770       Parsing command line option failed,
6771       Since we don't have a workable remaining_argc/remaining_argv
6772       to continue the server initialization, this is as far as this
6773       code can go.
6774       This is the best effort to log meaningful messages:
6775       - messages will be printed to stderr, which is not redirected yet,
6776       - messages will be printed in the NT event log, for windows.
6777     */
6778     flush_error_log_messages();
6779     /*
6780       Not enough initializations for unireg_abort()
6781       Using exit() for windows.
6782     */
6783     exit(MYSQLD_ABORT_EXIT);
6784   }
6785 
6786   if (init_common_variables()) {
6787     setup_error_log();
6788     unireg_abort(MYSQLD_ABORT_EXIT);  // Will do exit
6789   }
6790 
6791   my_init_signals();
6792 
6793   size_t guardize = 0;
6794 #ifndef _WIN32
6795   int retval = pthread_attr_getguardsize(&connection_attrib, &guardize);
6796   DBUG_ASSERT(retval == 0);
6797   if (retval != 0) guardize = my_thread_stack_size;
6798 #endif
6799 
6800 #if defined(__ia64__) || defined(__ia64)
6801   /*
6802     Peculiar things with ia64 platforms - it seems we only have half the
6803     stack size in reality, so we have to double it here
6804   */
6805   guardize = my_thread_stack_size;
6806 #endif
6807 
6808   if (0 != my_thread_attr_setstacksize(&connection_attrib,
6809                                        my_thread_stack_size + guardize)) {
6810     DBUG_ASSERT(false);
6811   }
6812 
6813   {
6814     /* Retrieve used stack size;  Needed for checking stack overflows */
6815     size_t stack_size = 0;
6816     my_thread_attr_getstacksize(&connection_attrib, &stack_size);
6817 
6818     /* We must check if stack_size = 0 as Solaris 2.9 can return 0 here */
6819     if (stack_size && stack_size < (my_thread_stack_size + guardize)) {
6820       LogErr(WARNING_LEVEL, ER_STACKSIZE_UNEXPECTED,
6821              my_thread_stack_size + guardize, (long)stack_size);
6822 #if defined(__ia64__) || defined(__ia64)
6823       my_thread_stack_size = stack_size / 2;
6824 #else
6825       my_thread_stack_size = static_cast<ulong>(stack_size - guardize);
6826 #endif
6827     }
6828   }
6829 
6830 #ifndef DBUG_OFF
6831   test_lc_time_sz();
6832   srand(static_cast<uint>(time(nullptr)));
6833 #endif
6834 
6835 #if !defined(_WIN32)
6836 
6837   if (opt_initialize && opt_daemonize) {
6838     fprintf(stderr, "Initialize and daemon options are incompatible.\n");
6839     unireg_abort(MYSQLD_ABORT_EXIT);
6840   }
6841 
6842   if (opt_daemonize && log_error_dest == disabled_my_option &&
6843       (isatty(STDOUT_FILENO) || isatty(STDERR_FILENO))) {
6844     // Just use the default in this case.
6845     log_error_dest = "";
6846   }
6847 
6848   if (opt_daemonize && !opt_validate_config) {
6849     if (chdir("/") < 0) {
6850       LogErr(ERROR_LEVEL, ER_CANNOT_CHANGE_TO_ROOT_DIR, strerror(errno));
6851       unireg_abort(MYSQLD_ABORT_EXIT);
6852     }
6853 
6854     if ((pipe_write_fd = mysqld::runtime::mysqld_daemonize()) < -1) {
6855       LogErr(ERROR_LEVEL, ER_FAILED_START_MYSQLD_DAEMON);
6856       unireg_abort(MYSQLD_ABORT_EXIT);
6857     }
6858 
6859     if (pipe_write_fd < 0) {
6860       // This is the launching process and the daemon appears to have
6861       // started ok (Need to call unireg_abort with success here to
6862       // clean up resources in the lauching process.
6863       unireg_abort(MYSQLD_SUCCESS_EXIT);
6864     }
6865 
6866     // Need to update the value of current_pid so that it reflects the
6867     // pid of the daemon (the previous value was set by unireg_init()
6868     // while still in the launcher process.
6869     current_pid = static_cast<ulong>(getpid());
6870   }
6871 #endif
6872 
6873 #ifndef _WIN32
6874   user_info = check_user(mysqld_user);
6875   if (!user_info.IsVoid()) {
6876 #if HAVE_CHOWN
6877     if (unlikely(opt_initialize)) {
6878       /* need to change the owner of the freshly created data directory */
6879       MY_STAT stat;
6880       char errbuf[MYSYS_STRERROR_SIZE];
6881       bool must_chown = true;
6882 
6883       /* fetch the directory's owner */
6884       if (!my_stat(mysql_real_data_home, &stat, MYF(0))) {
6885         LogErr(INFORMATION_LEVEL, ER_CANT_STAT_DATADIR, my_errno(),
6886                my_strerror(errbuf, sizeof(errbuf), my_errno()));
6887       }
6888       /* Don't change it if it's already the same as SElinux stops this */
6889       else if (stat.st_uid == user_info.pw_uid &&
6890                stat.st_gid == user_info.pw_gid)
6891         must_chown = false;
6892 
6893       if (must_chown &&
6894           chown(mysql_real_data_home, user_info.pw_uid, user_info.pw_gid)) {
6895         LogErr(ERROR_LEVEL, ER_CANT_CHOWN_DATADIR, mysqld_user);
6896         unireg_abort(1);
6897       }
6898     }
6899 #endif
6900 
6901 #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
6902     if (locked_in_memory)  // getuid() == 0 here
6903       set_effective_user(user_info);
6904     else
6905 #endif
6906       set_user(mysqld_user, user_info);
6907   }
6908 #endif  // !_WIN32
6909 
6910   /*
6911    initiate key migration if any one of the migration specific
6912    options are provided.
6913   */
6914   if (opt_keyring_migration_source || opt_keyring_migration_destination ||
6915       migrate_connect_options) {
6916     Migrate_keyring mk;
6917     my_getopt_skip_unknown = true;
6918     if (mk.init(remaining_argc, remaining_argv, opt_keyring_migration_source,
6919                 opt_keyring_migration_destination, opt_keyring_migration_user,
6920                 opt_keyring_migration_host, opt_keyring_migration_password,
6921                 opt_keyring_migration_socket, opt_keyring_migration_port)) {
6922       LogErr(ERROR_LEVEL, ER_KEYRING_MIGRATION_FAILED);
6923       log_error_dest = "stderr";
6924       flush_error_log_messages();
6925       unireg_abort(MYSQLD_ABORT_EXIT);
6926     }
6927 
6928     if (mk.execute()) {
6929       LogErr(ERROR_LEVEL, ER_KEYRING_MIGRATION_FAILED);
6930       log_error_dest = "stderr";
6931       flush_error_log_messages();
6932       unireg_abort(MYSQLD_ABORT_EXIT);
6933     }
6934 
6935     my_getopt_skip_unknown = false;
6936     LogErr(INFORMATION_LEVEL, ER_KEYRING_MIGRATION_SUCCESSFUL);
6937     log_error_dest = "stderr";
6938     flush_error_log_messages();
6939     unireg_abort(MYSQLD_SUCCESS_EXIT);
6940   }
6941 
6942   /*
6943    We have enough space for fiddling with the argv, continue
6944   */
6945   if (!(is_help_or_validate_option()) &&
6946       my_setwd(mysql_real_data_home, MYF(0))) {
6947     char errbuf[MYSYS_STRERROR_SIZE];
6948 
6949     LogErr(ERROR_LEVEL, ER_CANT_SET_DATA_DIR, mysql_real_data_home, errno,
6950            my_strerror(errbuf, sizeof(errbuf), errno));
6951     unireg_abort(MYSQLD_ABORT_EXIT); /* purecov: inspected */
6952   }
6953 
6954   /*
6955    The subsequent calls may take a long time : e.g. innodb log read.
6956    Thus set the long running service control manager timeout
6957   */
6958 #if defined(_WIN32)
6959   if (windows_service) {
6960     if (setup_service_status_cmd_processed_handle())
6961       unireg_abort(MYSQLD_ABORT_EXIT);
6962 
6963     char buf[32];
6964     snprintf(buf, sizeof(buf), "T %lu", slow_start_timeout);
6965     Service_status_msg msg(buf);
6966     send_service_status(msg);
6967   }
6968 #endif
6969 
6970   /* Determine default TCP port and unix socket name */
6971   set_ports();
6972 
6973   if (init_server_components()) unireg_abort(MYSQLD_ABORT_EXIT);
6974 
6975   if (!server_id_supplied)
6976     LogErr(INFORMATION_LEVEL, ER_WARN_NO_SERVERID_SPECIFIED);
6977 
6978   /*
6979     Add server_uuid to the sid_map.  This must be done after
6980     server_uuid has been initialized in init_server_auto_options and
6981     after the binary log (and sid_map file) has been initialized in
6982     init_server_components().
6983 
6984     No error message is needed: init_sid_map() prints a message.
6985 
6986     Strictly speaking, this is not currently needed when
6987     opt_bin_log==0, since the variables that gtid_state->init
6988     initializes are not currently used in that case.  But we call it
6989     regardless to avoid possible future bugs if gtid_state ever
6990     needs to do anything else.
6991   */
6992   global_sid_lock->wrlock();
6993   int gtid_ret = gtid_state->init();
6994   global_sid_lock->unlock();
6995 
6996   if (gtid_ret) unireg_abort(MYSQLD_ABORT_EXIT);
6997 
6998   if (!opt_initialize && !opt_initialize_insecure) {
6999     // Initialize executed_gtids from mysql.gtid_executed table.
7000     if (gtid_state->read_gtid_executed_from_table() == -1) unireg_abort(1);
7001   }
7002 
7003   if (opt_bin_log) {
7004     /*
7005       Initialize GLOBAL.GTID_EXECUTED and GLOBAL.GTID_PURGED from
7006       gtid_executed table and binlog files during server startup.
7007     */
7008     Gtid_set *executed_gtids =
7009         const_cast<Gtid_set *>(gtid_state->get_executed_gtids());
7010     Gtid_set *lost_gtids = const_cast<Gtid_set *>(gtid_state->get_lost_gtids());
7011     Gtid_set *gtids_only_in_table =
7012         const_cast<Gtid_set *>(gtid_state->get_gtids_only_in_table());
7013     Gtid_set *previous_gtids_logged =
7014         const_cast<Gtid_set *>(gtid_state->get_previous_gtids_logged());
7015 
7016     Gtid_set purged_gtids_from_binlog(global_sid_map, global_sid_lock);
7017     Gtid_set gtids_in_binlog(global_sid_map, global_sid_lock);
7018     Gtid_set gtids_in_binlog_not_in_table(global_sid_map, global_sid_lock);
7019 
7020     if (mysql_bin_log.init_gtid_sets(
7021             &gtids_in_binlog, &purged_gtids_from_binlog,
7022             opt_master_verify_checksum, true /*true=need lock*/,
7023             nullptr /*trx_parser*/, nullptr /*partial_trx*/,
7024             true /*is_server_starting*/))
7025       unireg_abort(MYSQLD_ABORT_EXIT);
7026 
7027     global_sid_lock->wrlock();
7028 
7029     purged_gtids_from_binlog.dbug_print("purged_gtids_from_binlog");
7030     gtids_in_binlog.dbug_print("gtids_in_binlog");
7031 
7032     if (!gtids_in_binlog.is_empty() &&
7033         !gtids_in_binlog.is_subset(executed_gtids)) {
7034       gtids_in_binlog_not_in_table.add_gtid_set(&gtids_in_binlog);
7035       if (!executed_gtids->is_empty())
7036         gtids_in_binlog_not_in_table.remove_gtid_set(executed_gtids);
7037       /*
7038         Save unsaved GTIDs into gtid_executed table, in the following
7039         four cases:
7040           1. the upgrade case.
7041           2. the case that a slave is provisioned from a backup of
7042              the master and the slave is cleaned by RESET MASTER
7043              and RESET SLAVE before this.
7044           3. the case that no binlog rotation happened from the
7045              last RESET MASTER on the server before it crashes.
7046           4. The set of GTIDs of the last binlog is not saved into the
7047              gtid_executed table if server crashes, so we save it into
7048              gtid_executed table and executed_gtids during recovery
7049              from the crash.
7050       */
7051       if (gtid_state->save(&gtids_in_binlog_not_in_table) == -1) {
7052         global_sid_lock->unlock();
7053         unireg_abort(MYSQLD_ABORT_EXIT);
7054       }
7055       executed_gtids->add_gtid_set(&gtids_in_binlog_not_in_table);
7056     }
7057 
7058     /* gtids_only_in_table= executed_gtids - gtids_in_binlog */
7059     if (gtids_only_in_table->add_gtid_set(executed_gtids) != RETURN_STATUS_OK) {
7060       global_sid_lock->unlock();
7061       unireg_abort(MYSQLD_ABORT_EXIT);
7062     }
7063     gtids_only_in_table->remove_gtid_set(&gtids_in_binlog);
7064     /*
7065       lost_gtids = executed_gtids -
7066                    (gtids_in_binlog - purged_gtids_from_binlog)
7067                  = gtids_only_in_table + purged_gtids_from_binlog;
7068     */
7069     DBUG_ASSERT(lost_gtids->is_empty());
7070     if (lost_gtids->add_gtid_set(gtids_only_in_table) != RETURN_STATUS_OK ||
7071         lost_gtids->add_gtid_set(&purged_gtids_from_binlog) !=
7072             RETURN_STATUS_OK) {
7073       global_sid_lock->unlock();
7074       unireg_abort(MYSQLD_ABORT_EXIT);
7075     }
7076 
7077     /* Prepare previous_gtids_logged for next binlog */
7078     if (previous_gtids_logged->add_gtid_set(&gtids_in_binlog) !=
7079         RETURN_STATUS_OK) {
7080       global_sid_lock->unlock();
7081       unireg_abort(MYSQLD_ABORT_EXIT);
7082     }
7083 
7084     /*
7085       Write the previous set of gtids at this point because during
7086       the creation of the binary log this is not done as we cannot
7087       move the init_gtid_sets() to a place before openning the binary
7088       log. This requires some investigation.
7089 
7090       /Alfranio
7091     */
7092     Previous_gtids_log_event prev_gtids_ev(&gtids_in_binlog);
7093 
7094     global_sid_lock->unlock();
7095 
7096     (prev_gtids_ev.common_footer)->checksum_alg =
7097         static_cast<enum_binlog_checksum_alg>(binlog_checksum_options);
7098 
7099     if (mysql_bin_log.write_event_to_binlog_and_sync(&prev_gtids_ev))
7100       unireg_abort(MYSQLD_ABORT_EXIT);
7101 
7102     (void)RUN_HOOK(server_state, after_engine_recovery, (nullptr));
7103   }
7104 
7105   if (init_ssl_communication()) unireg_abort(MYSQLD_ABORT_EXIT);
7106   if (network_init()) unireg_abort(MYSQLD_ABORT_EXIT);
7107 
7108 #ifdef _WIN32
7109   if (opt_require_secure_transport && !opt_enable_shared_memory &&
7110       !have_ssl() && !opt_initialize) {
7111     LogErr(ERROR_LEVEL, ER_TRANSPORTS_WHAT_TRANSPORTS);
7112     unireg_abort(MYSQLD_ABORT_EXIT);
7113   }
7114 #endif
7115 
7116   /*
7117    Initialize my_str_malloc(), my_str_realloc() and my_str_free()
7118   */
7119   my_str_malloc = &my_str_malloc_mysqld;
7120   my_str_free = &my_str_free_mysqld;
7121   my_str_realloc = &my_str_realloc_mysqld;
7122 
7123   error_handler_hook = my_message_sql;
7124 
7125   bool abort = false;
7126 
7127   /* Save pid of this process in a file */
7128   if (!opt_initialize) {
7129     if (create_pid_file()) abort = true;
7130   }
7131 
7132   /* Read the optimizer cost model configuration tables */
7133   if (!opt_initialize) reload_optimizer_cost_constants();
7134 
7135   if (
7136       /*
7137         Read components table to restore previously installed components. This
7138         requires read access to mysql.component table.
7139       */
7140       (!opt_initialize && mysql_component_infrastructure_init()) ||
7141       mysql_rm_tmp_tables()) {
7142     abort = true;
7143   }
7144 
7145   /* we do want to exit if there are any other unknown options */
7146   if (remaining_argc > 1) {
7147     int ho_error;
7148     struct my_option no_opts[] = {{nullptr, 0, nullptr, nullptr, nullptr,
7149                                    nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0,
7150                                    nullptr, 0, nullptr}};
7151     /*
7152       We need to eat any 'loose' arguments first before we conclude
7153       that there are unprocessed options.
7154     */
7155     my_getopt_skip_unknown = false;
7156 
7157     if ((ho_error = handle_options(&remaining_argc, &remaining_argv, no_opts,
7158                                    mysqld_get_one_option)))
7159       abort = true;
7160     else {
7161       /* Add back the program name handle_options removes */
7162       remaining_argc++;
7163       remaining_argv--;
7164       my_getopt_skip_unknown = true;
7165 
7166       if (remaining_argc > 1) {
7167         LogErr(ERROR_LEVEL, ER_EXCESS_ARGUMENTS, remaining_argv[1]);
7168         LogErr(INFORMATION_LEVEL, ER_VERBOSE_HINT);
7169         abort = true;
7170       }
7171     }
7172   }
7173 
7174   if (abort || acl_init(opt_noacl)) {
7175     if (!abort) LogErr(ERROR_LEVEL, ER_PRIVILEGE_SYSTEM_INIT_FAILED);
7176     abort = true;
7177     opt_noacl = true;
7178   }
7179 
7180   /*
7181    if running with --initialize, explicitly allocate the memory
7182    to be used by ACL objects.
7183   */
7184   if (opt_initialize) init_acl_memory();
7185 
7186   /*
7187     Turn ON the system variable '@@partial_revokes' during server
7188     start in case there exist at least one restrictions instance.
7189   */
7190   if (mysqld_partial_revokes() == false && is_partial_revoke_exists(nullptr)) {
7191     set_mysqld_partial_revokes(true);
7192     LogErr(WARNING_LEVEL, ER_TURNING_ON_PARTIAL_REVOKES);
7193   }
7194 
7195   if (abort || my_tz_init((THD *)nullptr, default_tz_name, opt_initialize) ||
7196       grant_init(opt_noacl)) {
7197     set_connection_events_loop_aborted(true);
7198 
7199     delete_pid_file(MYF(MY_WME));
7200 
7201     unireg_abort(MYSQLD_ABORT_EXIT);
7202   }
7203 
7204   /*
7205     Bootstrap the dynamic privilege service implementation
7206   */
7207   if (dynamic_privilege_init()) {
7208     LogErr(WARNING_LEVEL, ER_PERSISTENT_PRIVILEGES_BOOTSTRAP);
7209   }
7210 
7211   if (!opt_initialize) servers_init(false);
7212 
7213   if (!opt_noacl) {
7214     udf_read_functions_table();
7215   }
7216 
7217   init_status_vars();
7218   /* If running with --initialize, do not start replication. */
7219   if (opt_initialize) opt_skip_slave_start = true;
7220 
7221   check_binlog_cache_size(nullptr);
7222   check_binlog_stmt_cache_size(nullptr);
7223 
7224   binlog_unsafe_map_init();
7225 
7226   /* If running with --initialize, do not start replication. */
7227   if (!opt_initialize) {
7228     // Make @@slave_skip_errors show the nice human-readable value.
7229     set_slave_skip_errors(&opt_slave_skip_errors);
7230     /*
7231       Group replication filters should be discarded before init_slave(),
7232       otherwise the pre-configured filters will be referenced by group
7233       replication channels.
7234     */
7235     rpl_channel_filters.discard_group_replication_filters();
7236 
7237     /*
7238       init_slave() must be called after the thread keys are created.
7239     */
7240     if (server_id != 0)
7241       init_slave(); /* Ignoring errors while configuring replication. */
7242 
7243     /*
7244       If the user specifies a per-channel replication filter through a
7245       command-line option (or in a configuration file) for a slave
7246       replication channel which does not exist as of now (i.e not
7247       present in slave info tables yet), then the per-channel
7248       replication filter is discarded with a warning.
7249       If the user specifies a per-channel replication filter through
7250       a command-line option (or in a configuration file) for group
7251       replication channels 'group_replication_recovery' and
7252       'group_replication_applier' which is disallowed, then the
7253       per-channel replication filter is discarded with a warning.
7254     */
7255     rpl_channel_filters.discard_all_unattached_filters();
7256   }
7257 
7258 #ifdef WITH_LOCK_ORDER
7259   if (!opt_initialize) {
7260     LO_activate();
7261   }
7262 #endif /* WITH_LOCK_ORDER */
7263 
7264 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
7265   initialize_performance_schema_acl(opt_initialize);
7266 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
7267 
7268   initialize_information_schema_acl();
7269 
7270   (void)RUN_HOOK(server_state, after_recovery, (nullptr));
7271 
7272   if (Events::init(opt_noacl || opt_initialize))
7273     unireg_abort(MYSQLD_ABORT_EXIT);
7274 
7275 #ifndef _WIN32
7276   //  Start signal handler thread.
7277   start_signal_handler();
7278 #endif
7279 
7280   /* set all persistent options */
7281   if (persisted_variables_cache.set_persist_options()) {
7282     LogErr(ERROR_LEVEL, ER_CANT_SET_UP_PERSISTED_VALUES);
7283     flush_error_log_messages();
7284     return 1;
7285   }
7286 
7287   /*
7288     Activate loadable error logging components, if any.
7289     First, check configuration value -- is it well-formed, and do
7290     the requested services exist?
7291   */
7292   if (log_builtins_error_stack(opt_log_error_services, true, nullptr) == 0) {
7293     // Syntax is OK and services exist; let's try to initialize them:
7294     size_t pos;
7295 
7296     if (log_builtins_error_stack(opt_log_error_services, false, &pos) < 0) {
7297       char *problem = opt_log_error_services; /* purecov: begin inspected */
7298       const char *var_name = "log_error_services";
7299 
7300       /*
7301         We failed to set the requested configuration. This can happen
7302         e.g. when a given log-writer does not have sufficient permissions
7303         to open its log files. pos should mark the position in the
7304         configuration string where we ran into trouble. Make a char-pointer
7305         from it so we can inform the user what log-service we could not
7306         initialize.
7307       */
7308       if (pos < strlen(opt_log_error_services))
7309         problem = &((char *)opt_log_error_services)[pos];
7310 
7311       flush_error_log_messages();
7312 
7313       /*
7314         We could not set the requested pipeline.
7315         Try to fall back to default error logging stack
7316         (by looking up the system variable for this configuration
7317         item and extracting the default value from it).
7318         If that's impossible, print diagnostics, then exit.
7319       */
7320       sys_var *var = intern_find_sys_var(var_name, strlen(var_name));
7321 
7322       if (var != nullptr) {
7323         // We found the system variable, now extract the default value:
7324         opt_log_error_services = (char *)var->get_default();
7325         if (log_builtins_error_stack(opt_log_error_services, false, nullptr) >=
7326             0) {
7327           /*
7328             We managed to set the default pipeline. Now log what was wrong
7329             about the user-supplied value, then shut down.
7330           */
7331           LogErr(ERROR_LEVEL, ER_CANT_START_ERROR_LOG_SERVICE, var_name,
7332                  problem);
7333           unireg_abort(MYSQLD_ABORT_EXIT);
7334         }
7335         /*
7336           If we arrive here, the user-supplied value was valid, but could
7337           not be set. The default value was found, but also could not be
7338           set. Something is very wrong. Fall-through to below where we
7339           low-level write diagnostics, then abort.
7340         */
7341       }
7342 
7343       /*
7344         We failed to set the default error logging stack (or failed to look
7345         up the default setting). At this point, we don't know whether ANY of
7346         the requested sinks work, so our best bet is to write directly to the
7347         error stream. Then, we abort.
7348       */
7349       {
7350         char buff[512];
7351         size_t len;
7352 
7353         len = snprintf(buff, sizeof(buff),
7354                        ER_DEFAULT(ER_CANT_START_ERROR_LOG_SERVICE), var_name,
7355                        problem);
7356         len = std::min(len, sizeof(buff) - 1);
7357 
7358         // Trust nothing. Write directly. Quit.
7359         log_write_errstream(buff, len);
7360 
7361         unireg_abort(MYSQLD_ABORT_EXIT);
7362       } /* purecov: end */
7363     }   // value was OK, but could not be set
7364     // If we arrive here, the value was OK, and was set successfully.
7365   } else {
7366     /*
7367       We were given an illegal value at start-up, so the default was
7368       used instead. Let's now point our variable back at the default
7369       (i.e. the value actually used) so SELECT @@GLOBAL.log_error_services
7370       will render correct results.
7371     */
7372     sys_var *var = intern_find_sys_var(STRING_WITH_LEN("log_error_services"));
7373     char *default_services = nullptr;
7374 
7375     if ((var != nullptr) &&
7376         ((default_services = (char *)var->get_default()) != nullptr))
7377       log_builtins_error_stack(default_services, false, nullptr);
7378 
7379     // Report that we're falling back to the default value.
7380     LogErr(WARNING_LEVEL, ER_CANNOT_SET_LOG_ERROR_SERVICES,
7381            opt_log_error_services);
7382 
7383     if (default_services != nullptr) opt_log_error_services = default_services;
7384   }
7385 
7386   /*
7387     Now that the error-logging stack is fully set up, loadable components
7388     and all, flush buffered log-events to the log-services the user actually
7389     wants!
7390   */
7391   log_error_stage_set(LOG_ERROR_STAGE_EXTERNAL_SERVICES_AVAILABLE);
7392   flush_error_log_messages();
7393 
7394   /*
7395     Invoke the bootstrap thread, if required.
7396   */
7397   process_bootstrap();
7398 
7399   /*
7400     Event must be invoked after error_handler_hook is assigned to
7401     my_message_sql, otherwise my_message will not cause the event to abort.
7402   */
7403   void *argv_p = argv;
7404   if (mysql_audit_notify(AUDIT_EVENT(MYSQL_AUDIT_SERVER_STARTUP_STARTUP),
7405                          static_cast<const char **>(argv_p), argc))
7406     unireg_abort(MYSQLD_ABORT_EXIT);
7407 
7408 #ifdef _WIN32
7409   create_shutdown_and_restart_thread();
7410 #endif
7411   if (mysqld_process_must_end_at_startup) {
7412 #if !defined(_WIN32)
7413     if (opt_daemonize) mysqld::runtime::signal_parent(pipe_write_fd, 1);
7414 #endif
7415     unireg_abort(MYSQLD_SUCCESS_EXIT);
7416   }
7417 
7418   start_handle_manager();
7419 
7420   create_compress_gtid_table_thread();
7421 
7422   LogEvent()
7423       .type(LOG_TYPE_ERROR)
7424       .subsys(LOG_SUBSYSTEM_TAG)
7425       .prio(SYSTEM_LEVEL)
7426       .lookup(ER_SERVER_STARTUP_MSG, my_progname, server_version,
7427 #ifdef HAVE_SYS_UN_H
7428               (opt_initialize ? "" : mysqld_unix_port),
7429 #else
7430               "",
7431 #endif
7432               mysqld_port, MYSQL_COMPILATION_COMMENT_SERVER);
7433 
7434   if (!opt_disable_networking && my_admin_bind_addr_str)
7435     LogEvent()
7436         .type(LOG_TYPE_ERROR)
7437         .subsys(LOG_SUBSYSTEM_TAG)
7438         .prio(SYSTEM_LEVEL)
7439         .lookup(ER_SERVER_STARTUP_ADMIN_INTERFACE, my_admin_bind_addr_str,
7440                 mysqld_admin_port, MYSQL_COMPILATION_COMMENT);
7441 
7442 #if defined(_WIN32)
7443   if (windows_service) {
7444     Service_status_msg s("R");
7445     send_service_status(s);
7446   }
7447 #endif
7448 
7449   server_components_initialized();
7450 
7451   /*
7452     Set opt_super_readonly here because if opt_super_readonly is set
7453     in get_option, it will create problem while setting up event scheduler.
7454   */
7455   set_super_read_only_post_init();
7456 
7457   DBUG_PRINT("info", ("Block, listening for incoming connections"));
7458 
7459   (void)MYSQL_SET_STAGE(0, __FILE__, __LINE__);
7460 
7461   server_operational_state = SERVER_OPERATING;
7462   sysd::notify("READY=1\nSTATUS=Server is operational\nMAIN_PID=", getpid(),
7463                "\n");
7464 
7465   (void)RUN_HOOK(server_state, before_handle_connection, (nullptr));
7466 
7467 #if defined(_WIN32)
7468   setup_conn_event_handler_threads();
7469 #else
7470   mysql_mutex_lock(&LOCK_socket_listener_active);
7471   // Make it possible for the signal handler to kill the listener.
7472   socket_listener_active = true;
7473   mysql_mutex_unlock(&LOCK_socket_listener_active);
7474 
7475   if (opt_daemonize) {
7476     if (nstdout != nullptr) {
7477       // Show the pid on stdout if deamonizing and connected to tty
7478       fprintf(nstdout, "mysqld is running as pid %lu\n", current_pid);
7479       fclose(nstdout);
7480       nstdout = nullptr;
7481     }
7482 
7483     mysqld::runtime::signal_parent(pipe_write_fd, 1);
7484   }
7485 
7486   mysqld_socket_acceptor->connection_event_loop();
7487 #endif /* _WIN32 */
7488   server_operational_state = SERVER_SHUTTING_DOWN;
7489   sysd::notify("STOPPING=1\nSTATUS=Server shutdown in progress\n");
7490 
7491   DBUG_PRINT("info", ("No longer listening for incoming connections"));
7492 
7493   mysql_audit_notify(MYSQL_AUDIT_SERVER_SHUTDOWN_SHUTDOWN,
7494                      MYSQL_AUDIT_SERVER_SHUTDOWN_REASON_SHUTDOWN,
7495                      MYSQLD_SUCCESS_EXIT);
7496 
7497   terminate_compress_gtid_table_thread();
7498   /*
7499     Save set of GTIDs of the last binlog into gtid_executed table
7500     on server shutdown.
7501   */
7502   if (opt_bin_log)
7503     if (gtid_state->save_gtids_of_last_binlog_into_table())
7504       LogErr(WARNING_LEVEL, ER_CANT_SAVE_GTIDS);
7505 
7506 #ifndef _WIN32
7507   mysql_mutex_lock(&LOCK_socket_listener_active);
7508   // Notify the signal handler that we have stopped listening for connections.
7509   socket_listener_active = false;
7510   mysql_cond_broadcast(&COND_socket_listener_active);
7511   mysql_mutex_unlock(&LOCK_socket_listener_active);
7512 #endif  // !_WIN32
7513 
7514 #ifdef HAVE_PSI_THREAD_INTERFACE
7515   /*
7516     Disable the main thread instrumentation,
7517     to avoid recording events during the shutdown.
7518   */
7519   PSI_THREAD_CALL(delete_current_thread)();
7520 #endif /* HAVE_PSI_THREAD_INTERFACE */
7521 
7522   DBUG_PRINT("info", ("Waiting for shutdown proceed"));
7523   int ret = 0;
7524 #ifdef _WIN32
7525   if (shutdown_restart_thr_handle.handle)
7526     ret = my_thread_join(&shutdown_restart_thr_handle, NULL);
7527   shutdown_restart_thr_handle.handle = NULL;
7528   if (0 != ret)
7529     LogErr(WARNING_LEVEL, ER_CANT_JOIN_SHUTDOWN_THREAD, "shutdown ", ret);
7530 #else
7531   if (signal_thread_id.thread != 0)
7532     ret = my_thread_join(&signal_thread_id, nullptr);
7533   signal_thread_id.thread = 0;
7534   if (0 != ret)
7535     LogErr(WARNING_LEVEL, ER_CANT_JOIN_SHUTDOWN_THREAD, "signal_", ret);
7536 #endif  // _WIN32
7537 
7538   clean_up(true);
7539   sysd::notify("STATUS=Server shutdown complete");
7540   mysqld_exit(signal_hand_thr_exit_code);
7541 }
7542 
7543 /****************************************************************************
7544   Main and thread entry function for Win32
7545   (all this is needed only to run mysqld as a service on WinNT)
7546 ****************************************************************************/
7547 
7548 #if defined(_WIN32)
7549 
is_windows_service()7550 bool is_windows_service() { return windows_service; }
7551 
get_win_service_ptr()7552 NTService *get_win_service_ptr() { return &Service; }
7553 
mysql_service(void * p)7554 int mysql_service(void *p) {
7555   int my_argc;
7556   char **my_argv;
7557 
7558   if (use_opt_args) {
7559     my_argc = opt_argc;
7560     my_argv = opt_argv;
7561   } else if (is_mysqld_monitor()) {
7562     my_argc = Service.my_argc;
7563     my_argv = Service.my_argv;
7564   } else {
7565     my_argc = my_global_argc;
7566     my_argv = my_global_argv;
7567   }
7568 
7569   if (!mysqld_early_option) {
7570     int res = start_monitor();
7571     if (res != -1) {
7572       deinitialize_mysqld_monitor();
7573       return res;
7574     }
7575   }
7576 
7577   if (my_thread_init()) {
7578     flush_error_log_messages();
7579     return 1;
7580   }
7581 
7582   win_main(my_argc, my_argv);
7583 
7584   my_thread_end();
7585   return 0;
7586 }
7587 
7588 /* Quote string if it contains space, else copy */
7589 
add_quoted_string(char * to,const char * from,char * to_end)7590 static char *add_quoted_string(char *to, const char *from, char *to_end) {
7591   uint length = (uint)(to_end - to);
7592 
7593   if (!strchr(from, ' ')) return strmake(to, from, length - 1);
7594   return strxnmov(to, length - 1, "\"", from, "\"", NullS);
7595 }
7596 
7597 /**
7598   Handle basic handling of services, like installation and removal.
7599 
7600   @param argv             Pointer to argument list
7601   @param servicename    Internal name of service
7602   @param displayname    Display name of service (in taskbar ?)
7603   @param file_path    Path to this program
7604   @param startup_option Startup option to mysqld
7605 
7606   @retval
7607     0   option handled
7608   @retval
7609     1   Could not handle option
7610 */
7611 
default_service_handling(char ** argv,const char * servicename,const char * displayname,const char * file_path,const char * extra_opt,const char * account_name)7612 static bool default_service_handling(char **argv, const char *servicename,
7613                                      const char *displayname,
7614                                      const char *file_path,
7615                                      const char *extra_opt,
7616                                      const char *account_name) {
7617   char path_and_service[FN_REFLEN + FN_REFLEN + 32], *pos, *end;
7618   const char *opt_delim;
7619   end = path_and_service + sizeof(path_and_service) - 3;
7620 
7621   /* We have to quote filename if it contains spaces */
7622   pos = add_quoted_string(path_and_service, file_path, end);
7623   if (extra_opt && *extra_opt) {
7624     /*
7625      Add option after file_path. There will be zero or one extra option.  It's
7626      assumed to be --defaults-file=file but isn't checked.  The variable (not
7627      the option name) should be quoted if it contains a string.
7628     */
7629     *pos++ = ' ';
7630     if (opt_delim = strchr(extra_opt, '=')) {
7631       size_t length = ++opt_delim - extra_opt;
7632       pos = my_stpnmov(pos, extra_opt, length);
7633     } else
7634       opt_delim = extra_opt;
7635 
7636     pos = add_quoted_string(pos, opt_delim, end);
7637   }
7638   /* We must have servicename last */
7639   *pos++ = ' ';
7640   (void)add_quoted_string(pos, servicename, end);
7641 
7642   if (Service.got_service_option(argv, "install")) {
7643     Service.Install(1, servicename, displayname, path_and_service,
7644                     account_name);
7645     return 0;
7646   }
7647   if (Service.got_service_option(argv, "install-manual")) {
7648     Service.Install(0, servicename, displayname, path_and_service,
7649                     account_name);
7650     return 0;
7651   }
7652   if (Service.got_service_option(argv, "remove")) {
7653     Service.Remove(servicename);
7654     return 0;
7655   }
7656   return 1;
7657 }
7658 
mysqld_main(int argc,char ** argv)7659 int mysqld_main(int argc, char **argv) {
7660   bool mysqld_monitor = false;
7661   mysqld_early_option = is_early_option(argc, argv);
7662 
7663   if (!mysqld_early_option) {
7664     initialize_mysqld_monitor();
7665     mysqld_monitor = is_mysqld_monitor();
7666   }
7667 
7668   if (mysqld_early_option || !mysqld_monitor) {
7669     /*
7670       When several instances are running on the same machine, we
7671       need to have an  unique  named  hEventShudown  through the
7672       application PID e.g.: MySQLShutdown1890; MySQLShutdown2342
7673     */
7674 
7675     longlong10_to_str(GetCurrentProcessId(),
7676                       my_stpcpy(shutdown_event_name, "MYSQLShutdown"), 10);
7677     longlong10_to_str(GetCurrentProcessId(),
7678                       my_stpcpy(restart_event_name, "MYSQLRestart"), 10);
7679   }
7680 
7681   /* Must be initialized early for comparison of service name */
7682   system_charset_info = &my_charset_utf8_general_ci;
7683 
7684   if (mysqld_early_option || !mysqld_monitor) {
7685 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
7686     pre_initialize_performance_schema();
7687 #endif /*WITH_PERFSCHEMA_STORAGE_ENGINE */
7688 
7689     if (my_init()) {
7690       LogErr(ERROR_LEVEL, ER_MYINIT_FAILED);
7691       flush_error_log_messages();
7692       return 1;
7693     }
7694   }
7695 
7696   if (Service.GetOS() && mysqld_monitor) /* true NT family */
7697   {
7698     char file_path[FN_REFLEN];
7699     my_path(file_path, argv[0], ""); /* Find name in path */
7700     fn_format(file_path, argv[0], file_path, "",
7701               MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_RESOLVE_SYMLINKS);
7702 
7703     if (argc == 2) {
7704       if (!default_service_handling(argv, MYSQL_SERVICENAME, MYSQL_SERVICENAME,
7705                                     file_path, "", NULL))
7706         return 0;
7707       if (Service.IsService(argv[1])) /* Start an optional service */
7708       {
7709         /*
7710           Only add the service name to the groups read from the config file
7711           if it's not "MySQL". (The default service name should be 'mysqld'
7712           but we started a bad tradition by calling it MySQL from the start
7713           and we are now stuck with it.
7714         */
7715         if (my_strcasecmp(system_charset_info, argv[1], "mysql"))
7716           load_default_groups[load_default_groups_sz - 2] = argv[1];
7717         windows_service = true;
7718 
7719         Service.Init(argv[1], mysql_service);
7720         return 0;
7721       }
7722     } else if (argc == 3) /* install or remove any optional service */
7723     {
7724       if (!default_service_handling(argv, argv[2], argv[2], file_path, "",
7725                                     NULL))
7726         return 0;
7727       if (Service.IsService(argv[2])) {
7728         /*
7729           mysqld was started as
7730           mysqld --defaults-file=my_path\my.ini service-name
7731         */
7732         use_opt_args = 1;
7733         opt_argc = 2;  // Skip service-name
7734         opt_argv = argv;
7735         windows_service = true;
7736         if (my_strcasecmp(system_charset_info, argv[2], "mysql"))
7737           load_default_groups[load_default_groups_sz - 2] = argv[2];
7738         Service.Init(argv[2], mysql_service);
7739         return 0;
7740       }
7741     } else if (argc == 4 || argc == 5) {
7742       /*
7743         This may seem strange, because we handle --local-service while
7744         preserving 4.1's behavior of allowing any one other argument that is
7745         passed to the service on startup. (The assumption is that this is
7746         --defaults-file=file, but that was not enforced in 4.1, so we don't
7747         enforce it here.)
7748       */
7749       const char *extra_opt = NullS;
7750       const char *account_name = NullS;
7751       int index;
7752       for (index = 3; index < argc; index++) {
7753         if (!strcmp(argv[index], "--local-service"))
7754           account_name = "NT AUTHORITY\\LocalService";
7755         else
7756           extra_opt = argv[index];
7757       }
7758 
7759       if (argc == 4 || account_name)
7760         if (!default_service_handling(argv, argv[2], argv[2], file_path,
7761                                       extra_opt, account_name))
7762           return 0;
7763     } else if (argc == 1 && Service.IsService(MYSQL_SERVICENAME)) {
7764       /* start the default service */
7765       windows_service = true;
7766       Service.Init(MYSQL_SERVICENAME, mysql_service);
7767       return 0;
7768     }
7769   }
7770 
7771   // Set windows_service value in mysqld
7772   if (!mysqld_monitor) {
7773     windows_service = is_monitor_win_service();
7774 
7775     if (windows_service) {
7776       if (argc == 2 && Service.IsService(argv[1])) {
7777         if (my_strcasecmp(system_charset_info, argv[1], "mysql"))
7778           load_default_groups[load_default_groups_sz - 2] = argv[1];
7779         argc--;
7780 
7781       } else if (argc == 3 && Service.IsService(argv[2])) {
7782         /*
7783         mysqld was started as
7784         mysqld --defaults-file=my_path\my.ini service-name
7785         */
7786         if (my_strcasecmp(system_charset_info, argv[2], "mysql"))
7787           load_default_groups[load_default_groups_sz - 2] = argv[2];
7788         argc--;
7789       }
7790     }
7791 
7792     my_global_argc = argc;
7793     my_global_argv = argv;
7794   } else {
7795     Service.my_argc = argc;
7796     Service.my_argv = argv;
7797   }
7798 
7799   return mysql_service(NULL);
7800 }
7801 #endif  // _WIN32
7802 
7803 /**
7804   Execute the bootstrap thread, if required.
7805 
7806   When mysqld is started with --initialize only,
7807   the bootstrap thread executes
7808   - compiled in statements.
7809   - create the non-DD based INFORMATION_SCHEMA.
7810   and the server exits.
7811 
7812   When mysqld is started with --init-file only,
7813   the bootstrap thread executes SQL statements provided
7814   in the input text file,
7815   and the server continues and serves requests.
7816 
7817   When mysqld is started with both --initialize and --init-file,
7818   the bootstrap thread:
7819   - executes compiled in statements,
7820   - executes SQL statements in the --init-file.
7821   - creates the non-DD based INFORMATION_SCHEMA.
7822   The server then exits.
7823 
7824   Compiled in statements are executed in a privileged mode,
7825   with SYSTEM_THREAD_SERVER_INITIALIZE.
7826 
7827   @see handle_bootstrap_impl
7828 */
process_bootstrap()7829 static void process_bootstrap() {
7830   MYSQL_FILE *init_file = nullptr;
7831   const char *init_file_name = nullptr;
7832   enum_thread_type system_thread;
7833   bool need_bootstrap = false;
7834 
7835   if (opt_initialize) {
7836     // Make sure we can process SIGHUP during bootstrap.
7837     server_components_initialized();
7838     need_bootstrap = true;
7839     system_thread = SYSTEM_THREAD_SERVER_INITIALIZE;
7840   } else {
7841     system_thread = SYSTEM_THREAD_INIT_FILE;
7842   }
7843 
7844   if (opt_init_file != nullptr) {
7845     if (*opt_init_file != '\0') {
7846       init_file_name = opt_init_file;
7847       LogErr(INFORMATION_LEVEL, ER_BEG_INITFILE, init_file_name);
7848 
7849       init_file = mysql_file_fopen(key_file_init, init_file_name, O_RDONLY,
7850                                    MYF(MY_WME));
7851       need_bootstrap = true;
7852     }
7853 
7854     if (init_file == nullptr) {
7855       LogErr(ERROR_LEVEL, ER_INIT_CANT_OPEN_BOOTSTRAP_FILE, init_file_name);
7856       unireg_abort(MYSQLD_ABORT_EXIT);
7857     }
7858   }
7859 
7860   if (need_bootstrap) {
7861     bool error = bootstrap::run_bootstrap_thread(init_file_name, init_file,
7862                                                  nullptr, system_thread);
7863 
7864     if (init_file != nullptr) {
7865       mysql_file_fclose(init_file, MYF(MY_WME));
7866       LogErr(INFORMATION_LEVEL, ER_END_INITFILE, init_file_name);
7867     }
7868 
7869     if (error) {
7870       /* Abort during system initialization, but not init-file execution */
7871       if (system_thread == SYSTEM_THREAD_SERVER_INITIALIZE) {
7872         unireg_abort(MYSQLD_ABORT_EXIT);
7873       }
7874     }
7875 
7876     if (opt_initialize) {
7877       // Create non DD based system views during --initialize.
7878       error = dd::init(
7879           dd::enum_dd_init_type::DD_INITIALIZE_NON_DD_BASED_SYSTEM_VIEWS);
7880       if (error != 0) {
7881         LogErr(ERROR_LEVEL, ER_SYSTEM_VIEW_INIT_FAILED);
7882         unireg_abort(MYSQLD_ABORT_EXIT);
7883       }
7884 
7885       unireg_abort(MYSQLD_SUCCESS_EXIT);
7886     }
7887   }
7888 
7889   return;
7890 }
7891 
7892 /****************************************************************************
7893   Handle start options
7894 ******************************************************************************/
7895 
7896 /**
7897   Process command line options flagged as 'early'.
7898   Some components needs to be initialized as early as possible,
7899   because the rest of the server initialization depends on them.
7900   Options that needs to be parsed early includes:
7901   - the performance schema, when compiled in,
7902   - options related to the help,
7903   - options related to the bootstrap
7904   The performance schema needs to be initialized as early as possible,
7905   before to-be-instrumented objects of the server are initialized.
7906 */
handle_early_options()7907 static int handle_early_options() {
7908   int ho_error;
7909   vector<my_option> all_early_options;
7910   all_early_options.reserve(100);
7911 
7912   my_getopt_register_get_addr(nullptr);
7913   /* Skip unknown options so that they may be processed later */
7914   my_getopt_skip_unknown = true;
7915 
7916   /* Add the system variables parsed early */
7917   sys_var_add_options(&all_early_options, sys_var::PARSE_EARLY);
7918 
7919   /* Add the command line options parsed early */
7920   for (my_option *opt = my_long_early_options; opt->name != nullptr; opt++)
7921     all_early_options.push_back(*opt);
7922 
7923   add_terminator(&all_early_options);
7924 
7925   my_getopt_error_reporter = option_error_reporter;
7926   my_charset_error_reporter = charset_error_reporter;
7927 
7928   ho_error = handle_options(&remaining_argc, &remaining_argv,
7929                             &all_early_options[0], mysqld_get_one_option);
7930   if (ho_error == 0) {
7931     /* Add back the program name handle_options removes */
7932     remaining_argc++;
7933     remaining_argv--;
7934 
7935     if (opt_initialize_insecure) opt_initialize = true;
7936   }
7937 
7938   // Swap with an empty vector, i.e. delete elements and free allocated space.
7939   vector<my_option>().swap(all_early_options);
7940 
7941   return ho_error;
7942 }
7943 
7944 /**
7945   Adjust @c open_files_limit.
7946   Computation is  based on:
7947   - @c max_connections,
7948   - @c table_cache_size,
7949   - the platform max open file limit.
7950 */
adjust_open_files_limit(ulong * requested_open_files)7951 static void adjust_open_files_limit(ulong *requested_open_files) {
7952   ulong limit_1;
7953   ulong limit_2;
7954   ulong limit_3;
7955   ulong request_open_files;
7956   ulong effective_open_files;
7957 
7958   /* MyISAM requires two file handles per table. */
7959   limit_1 = 10 + max_connections + table_cache_size * 2;
7960 
7961   /*
7962     We are trying to allocate no less than max_connections*5 file
7963     handles (i.e. we are trying to set the limit so that they will
7964     be available).
7965   */
7966   limit_2 = max_connections * 5;
7967 
7968   /* Try to allocate no less than 5000 by default. */
7969   limit_3 = open_files_limit ? open_files_limit : 5000;
7970 
7971   request_open_files = max<ulong>(max<ulong>(limit_1, limit_2), limit_3);
7972 
7973   /* Notice: my_set_max_open_files() may return more than requested. */
7974   effective_open_files = my_set_max_open_files(request_open_files);
7975 
7976   if (effective_open_files < request_open_files) {
7977     if (open_files_limit == 0) {
7978       LogErr(WARNING_LEVEL, ER_CHANGED_MAX_OPEN_FILES, effective_open_files,
7979              request_open_files);
7980     } else {
7981       LogErr(WARNING_LEVEL, ER_CANT_INCREASE_MAX_OPEN_FILES,
7982              effective_open_files, request_open_files);
7983     }
7984   }
7985 
7986   open_files_limit = effective_open_files;
7987   if (requested_open_files)
7988     *requested_open_files =
7989         min<ulong>(effective_open_files, request_open_files);
7990 }
7991 
adjust_max_connections(ulong requested_open_files)7992 static void adjust_max_connections(ulong requested_open_files) {
7993   ulong limit;
7994 
7995   limit = requested_open_files - 10 - TABLE_OPEN_CACHE_MIN * 2;
7996 
7997   if (limit < max_connections) {
7998     LogErr(WARNING_LEVEL, ER_CHANGED_MAX_CONNECTIONS, limit, max_connections);
7999 
8000     // This can be done unprotected since it is only called on startup.
8001     max_connections = limit;
8002   }
8003 }
8004 
adjust_table_cache_size(ulong requested_open_files)8005 static void adjust_table_cache_size(ulong requested_open_files) {
8006   ulong limit;
8007 
8008   limit = max<ulong>((requested_open_files - 10 - max_connections) / 2,
8009                      TABLE_OPEN_CACHE_MIN);
8010 
8011   if (limit < table_cache_size) {
8012     LogErr(WARNING_LEVEL, ER_CHANGED_TABLE_OPEN_CACHE, limit, table_cache_size);
8013 
8014     table_cache_size = limit;
8015   }
8016 
8017   table_cache_size_per_instance = table_cache_size / table_cache_instances;
8018 }
8019 
adjust_table_def_size()8020 static void adjust_table_def_size() {
8021   ulong default_value;
8022   sys_var *var;
8023 
8024   default_value = min<ulong>(400 + table_cache_size / 2, 2000);
8025   var = intern_find_sys_var(STRING_WITH_LEN("table_definition_cache"));
8026   DBUG_ASSERT(var != nullptr);
8027   var->update_default(default_value);
8028 
8029   if (!table_definition_cache_specified) table_def_size = default_value;
8030 }
8031 
adjust_related_options(ulong * requested_open_files)8032 static void adjust_related_options(ulong *requested_open_files) {
8033   /*
8034     In bootstrap, disable grant tables (about to be created)
8035   */
8036   if (opt_initialize) opt_noacl = true;
8037 
8038   /* The order is critical here, because of dependencies. */
8039   adjust_open_files_limit(requested_open_files);
8040   adjust_max_connections(*requested_open_files);
8041   adjust_table_cache_size(*requested_open_files);
8042   adjust_table_def_size();
8043 }
8044 
8045 vector<my_option> all_options;
8046 
8047 struct my_option my_long_early_options[] = {
8048 #if !defined(_WIN32)
8049     {"daemonize", 'D', "Run mysqld as sysv daemon", &opt_daemonize,
8050      &opt_daemonize, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8051 #endif
8052     {"skip-grant-tables", 0,
8053      "Start without grant tables. This gives all users FULL ACCESS to all "
8054      "tables.",
8055      &opt_noacl, &opt_noacl, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0,
8056      nullptr},
8057     {"help", '?', "Display this help and exit.", &opt_help, &opt_help, nullptr,
8058      GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8059     {"verbose", 'v', "Used with --help option for detailed help.", &opt_verbose,
8060      &opt_verbose, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8061     {"version", 'V', "Output version information and exit.", nullptr, nullptr,
8062      nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8063     {"initialize", 'I',
8064      "Create the default database and exit."
8065      " Create a super user with a random expired password and store it into "
8066      "the log.",
8067      &opt_initialize, &opt_initialize, nullptr, GET_BOOL, NO_ARG, 0, 0, 0,
8068      nullptr, 0, nullptr},
8069     {"initialize-insecure", 0,
8070      "Create the default database and exit."
8071      " Create a super user with empty password.",
8072      &opt_initialize_insecure, &opt_initialize_insecure, nullptr, GET_BOOL,
8073      NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8074     {"keyring-migration-source", OPT_KEYRING_MIGRATION_SOURCE,
8075      "Keyring plugin from where the keys needs to "
8076      "be migrated to. This option must be specified along with "
8077      "--keyring-migration-destination.",
8078      &opt_keyring_migration_source, &opt_keyring_migration_source, nullptr,
8079      GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
8080     {"keyring-migration-destination", OPT_KEYRING_MIGRATION_DESTINATION,
8081      "Keyring plugin to which the keys are "
8082      "migrated to. This option must be specified along with "
8083      "--keyring-migration-source.",
8084      &opt_keyring_migration_destination, &opt_keyring_migration_destination,
8085      nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
8086     {"keyring-migration-user", OPT_KEYRING_MIGRATION_USER,
8087      "User to login to server.", &opt_keyring_migration_user,
8088      &opt_keyring_migration_user, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0,
8089      nullptr, 0, nullptr},
8090     {"keyring-migration-host", OPT_KEYRING_MIGRATION_HOST, "Connect to host.",
8091      &opt_keyring_migration_host, &opt_keyring_migration_host, nullptr, GET_STR,
8092      REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
8093     {"keyring-migration-password", 'p',
8094      "Password to use when connecting to server during keyring migration. "
8095      "If password value is not specified then it will be asked from the tty.",
8096      nullptr, nullptr, nullptr, GET_PASSWORD, OPT_ARG, 0, 0, 0, nullptr, 0,
8097      nullptr},
8098     {"keyring-migration-socket", OPT_KEYRING_MIGRATION_SOCKET,
8099      "The socket file to use for connection.", &opt_keyring_migration_socket,
8100      &opt_keyring_migration_socket, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0,
8101      nullptr, 0, nullptr},
8102     {"keyring-migration-port", OPT_KEYRING_MIGRATION_PORT,
8103      "Port number to use for connection.", &opt_keyring_migration_port,
8104      &opt_keyring_migration_port, nullptr, GET_ULONG, REQUIRED_ARG, 0, 0, 0,
8105      nullptr, 0, nullptr},
8106     {"no-dd-upgrade", 0,
8107      "Abort restart if automatic upgrade or downgrade of the data dictionary "
8108      "is needed. Deprecated option. Use --upgrade=NONE instead.",
8109      &opt_no_dd_upgrade, &opt_no_dd_upgrade, nullptr, GET_BOOL, NO_ARG, 0, 0, 0,
8110      nullptr, 0, nullptr},
8111     {"validate-config", 0,
8112      "Validate the server configuration specified by the user.",
8113      &opt_validate_config, &opt_validate_config, nullptr, GET_BOOL, NO_ARG, 0,
8114      0, 0, nullptr, 0, nullptr},
8115     {nullptr, 0, nullptr, nullptr, nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0,
8116      0, nullptr, 0, nullptr}};
8117 
8118 /**
8119   System variables are automatically command-line options (few
8120   exceptions are documented in sys_var.h), so don't need
8121   to be listed here.
8122 */
8123 
8124 struct my_option my_long_options[] = {
8125     {"abort-slave-event-count", 0,
8126      "Option used by mysql-test for debugging and testing of replication.",
8127      &abort_slave_event_count, &abort_slave_event_count, nullptr, GET_INT,
8128      REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
8129     {"allow-suspicious-udfs", 0,
8130      "Allows use of UDFs consisting of only one symbol xxx() "
8131      "without corresponding xxx_init() or xxx_deinit(). That also means "
8132      "that one can load any function from any library, for example exit() "
8133      "from libc.so",
8134      &opt_allow_suspicious_udfs, &opt_allow_suspicious_udfs, nullptr, GET_BOOL,
8135      NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8136     {"ansi", 'a',
8137      "Use ANSI SQL syntax instead of MySQL syntax. This mode "
8138      "will also set transaction isolation level 'serializable'.",
8139      nullptr, nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0,
8140      nullptr},
8141     /*
8142       Because Sys_var_bit does not support command-line options, we need to
8143       explicitly add one for --autocommit
8144     */
8145     {"autocommit", 0, "Set default value for autocommit (0 or 1)",
8146      &opt_autocommit, &opt_autocommit, nullptr, GET_BOOL, OPT_ARG, 1, 0, 0,
8147      &source_autocommit, /* arg_source, to be copied to Sys_var */
8148      0, nullptr},
8149     {"binlog-do-db", OPT_BINLOG_DO_DB,
8150      "Tells the master it should log updates for the specified database, "
8151      "and exclude all others not explicitly mentioned.",
8152      nullptr, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8153      nullptr},
8154     {"binlog-ignore-db", OPT_BINLOG_IGNORE_DB,
8155      "Tells the master that updates to the given database should not be logged "
8156      "to the binary log.",
8157      nullptr, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8158      nullptr},
8159     {"character-set-client-handshake", 0,
8160      "Don't ignore client side character set value sent during handshake.",
8161      &opt_character_set_client_handshake, &opt_character_set_client_handshake,
8162      nullptr, GET_BOOL, NO_ARG, 1, 0, 0, nullptr, 0, nullptr},
8163     {"character-set-filesystem", 0, "Set the filesystem character set.",
8164      &character_set_filesystem_name, &character_set_filesystem_name, nullptr,
8165      GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
8166     {"character-set-server", 'C', "Set the default character set.",
8167      &default_character_set_name, &default_character_set_name, nullptr, GET_STR,
8168      REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
8169     {"chroot", 'r', "Chroot mysqld daemon during startup.", &mysqld_chroot,
8170      &mysqld_chroot, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8171      nullptr},
8172     {"collation-server", 0, "Set the default collation.",
8173      &default_collation_name, &default_collation_name, nullptr, GET_STR,
8174      REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
8175     {"console", OPT_CONSOLE,
8176      "Write error output on screen; don't remove the console window on "
8177      "windows.",
8178      &opt_console, &opt_console, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0,
8179      nullptr},
8180     {"core-file", OPT_WANT_CORE, "Write core on errors.", nullptr, nullptr,
8181      nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8182     /* default-storage-engine should have "MyISAM" as def_value. Instead
8183        of initializing it here it is done in init_common_variables() due
8184        to a compiler bug in Sun Studio compiler. */
8185     {"default-storage-engine", 0, "The default storage engine for new tables",
8186      &default_storage_engine, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0,
8187      nullptr, 0, nullptr},
8188     {"default-tmp-storage-engine", 0,
8189      "The default storage engine for new explicit temporary tables",
8190      &default_tmp_storage_engine, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0,
8191      0, nullptr, 0, nullptr},
8192     {"default-time-zone", 0, "Set the default time zone.", &default_tz_name,
8193      &default_tz_name, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8194      nullptr},
8195     {"disconnect-slave-event-count", 0,
8196      "Option used by mysql-test for debugging and testing of replication.",
8197      &disconnect_slave_event_count, &disconnect_slave_event_count, nullptr,
8198      GET_INT, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
8199     {"exit-info", 'T', "Used for debugging. Use at your own risk.", nullptr,
8200      nullptr, nullptr, GET_LONG, OPT_ARG, 0, 0, 0, nullptr, 0, nullptr},
8201 
8202     {"external-locking", 0,
8203      "Use system (external) locking (disabled by "
8204      "default).  With this option enabled you can run myisamchk to test "
8205      "(not repair) tables while the MySQL server is running. Disable with "
8206      "--skip-external-locking.",
8207      &opt_external_locking, &opt_external_locking, nullptr, GET_BOOL, NO_ARG, 0,
8208      0, 0, nullptr, 0, nullptr},
8209     /* We must always support the next option to make scripts like mysqltest
8210        easier to do */
8211     {"gdb", 0, "Set up signals usable for debugging.", &opt_debugging,
8212      &opt_debugging, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8213 #if defined(HAVE_LINUX_LARGE_PAGES) || defined(HAVE_SOLARIS_LARGE_PAGES)
8214     {"super-large-pages", 0, "Enable support for super large pages.",
8215      &opt_super_large_pages, &opt_super_large_pages, nullptr, GET_BOOL, OPT_ARG,
8216      0, 0, 1, nullptr, 1, nullptr},
8217 #endif
8218     {"language", 'L',
8219      "Client error messages in given language. May be given as a full path. "
8220      "Deprecated. Use --lc-messages-dir instead.",
8221      &lc_messages_dir_ptr, &lc_messages_dir_ptr, nullptr, GET_STR, REQUIRED_ARG,
8222      0, 0, 0, nullptr, 0, nullptr},
8223     {"lc-messages", 0, "Set the language used for the error messages.",
8224      &lc_messages, &lc_messages, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0,
8225      nullptr, 0, nullptr},
8226     {"lc-time-names", 0,
8227      "Set the language used for the month names and the days of the week.",
8228      &lc_time_names_name, &lc_time_names_name, nullptr, GET_STR, REQUIRED_ARG,
8229      0, 0, 0, nullptr, 0, nullptr},
8230     {"log-bin", OPT_BIN_LOG,
8231      "Configures the name prefix to use for binary log files. If the --log-bin "
8232      "option is not supplied, the name prefix defaults to \"binlog\". If the "
8233      "--log-bin option is supplied without argument, the name prefix defaults "
8234      "to \"HOSTNAME-bin\", where HOSTNAME is the machine's hostname. To set a "
8235      "different name prefix for binary log files, use --log-bin=name. To "
8236      "disable "
8237      "binary logging, use the --skip-log-bin or --disable-log-bin option.",
8238      &opt_bin_logname, &opt_bin_logname, nullptr, GET_STR_ALLOC, OPT_ARG, 0, 0,
8239      0, nullptr, 0, nullptr},
8240     {"log-bin-index", 0, "File that holds the names for binary log files.",
8241      &opt_binlog_index_name, &opt_binlog_index_name, nullptr, GET_STR,
8242      REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
8243     {"relay-log-index", 0, "File that holds the names for relay log files.",
8244      &opt_relaylog_index_name, &opt_relaylog_index_name, nullptr, GET_STR,
8245      REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
8246     {"log-isam", OPT_ISAM_LOG, "Log all MyISAM changes to file.",
8247      &myisam_log_filename, &myisam_log_filename, nullptr, GET_STR, OPT_ARG, 0,
8248      0, 0, nullptr, 0, nullptr},
8249     {"log-short-format", 0,
8250      "Don't log extra information to update and slow-query logs.",
8251      &opt_short_log_format, &opt_short_log_format, nullptr, GET_BOOL, NO_ARG, 0,
8252      0, 0, nullptr, 0, nullptr},
8253     {"log-tc", 0,
8254      "Path to transaction coordinator log (used for transactions that affect "
8255      "more than one storage engine, when binary log is disabled).",
8256      &opt_tc_log_file, &opt_tc_log_file, nullptr, GET_STR, REQUIRED_ARG, 0, 0,
8257      0, nullptr, 0, nullptr},
8258     {"log-tc-size", 0, "Size of transaction coordinator log.", &opt_tc_log_size,
8259      &opt_tc_log_size, nullptr, GET_ULONG, REQUIRED_ARG,
8260      TC_LOG_MIN_PAGES *my_getpagesize(), TC_LOG_MIN_PAGES *my_getpagesize(),
8261      ULONG_MAX, nullptr, my_getpagesize(), nullptr},
8262     {"master-info-file", OPT_MASTER_INFO_FILE,
8263      "The location and name of the file that remembers the master and where "
8264      "the I/O replication thread is in the master's binlogs. "
8265      "Deprecated option that shall be removed eventually without a "
8266      "replacement.",
8267      &master_info_file, &master_info_file, nullptr, GET_STR, REQUIRED_ARG, 0, 0,
8268      0, nullptr, 0, nullptr},
8269     {"master-retry-count", OPT_MASTER_RETRY_COUNT,
8270      "The number of tries the slave will make to connect to the master before "
8271      "giving up. "
8272      "Deprecated option, use 'CHANGE MASTER TO master_retry_count = <num>' "
8273      "instead.",
8274      &master_retry_count, &master_retry_count, nullptr, GET_ULONG, REQUIRED_ARG,
8275      3600 * 24, 0, 0, nullptr, 0, nullptr},
8276     {"max-binlog-dump-events", 0,
8277      "Option used by mysql-test for debugging and testing of replication.",
8278      &max_binlog_dump_events, &max_binlog_dump_events, nullptr, GET_INT,
8279      REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
8280     {"memlock", 0, "Lock mysqld in memory.", &locked_in_memory,
8281      &locked_in_memory, nullptr, GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0,
8282      nullptr},
8283     {"old-style-user-limits", 0,
8284      "Enable old-style user limits (before 5.0.3, user resources were counted "
8285      "per each user+host vs. per account).",
8286      &opt_old_style_user_limits, &opt_old_style_user_limits, nullptr, GET_BOOL,
8287      NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8288     {"port-open-timeout", 0,
8289      "Maximum time in seconds to wait for the port to become free. "
8290      "(Default: No wait).",
8291      &mysqld_port_timeout, &mysqld_port_timeout, nullptr, GET_UINT,
8292      REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
8293     {"replicate-do-db", OPT_REPLICATE_DO_DB,
8294      "Tells the slave thread to restrict replication to the specified "
8295      "database. "
8296      "To specify more than one database, use the directive multiple times, "
8297      "once for each database. Note that this will only work if you do not use "
8298      "cross-database queries such as UPDATE some_db.some_table SET foo='bar' "
8299      "while having selected a different or no database. If you need cross "
8300      "database updates to work, make sure you have 3.23.28 or later, and use "
8301      "replicate-wild-do-table=db_name.%.",
8302      nullptr, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8303      nullptr},
8304     {"replicate-do-table", OPT_REPLICATE_DO_TABLE,
8305      "Tells the slave thread to restrict replication to the specified table. "
8306      "To specify more than one table, use the directive multiple times, once "
8307      "for each table. This will work for cross-database updates, in contrast "
8308      "to replicate-do-db.",
8309      nullptr, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8310      nullptr},
8311     {"replicate-ignore-db", OPT_REPLICATE_IGNORE_DB,
8312      "Tells the slave thread to not replicate to the specified database. To "
8313      "specify more than one database to ignore, use the directive multiple "
8314      "times, once for each database. This option will not work if you use "
8315      "cross database updates. If you need cross database updates to work, "
8316      "make sure you have 3.23.28 or later, and use replicate-wild-ignore-"
8317      "table=db_name.%. ",
8318      nullptr, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8319      nullptr},
8320     {"replicate-ignore-table", OPT_REPLICATE_IGNORE_TABLE,
8321      "Tells the slave thread to not replicate to the specified table. To "
8322      "specify "
8323      "more than one table to ignore, use the directive multiple times, once "
8324      "for "
8325      "each table. This will work for cross-database updates, in contrast to "
8326      "replicate-ignore-db.",
8327      nullptr, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8328      nullptr},
8329     {"replicate-rewrite-db", OPT_REPLICATE_REWRITE_DB,
8330      "Updates to a database with a different name than the original. Example: "
8331      "replicate-rewrite-db=master_db_name->slave_db_name.",
8332      nullptr, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8333      nullptr},
8334     {"replicate-same-server-id", 0,
8335      "In replication, if set to 1, do not skip events having our server id. "
8336      "Default value is 0 (to break infinite loops in circular replication). "
8337      "Can't be set to 1 if --log-slave-updates is used.",
8338      &replicate_same_server_id, &replicate_same_server_id, nullptr, GET_BOOL,
8339      NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8340     {"replicate-wild-do-table", OPT_REPLICATE_WILD_DO_TABLE,
8341      "Tells the slave thread to restrict replication to the tables that match "
8342      "the specified wildcard pattern. To specify more than one table, use the "
8343      "directive multiple times, once for each table. This will work for cross-"
8344      "database updates. Example: replicate-wild-do-table=foo%.bar% will "
8345      "replicate only updates to tables in all databases that start with foo "
8346      "and whose table names start with bar.",
8347      nullptr, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8348      nullptr},
8349     {"replicate-wild-ignore-table", OPT_REPLICATE_WILD_IGNORE_TABLE,
8350      "Tells the slave thread to not replicate to the tables that match the "
8351      "given wildcard pattern. To specify more than one table to ignore, use "
8352      "the directive multiple times, once for each table. This will work for "
8353      "cross-database updates. Example: replicate-wild-ignore-table=foo%.bar% "
8354      "will not do updates to tables in databases that start with foo and whose "
8355      "table names start with bar.",
8356      nullptr, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8357      nullptr},
8358     {"safe-user-create", 0,
8359      "Don't allow new user creation by the user who has no write privileges to "
8360      "the mysql.user table.",
8361      &opt_safe_user_create, &opt_safe_user_create, nullptr, GET_BOOL, NO_ARG, 0,
8362      0, 0, nullptr, 0, nullptr},
8363     {"show-slave-auth-info", 0,
8364      "Show user and password in SHOW SLAVE HOSTS on this master.",
8365      &opt_show_slave_auth_info, &opt_show_slave_auth_info, nullptr, GET_BOOL,
8366      NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8367     {"skip-host-cache", OPT_SKIP_HOST_CACHE, "Don't cache host names.", nullptr,
8368      nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8369     {"skip-new", OPT_SKIP_NEW, "Don't use new, possibly wrong routines.",
8370      nullptr, nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0,
8371      nullptr},
8372     {"skip-slave-start", 0, "If set, slave is not autostarted.",
8373      &opt_skip_slave_start, &opt_skip_slave_start, nullptr, GET_BOOL, NO_ARG, 0,
8374      0, 0, nullptr, 0, nullptr},
8375     {"skip-stack-trace", OPT_SKIP_STACK_TRACE,
8376      "Don't print a stack trace on failure.", nullptr, nullptr, nullptr,
8377      GET_NO_ARG, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8378 #if defined(_WIN32)
8379     {"slow-start-timeout", 0,
8380      "Maximum number of milliseconds that the service control manager should "
8381      "wait "
8382      "before trying to kill the windows service during startup"
8383      "(Default: 15000).",
8384      &slow_start_timeout, &slow_start_timeout, 0, GET_ULONG, REQUIRED_ARG,
8385      15000, 0, 0, 0, 0, 0},
8386 #endif
8387     {"sporadic-binlog-dump-fail", 0,
8388      "Option used by mysql-test for debugging and testing of replication.",
8389      &opt_sporadic_binlog_dump_fail, &opt_sporadic_binlog_dump_fail, 0,
8390      GET_BOOL, NO_ARG, 0, 0, 0, nullptr, 0, nullptr},
8391 #ifndef XTRABACKUP
8392     {"ssl", 0,
8393      "Enable SSL for connection (automatically enabled with other flags).",
8394      &opt_use_ssl, &opt_use_ssl, nullptr, GET_BOOL, OPT_ARG, 1, 0, 0, nullptr,
8395      0, nullptr},
8396     {"admin-ssl", 0,
8397      "Enable SSL for admin interface (automatically enabled with other flags).",
8398      &opt_use_admin_ssl, &opt_use_admin_ssl, nullptr, GET_BOOL, OPT_ARG, 1, 0,
8399      0, nullptr, 0, nullptr},
8400 #endif /* XTRABACKUP */
8401 #ifdef _WIN32
8402     {"standalone", 0, "Dummy option to start as a standalone program (NT).", 0,
8403      0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
8404     {"no-monitor", 0, "Disable monitor process.", &opt_no_monitor,
8405      &opt_no_monitor, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
8406 #endif
8407     {"symbolic-links", 's',
8408      "Enable symbolic link support (deprecated and will be  removed in a future"
8409      " release).",
8410      &my_enable_symlinks, &my_enable_symlinks, nullptr, GET_BOOL, NO_ARG, 0, 0,
8411      0, nullptr, 0, nullptr},
8412     {"sysdate-is-now", 0,
8413      "Non-default option to alias SYSDATE() to NOW() to make it "
8414      "safe-replicable. "
8415      "Since 5.0, SYSDATE() returns a `dynamic' value different for different "
8416      "invocations, even within the same statement.",
8417      &global_system_variables.sysdate_is_now, nullptr, nullptr, GET_BOOL,
8418      NO_ARG, 0, 0, 1, nullptr, 1, nullptr},
8419     {"tc-heuristic-recover", 0,
8420      "Decision to use in heuristic recover process. Possible values are OFF, "
8421      "COMMIT or ROLLBACK.",
8422      &tc_heuristic_recover, &tc_heuristic_recover,
8423      &tc_heuristic_recover_typelib, GET_ENUM, REQUIRED_ARG,
8424      TC_HEURISTIC_NOT_USED, 0, 0, nullptr, 0, nullptr},
8425 #if defined(ENABLED_DEBUG_SYNC)
8426     {"debug-sync-timeout", OPT_DEBUG_SYNC_TIMEOUT,
8427      "Enable the debug sync facility "
8428      "and optionally specify a default wait timeout in seconds. "
8429      "A zero value keeps the facility disabled.",
8430      &opt_debug_sync_timeout, nullptr, nullptr, GET_UINT, OPT_ARG, 0, 0,
8431      UINT_MAX, nullptr, 0, nullptr},
8432 #endif /* defined(ENABLED_DEBUG_SYNC) */
8433     {"transaction-isolation", 0, "Default transaction isolation level.",
8434      &global_system_variables.transaction_isolation,
8435      &global_system_variables.transaction_isolation, &tx_isolation_typelib,
8436      GET_ENUM, REQUIRED_ARG, ISO_REPEATABLE_READ, 0, 0, nullptr, 0, nullptr},
8437     {"transaction-read-only", 0,
8438      "Default transaction access mode. "
8439      "True if transactions are read-only.",
8440      &global_system_variables.transaction_read_only,
8441      &global_system_variables.transaction_read_only, nullptr, GET_BOOL, OPT_ARG,
8442      0, 0, 0, nullptr, 0, nullptr},
8443     {"user", 'u', "Run mysqld daemon as user.", nullptr, nullptr, nullptr,
8444      GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0, nullptr},
8445     {"early-plugin-load", OPT_EARLY_PLUGIN_LOAD,
8446      "Optional semicolon-separated list of plugins to load before storage "
8447      "engine "
8448      "initialization, where each plugin is identified as name=library, where "
8449      "name is the plugin name and library is the plugin library in plugin_dir.",
8450      nullptr, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8451      nullptr},
8452     {"plugin-load", OPT_PLUGIN_LOAD,
8453      "Optional semicolon-separated list of plugins to load, where each plugin "
8454      "is "
8455      "identified as name=library, where name is the plugin name and library "
8456      "is the plugin library in plugin_dir.",
8457      nullptr, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8458      nullptr},
8459     {"plugin-load-add", OPT_PLUGIN_LOAD_ADD,
8460      "Optional semicolon-separated list of plugins to load, where each plugin "
8461      "is "
8462      "identified as name=library, where name is the plugin name and library "
8463      "is the plugin library in plugin_dir. This option adds to the list "
8464      "specified by --plugin-load in an incremental way. "
8465      "Multiple --plugin-load-add are supported.",
8466      nullptr, nullptr, nullptr, GET_STR, REQUIRED_ARG, 0, 0, 0, nullptr, 0,
8467      nullptr},
8468 
8469     {"innodb", OPT_SKIP_INNODB,
8470      "Deprecated option. Provided for backward compatibility only. "
8471      "The option has no effect on the server behaviour. InnoDB is always "
8472      "enabled. "
8473      "The option will be removed in a future release.",
8474      nullptr, nullptr, nullptr, GET_BOOL, OPT_ARG, 0, 0, 0, nullptr, 0,
8475      nullptr},
8476 
8477     {"upgrade", 0,
8478      "Set server upgrade mode. NONE to abort server if automatic upgrade of "
8479      "the server is needed; MINIMAL to start the server, but skip upgrade "
8480      "steps that are not absolutely necessary; AUTO (default) to upgrade the "
8481      "server if required; FORCE to force upgrade server.",
8482      &opt_upgrade_mode, &opt_upgrade_mode, &upgrade_mode_typelib, GET_ENUM,
8483      REQUIRED_ARG, UPGRADE_AUTO, 0, 0, nullptr, 0, nullptr},
8484 
8485     {nullptr, 0, nullptr, nullptr, nullptr, nullptr, GET_NO_ARG, NO_ARG, 0, 0,
8486      0, nullptr, 0, nullptr}};
8487 
show_queries(THD * thd,SHOW_VAR * var,char *)8488 static int show_queries(THD *thd, SHOW_VAR *var, char *) {
8489   var->type = SHOW_LONGLONG;
8490   var->value = (char *)&thd->query_id;
8491   return 0;
8492 }
8493 
show_net_compression(THD * thd,SHOW_VAR * var,char * buff)8494 static int show_net_compression(THD *thd, SHOW_VAR *var, char *buff) {
8495   var->type = SHOW_MY_BOOL;
8496   var->value = buff;
8497   *((bool *)buff) = thd->get_protocol()->get_compression();
8498   return 0;
8499 }
8500 
show_net_compression_algorithm(THD * thd,SHOW_VAR * var,char * buff)8501 static int show_net_compression_algorithm(THD *thd, SHOW_VAR *var, char *buff) {
8502   const char *s = thd->get_protocol()->get_compression_algorithm();
8503   var->type = SHOW_CHAR;
8504   var->value = buff;
8505   sprintf(buff, "%s", (s ? s : ""));
8506   return 0;
8507 }
8508 
show_net_compression_level(THD * thd,SHOW_VAR * var,char * buff)8509 static int show_net_compression_level(THD *thd, SHOW_VAR *var, char *buff) {
8510   var->type = SHOW_INT;
8511   var->value = buff;
8512   unsigned int *value = reinterpret_cast<unsigned int *>(buff);
8513   *value = thd->get_protocol()->get_compression_level();
8514   return 0;
8515 }
8516 
show_starttime(THD * thd,SHOW_VAR * var,char * buff)8517 static int show_starttime(THD *thd, SHOW_VAR *var, char *buff) {
8518   var->type = SHOW_LONGLONG;
8519   var->value = buff;
8520   *((longlong *)buff) =
8521       (longlong)(thd->query_start_in_secs() - server_start_time);
8522   return 0;
8523 }
8524 
show_max_used_connections_time(THD * thd,SHOW_VAR * var,char * buff)8525 static int show_max_used_connections_time(THD *thd, SHOW_VAR *var, char *buff) {
8526   MYSQL_TIME max_used_connections_time;
8527   var->type = SHOW_CHAR;
8528   var->value = buff;
8529   thd->variables.time_zone->gmt_sec_to_TIME(
8530       &max_used_connections_time,
8531       Connection_handler_manager::max_used_connections_time);
8532   my_datetime_to_str(max_used_connections_time, buff, 0);
8533   return 0;
8534 }
8535 
show_num_thread_running(THD *,SHOW_VAR * var,char * buff)8536 static int show_num_thread_running(THD *, SHOW_VAR *var, char *buff) {
8537   var->type = SHOW_LONGLONG;
8538   var->value = buff;
8539   long long *value = reinterpret_cast<long long *>(buff);
8540   *value = static_cast<long long>(
8541       Global_THD_manager::get_instance()->get_num_thread_running());
8542   return 0;
8543 }
8544 
show_num_thread_created(THD *,SHOW_VAR * var,char * buff)8545 static int show_num_thread_created(THD *, SHOW_VAR *var, char *buff) {
8546   var->type = SHOW_LONG;
8547   var->value = buff;
8548   long *value = reinterpret_cast<long *>(buff);
8549   *value = static_cast<long>(
8550       Global_THD_manager::get_instance()->get_num_thread_created());
8551   return 0;
8552 }
8553 
show_thread_id_count(THD *,SHOW_VAR * var,char * buff)8554 static int show_thread_id_count(THD *, SHOW_VAR *var, char *buff) {
8555   var->type = SHOW_LONG;
8556   var->value = buff;
8557   long *value = reinterpret_cast<long *>(buff);
8558   *value = static_cast<long>(
8559       Global_THD_manager::get_instance()->get_thread_id() - 1);
8560   return 0;
8561 }
8562 
show_aborted_connects(THD *,SHOW_VAR * var,char * buff)8563 static int show_aborted_connects(THD *, SHOW_VAR *var, char *buff) {
8564   var->type = SHOW_LONG;
8565   var->value = buff;
8566   long *value = reinterpret_cast<long *>(buff);
8567   *value = static_cast<long>(
8568       Connection_handler_manager::get_instance()->aborted_connects());
8569   return 0;
8570 }
8571 
show_acl_cache_items_count(THD *,SHOW_VAR * var,char * buff)8572 static int show_acl_cache_items_count(THD *, SHOW_VAR *var, char *buff) {
8573   var->type = SHOW_LONG;
8574   var->value = buff;
8575   long *value = reinterpret_cast<long *>(buff);
8576   *value = static_cast<long>(get_global_acl_cache_size());
8577   return 0;
8578 }
8579 
show_connection_errors_max_connection(THD *,SHOW_VAR * var,char * buff)8580 static int show_connection_errors_max_connection(THD *, SHOW_VAR *var,
8581                                                  char *buff) {
8582   var->type = SHOW_LONG;
8583   var->value = buff;
8584   long *value = reinterpret_cast<long *>(buff);
8585   *value = static_cast<long>(Connection_handler_manager::get_instance()
8586                                  ->connection_errors_max_connection());
8587   return 0;
8588 }
8589 
show_connection_errors_select(THD *,SHOW_VAR * var,char * buff)8590 static int show_connection_errors_select(THD *, SHOW_VAR *var, char *buff) {
8591   var->type = SHOW_LONG;
8592   var->value = buff;
8593   long *value = reinterpret_cast<long *>(buff);
8594   *value = static_cast<long>(get_connection_errors_select());
8595   return 0;
8596 }
8597 
show_connection_errors_accept(THD *,SHOW_VAR * var,char * buff)8598 static int show_connection_errors_accept(THD *, SHOW_VAR *var, char *buff) {
8599   var->type = SHOW_LONG;
8600   var->value = buff;
8601   long *value = reinterpret_cast<long *>(buff);
8602   *value = static_cast<long>(get_connection_errors_accept());
8603   return 0;
8604 }
8605 
show_connection_errors_tcpwrap(THD *,SHOW_VAR * var,char * buff)8606 static int show_connection_errors_tcpwrap(THD *, SHOW_VAR *var, char *buff) {
8607   var->type = SHOW_LONG;
8608   var->value = buff;
8609   long *value = reinterpret_cast<long *>(buff);
8610   *value = static_cast<long>(get_connection_errors_tcpwrap());
8611   return 0;
8612 }
8613 
8614 #ifdef ENABLED_PROFILING
show_flushstatustime(THD * thd,SHOW_VAR * var,char * buff)8615 static int show_flushstatustime(THD *thd, SHOW_VAR *var, char *buff) {
8616   var->type = SHOW_LONGLONG;
8617   var->value = buff;
8618   *((longlong *)buff) =
8619       (longlong)(thd->query_start_in_secs() - flush_status_time);
8620   return 0;
8621 }
8622 #endif
8623 
8624 /**
8625   After Multisource replication, this function only shows the value
8626   of default channel.
8627 
8628   To know the status of other channels, performance schema replication
8629   tables comes to the rescue.
8630 
8631   @todo  Any warning needed if multiple channels exist to request
8632          the users to start using replication performance schema
8633          tables.
8634 */
show_slave_running(THD *,SHOW_VAR * var,char * buff)8635 static int show_slave_running(THD *, SHOW_VAR *var, char *buff) {
8636   channel_map.rdlock();
8637   Master_info *mi = channel_map.get_default_channel_mi();
8638 
8639   if (mi) {
8640     var->type = SHOW_MY_BOOL;
8641     var->value = buff;
8642     *((bool *)buff) =
8643         (bool)(mi && mi->slave_running == MYSQL_SLAVE_RUN_CONNECT &&
8644                mi->rli->slave_running);
8645   } else
8646     var->type = SHOW_UNDEF;
8647 
8648   channel_map.unlock();
8649   return 0;
8650 }
8651 
8652 /**
8653   This status variable is also exclusively (look comments on
8654   show_slave_running()) for default channel.
8655 */
show_slave_retried_trans(THD *,SHOW_VAR * var,char * buff)8656 static int show_slave_retried_trans(THD *, SHOW_VAR *var, char *buff) {
8657   channel_map.rdlock();
8658   Master_info *mi = channel_map.get_default_channel_mi();
8659 
8660   if (mi) {
8661     var->type = SHOW_LONG;
8662     var->value = buff;
8663     *((long *)buff) = (long)mi->rli->retried_trans;
8664   } else
8665     var->type = SHOW_UNDEF;
8666 
8667   channel_map.unlock();
8668   return 0;
8669 }
8670 
8671 /**
8672   Only for default channel. Refer to comments on show_slave_running()
8673 */
show_slave_received_heartbeats(THD *,SHOW_VAR * var,char * buff)8674 static int show_slave_received_heartbeats(THD *, SHOW_VAR *var, char *buff) {
8675   channel_map.rdlock();
8676   Master_info *mi = channel_map.get_default_channel_mi();
8677 
8678   if (mi) {
8679     var->type = SHOW_LONGLONG;
8680     var->value = buff;
8681     *((longlong *)buff) = mi->received_heartbeats;
8682   } else
8683     var->type = SHOW_UNDEF;
8684 
8685   channel_map.unlock();
8686   return 0;
8687 }
8688 
8689 /**
8690   Only for default channel. Refer to comments on show_slave_running()
8691 */
show_slave_last_heartbeat(THD * thd,SHOW_VAR * var,char * buff)8692 static int show_slave_last_heartbeat(THD *thd, SHOW_VAR *var, char *buff) {
8693   MYSQL_TIME received_heartbeat_time;
8694 
8695   channel_map.rdlock();
8696   Master_info *mi = channel_map.get_default_channel_mi();
8697 
8698   if (mi) {
8699     var->type = SHOW_CHAR;
8700     var->value = buff;
8701     if (mi->last_heartbeat == 0)
8702       buff[0] = '\0';
8703     else {
8704       thd->variables.time_zone->gmt_sec_to_TIME(
8705           &received_heartbeat_time,
8706           static_cast<my_time_t>(mi->last_heartbeat / 1000000));
8707       my_datetime_to_str(received_heartbeat_time, buff, 0);
8708     }
8709   } else
8710     var->type = SHOW_UNDEF;
8711 
8712   channel_map.unlock();
8713   return 0;
8714 }
8715 
8716 /**
8717   Only for default channel. For details, refer to show_slave_running()
8718 */
show_heartbeat_period(THD *,SHOW_VAR * var,char * buff)8719 static int show_heartbeat_period(THD *, SHOW_VAR *var, char *buff) {
8720   channel_map.rdlock();
8721   Master_info *mi = channel_map.get_default_channel_mi();
8722 
8723   if (mi) {
8724     var->type = SHOW_CHAR;
8725     var->value = buff;
8726     sprintf(buff, "%.3f", mi->heartbeat_period);
8727   } else
8728     var->type = SHOW_UNDEF;
8729 
8730   channel_map.unlock();
8731   return 0;
8732 }
8733 
8734 #ifndef DBUG_OFF
show_slave_rows_last_search_algorithm_used(THD *,SHOW_VAR * var,char * buff)8735 static int show_slave_rows_last_search_algorithm_used(THD *, SHOW_VAR *var,
8736                                                       char *buff) {
8737   uint res = slave_rows_last_search_algorithm_used;
8738   const char *s =
8739       ((res == Rows_log_event::ROW_LOOKUP_TABLE_SCAN)
8740            ? "TABLE_SCAN"
8741            : ((res == Rows_log_event::ROW_LOOKUP_HASH_SCAN) ? "HASH_SCAN"
8742                                                             : "INDEX_SCAN"));
8743 
8744   var->type = SHOW_CHAR;
8745   var->value = buff;
8746   sprintf(buff, "%s", s);
8747 
8748   return 0;
8749 }
8750 
show_ongoing_automatic_gtid_violating_transaction_count(THD *,SHOW_VAR * var,char * buf)8751 static int show_ongoing_automatic_gtid_violating_transaction_count(
8752     THD *, SHOW_VAR *var, char *buf) {
8753   var->type = SHOW_CHAR;
8754   var->value = buf;
8755   sprintf(buf, "%d",
8756           gtid_state->get_automatic_gtid_violating_transaction_count());
8757   return 0;
8758 }
8759 
show_ongoing_anonymous_gtid_violating_transaction_count(THD *,SHOW_VAR * var,char * buf)8760 static int show_ongoing_anonymous_gtid_violating_transaction_count(
8761     THD *, SHOW_VAR *var, char *buf) {
8762   var->type = SHOW_CHAR;
8763   var->value = buf;
8764   sprintf(buf, "%d",
8765           gtid_state->get_anonymous_gtid_violating_transaction_count());
8766   return 0;
8767 }
8768 
8769 #endif
8770 
show_ongoing_anonymous_transaction_count(THD *,SHOW_VAR * var,char * buf)8771 static int show_ongoing_anonymous_transaction_count(THD *, SHOW_VAR *var,
8772                                                     char *buf) {
8773   var->type = SHOW_CHAR;
8774   var->value = buf;
8775   sprintf(buf, "%d", gtid_state->get_anonymous_ownership_count());
8776   return 0;
8777 }
8778 
show_open_tables(THD *,SHOW_VAR * var,char * buff)8779 static int show_open_tables(THD *, SHOW_VAR *var, char *buff) {
8780   var->type = SHOW_LONG;
8781   var->value = buff;
8782   *((long *)buff) = (long)table_cache_manager.cached_tables();
8783   return 0;
8784 }
8785 
show_prepared_stmt_count(THD *,SHOW_VAR * var,char * buff)8786 static int show_prepared_stmt_count(THD *, SHOW_VAR *var, char *buff) {
8787   var->type = SHOW_LONG;
8788   var->value = buff;
8789   mysql_mutex_lock(&LOCK_prepared_stmt_count);
8790   *((long *)buff) = (long)prepared_stmt_count;
8791   mysql_mutex_unlock(&LOCK_prepared_stmt_count);
8792   return 0;
8793 }
8794 
show_table_definitions(THD *,SHOW_VAR * var,char * buff)8795 static int show_table_definitions(THD *, SHOW_VAR *var, char *buff) {
8796   var->type = SHOW_LONG;
8797   var->value = buff;
8798   *((long *)buff) = (long)cached_table_definitions();
8799   return 0;
8800 }
8801 
8802 /*
8803    Functions relying on SSL
8804    Note: In the show_ssl_* functions, we need to check if we have a
8805          valid vio-object since this isn't always true, specifically
8806          when session_status or global_status is requested from
8807          inside an Event.
8808  */
show_ssl_get_version(THD * thd,SHOW_VAR * var,char *)8809 static int show_ssl_get_version(THD *thd, SHOW_VAR *var, char *) {
8810   SSL_handle ssl = thd->get_ssl();
8811   var->type = SHOW_CHAR;
8812   if (ssl)
8813     var->value = const_cast<char *>(SSL_get_version(ssl));
8814   else
8815     var->value = const_cast<char *>("");
8816   return 0;
8817 }
8818 
show_ssl_session_reused(THD * thd,SHOW_VAR * var,char * buff)8819 static int show_ssl_session_reused(THD *thd, SHOW_VAR *var, char *buff) {
8820   SSL_handle ssl = thd->get_ssl();
8821   var->type = SHOW_LONG;
8822   var->value = buff;
8823   if (ssl)
8824     *((long *)buff) = (long)SSL_session_reused(ssl);
8825   else
8826     *((long *)buff) = 0;
8827   return 0;
8828 }
8829 
show_ssl_get_default_timeout(THD * thd,SHOW_VAR * var,char * buff)8830 static int show_ssl_get_default_timeout(THD *thd, SHOW_VAR *var, char *buff) {
8831   SSL_handle ssl = thd->get_ssl();
8832   var->type = SHOW_LONG;
8833   var->value = buff;
8834   if (ssl)
8835     *((long *)buff) = (long)SSL_get_default_timeout(ssl);
8836   else
8837     *((long *)buff) = 0;
8838   return 0;
8839 }
8840 
show_ssl_get_verify_mode(THD * thd,SHOW_VAR * var,char * buff)8841 static int show_ssl_get_verify_mode(THD *thd, SHOW_VAR *var, char *buff) {
8842   SSL_handle ssl = thd->get_ssl();
8843   var->type = SHOW_LONG;
8844   var->value = buff;
8845   if (ssl)
8846     *((long *)buff) = (long)SSL_get_verify_mode(ssl);
8847   else
8848     *((long *)buff) = 0;
8849   return 0;
8850 }
8851 
show_ssl_get_verify_depth(THD * thd,SHOW_VAR * var,char * buff)8852 static int show_ssl_get_verify_depth(THD *thd, SHOW_VAR *var, char *buff) {
8853   SSL_handle ssl = thd->get_ssl();
8854   var->type = SHOW_LONG;
8855   var->value = buff;
8856   if (ssl)
8857     *((long *)buff) = (long)SSL_get_verify_depth(ssl);
8858   else
8859     *((long *)buff) = 0;
8860   return 0;
8861 }
8862 
show_ssl_get_cipher(THD * thd,SHOW_VAR * var,char *)8863 static int show_ssl_get_cipher(THD *thd, SHOW_VAR *var, char *) {
8864   SSL_handle ssl = thd->get_ssl();
8865   var->type = SHOW_CHAR;
8866   if (ssl)
8867     var->value = const_cast<char *>(SSL_get_cipher(ssl));
8868   else
8869     var->value = const_cast<char *>("");
8870   return 0;
8871 }
8872 
show_ssl_get_cipher_list(THD * thd,SHOW_VAR * var,char * buff)8873 static int show_ssl_get_cipher_list(THD *thd, SHOW_VAR *var, char *buff) {
8874   SSL_handle ssl = thd->get_ssl();
8875   var->type = SHOW_CHAR;
8876   var->value = buff;
8877   if (ssl) {
8878     int i;
8879     const char *p;
8880     char *end = buff + SHOW_VAR_FUNC_BUFF_SIZE;
8881     for (i = 0; (p = SSL_get_cipher_list(ssl, i)) && buff < end; i++) {
8882       buff = my_stpnmov(buff, p, end - buff - 1);
8883       *buff++ = ':';
8884     }
8885     if (i) buff--;
8886   }
8887   *buff = 0;
8888   return 0;
8889 }
8890 
show_slave_open_temp_tables(THD *,SHOW_VAR * var,char * buf)8891 static int show_slave_open_temp_tables(THD *, SHOW_VAR *var, char *buf) {
8892   var->type = SHOW_INT;
8893   var->value = buf;
8894   *((int *)buf) = atomic_slave_open_temp_tables;
8895   return 0;
8896 }
8897 
8898 /*
8899   Variables shown by SHOW STATUS in alphabetical order
8900 */
8901 
8902 SHOW_VAR status_vars[] = {
8903     {"Aborted_clients", (char *)&aborted_threads, SHOW_LONG, SHOW_SCOPE_GLOBAL},
8904     {"Aborted_connects", (char *)&show_aborted_connects, SHOW_FUNC,
8905      SHOW_SCOPE_GLOBAL},
8906     {"Acl_cache_items_count", (char *)&show_acl_cache_items_count, SHOW_FUNC,
8907      SHOW_SCOPE_GLOBAL},
8908 #ifndef DBUG_OFF
8909     {"Ongoing_anonymous_gtid_violating_transaction_count",
8910      (char *)&show_ongoing_anonymous_gtid_violating_transaction_count,
8911      SHOW_FUNC, SHOW_SCOPE_GLOBAL},
8912 #endif  //! DBUG_OFF
8913     {"Ongoing_anonymous_transaction_count",
8914      (char *)&show_ongoing_anonymous_transaction_count, SHOW_FUNC,
8915      SHOW_SCOPE_GLOBAL},
8916 #ifndef DBUG_OFF
8917     {"Ongoing_automatic_gtid_violating_transaction_count",
8918      (char *)&show_ongoing_automatic_gtid_violating_transaction_count,
8919      SHOW_FUNC, SHOW_SCOPE_GLOBAL},
8920 #endif  //! DBUG_OFF
8921     {"Binlog_cache_disk_use", (char *)&binlog_cache_disk_use, SHOW_LONG,
8922      SHOW_SCOPE_GLOBAL},
8923     {"Binlog_cache_use", (char *)&binlog_cache_use, SHOW_LONG,
8924      SHOW_SCOPE_GLOBAL},
8925     {"Binlog_stmt_cache_disk_use", (char *)&binlog_stmt_cache_disk_use,
8926      SHOW_LONG, SHOW_SCOPE_GLOBAL},
8927     {"Binlog_stmt_cache_use", (char *)&binlog_stmt_cache_use, SHOW_LONG,
8928      SHOW_SCOPE_GLOBAL},
8929     {"Bytes_received", (char *)offsetof(System_status_var, bytes_received),
8930      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8931     {"Bytes_sent", (char *)offsetof(System_status_var, bytes_sent),
8932      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8933     {"Com", (char *)com_status_vars, SHOW_ARRAY, SHOW_SCOPE_ALL},
8934     {"Com_stmt_reprepare",
8935      (char *)offsetof(System_status_var, com_stmt_reprepare), SHOW_LONG_STATUS,
8936      SHOW_SCOPE_ALL},
8937     {"Compression", (char *)&show_net_compression, SHOW_FUNC,
8938      SHOW_SCOPE_SESSION},
8939     {"Compression_algorithm", (char *)&show_net_compression_algorithm,
8940      SHOW_FUNC, SHOW_SCOPE_SESSION},
8941     {"Compression_level", (char *)&show_net_compression_level, SHOW_FUNC,
8942      SHOW_SCOPE_SESSION},
8943     {"Connections", (char *)&show_thread_id_count, SHOW_FUNC,
8944      SHOW_SCOPE_GLOBAL},
8945     {"Connection_errors_accept", (char *)&show_connection_errors_accept,
8946      SHOW_FUNC, SHOW_SCOPE_GLOBAL},
8947     {"Connection_errors_internal", (char *)&connection_errors_internal,
8948      SHOW_LONG, SHOW_SCOPE_GLOBAL},
8949     {"Connection_errors_max_connections",
8950      (char *)&show_connection_errors_max_connection, SHOW_FUNC,
8951      SHOW_SCOPE_GLOBAL},
8952     {"Connection_errors_peer_address", (char *)&connection_errors_peer_addr,
8953      SHOW_LONG, SHOW_SCOPE_GLOBAL},
8954     {"Connection_errors_select", (char *)&show_connection_errors_select,
8955      SHOW_FUNC, SHOW_SCOPE_GLOBAL},
8956     {"Connection_errors_tcpwrap", (char *)&show_connection_errors_tcpwrap,
8957      SHOW_FUNC, SHOW_SCOPE_GLOBAL},
8958     {"Created_tmp_disk_tables",
8959      (char *)offsetof(System_status_var, created_tmp_disk_tables),
8960      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8961     {"Created_tmp_files", (char *)&my_tmp_file_created, SHOW_LONG,
8962      SHOW_SCOPE_GLOBAL},
8963     {"Created_tmp_tables",
8964      (char *)offsetof(System_status_var, created_tmp_tables),
8965      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8966     {"Delayed_errors", (char *)&delayed_insert_errors, SHOW_LONG,
8967      SHOW_SCOPE_GLOBAL},
8968     {"Delayed_insert_threads", (char *)&delayed_insert_threads,
8969      SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
8970     {"Delayed_writes", (char *)&delayed_insert_writes, SHOW_LONG,
8971      SHOW_SCOPE_GLOBAL},
8972     {"Flush_commands", (char *)&refresh_version, SHOW_LONG_NOFLUSH,
8973      SHOW_SCOPE_GLOBAL},
8974     {"Handler_commit", (char *)offsetof(System_status_var, ha_commit_count),
8975      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8976     {"Handler_delete", (char *)offsetof(System_status_var, ha_delete_count),
8977      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8978     {"Handler_discover", (char *)offsetof(System_status_var, ha_discover_count),
8979      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8980     {"Handler_external_lock",
8981      (char *)offsetof(System_status_var, ha_external_lock_count),
8982      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8983     {"Handler_mrr_init",
8984      (char *)offsetof(System_status_var, ha_multi_range_read_init_count),
8985      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8986     {"Handler_prepare", (char *)offsetof(System_status_var, ha_prepare_count),
8987      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8988     {"Handler_read_first",
8989      (char *)offsetof(System_status_var, ha_read_first_count),
8990      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8991     {"Handler_read_key", (char *)offsetof(System_status_var, ha_read_key_count),
8992      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8993     {"Handler_read_last",
8994      (char *)offsetof(System_status_var, ha_read_last_count),
8995      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8996     {"Handler_read_next",
8997      (char *)offsetof(System_status_var, ha_read_next_count),
8998      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
8999     {"Handler_read_prev",
9000      (char *)offsetof(System_status_var, ha_read_prev_count),
9001      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9002     {"Handler_read_rnd", (char *)offsetof(System_status_var, ha_read_rnd_count),
9003      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9004     {"Handler_read_rnd_next",
9005      (char *)offsetof(System_status_var, ha_read_rnd_next_count),
9006      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9007     {"Handler_rollback", (char *)offsetof(System_status_var, ha_rollback_count),
9008      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9009     {"Handler_savepoint",
9010      (char *)offsetof(System_status_var, ha_savepoint_count),
9011      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9012     {"Handler_savepoint_rollback",
9013      (char *)offsetof(System_status_var, ha_savepoint_rollback_count),
9014      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9015     {"Handler_update", (char *)offsetof(System_status_var, ha_update_count),
9016      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9017     {"Handler_write", (char *)offsetof(System_status_var, ha_write_count),
9018      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9019     {"Key_blocks_not_flushed",
9020      (char *)offsetof(KEY_CACHE, global_blocks_changed), SHOW_KEY_CACHE_LONG,
9021      SHOW_SCOPE_GLOBAL},
9022     {"Key_blocks_unused", (char *)offsetof(KEY_CACHE, blocks_unused),
9023      SHOW_KEY_CACHE_LONG, SHOW_SCOPE_GLOBAL},
9024     {"Key_blocks_used", (char *)offsetof(KEY_CACHE, blocks_used),
9025      SHOW_KEY_CACHE_LONG, SHOW_SCOPE_GLOBAL},
9026     {"Key_read_requests", (char *)offsetof(KEY_CACHE, global_cache_r_requests),
9027      SHOW_KEY_CACHE_LONGLONG, SHOW_SCOPE_GLOBAL},
9028     {"Key_reads", (char *)offsetof(KEY_CACHE, global_cache_read),
9029      SHOW_KEY_CACHE_LONGLONG, SHOW_SCOPE_GLOBAL},
9030     {"Key_write_requests", (char *)offsetof(KEY_CACHE, global_cache_w_requests),
9031      SHOW_KEY_CACHE_LONGLONG, SHOW_SCOPE_GLOBAL},
9032     {"Key_writes", (char *)offsetof(KEY_CACHE, global_cache_write),
9033      SHOW_KEY_CACHE_LONGLONG, SHOW_SCOPE_GLOBAL},
9034     {"Last_query_cost", (char *)offsetof(System_status_var, last_query_cost),
9035      SHOW_DOUBLE_STATUS, SHOW_SCOPE_SESSION},
9036     {"Last_query_partial_plans",
9037      (char *)offsetof(System_status_var, last_query_partial_plans),
9038      SHOW_LONGLONG_STATUS, SHOW_SCOPE_SESSION},
9039     {"Locked_connects", (char *)&locked_account_connection_count, SHOW_LONG,
9040      SHOW_SCOPE_GLOBAL},
9041     {"Max_execution_time_exceeded",
9042      (char *)offsetof(System_status_var, max_execution_time_exceeded),
9043      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9044     {"Max_execution_time_set",
9045      (char *)offsetof(System_status_var, max_execution_time_set),
9046      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9047     {"Max_execution_time_set_failed",
9048      (char *)offsetof(System_status_var, max_execution_time_set_failed),
9049      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9050     {"Max_used_connections",
9051      (char *)&Connection_handler_manager::max_used_connections, SHOW_LONG,
9052      SHOW_SCOPE_GLOBAL},
9053     {"Max_used_connections_time", (char *)&show_max_used_connections_time,
9054      SHOW_FUNC, SHOW_SCOPE_GLOBAL},
9055     {"Not_flushed_delayed_rows", (char *)&delayed_rows_in_use,
9056      SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
9057     {"Open_files", (char *)&my_file_opened, SHOW_LONG_NOFLUSH,
9058      SHOW_SCOPE_GLOBAL},
9059     {"Open_streams", (char *)&my_stream_opened, SHOW_LONG_NOFLUSH,
9060      SHOW_SCOPE_GLOBAL},
9061     {"Open_table_definitions", (char *)&show_table_definitions, SHOW_FUNC,
9062      SHOW_SCOPE_GLOBAL},
9063     {"Open_tables", (char *)&show_open_tables, SHOW_FUNC, SHOW_SCOPE_ALL},
9064     {"Opened_files",
9065      const_cast<char *>(reinterpret_cast<const char *>(&my_file_total_opened)),
9066      SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
9067     {"Opened_tables", (char *)offsetof(System_status_var, opened_tables),
9068      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9069     {"Opened_table_definitions",
9070      (char *)offsetof(System_status_var, opened_shares), SHOW_LONGLONG_STATUS,
9071      SHOW_SCOPE_ALL},
9072     {"Prepared_stmt_count", (char *)&show_prepared_stmt_count, SHOW_FUNC,
9073      SHOW_SCOPE_GLOBAL},
9074     {"Queries", (char *)&show_queries, SHOW_FUNC, SHOW_SCOPE_ALL},
9075     {"Questions", (char *)offsetof(System_status_var, questions),
9076      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9077     {"Secondary_engine_execution_count",
9078      (char *)offsetof(System_status_var, secondary_engine_execution_count),
9079      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9080     {"Select_full_join",
9081      (char *)offsetof(System_status_var, select_full_join_count),
9082      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9083     {"Select_full_range_join",
9084      (char *)offsetof(System_status_var, select_full_range_join_count),
9085      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9086     {"Select_range", (char *)offsetof(System_status_var, select_range_count),
9087      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9088     {"Select_range_check",
9089      (char *)offsetof(System_status_var, select_range_check_count),
9090      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9091     {"Select_scan", (char *)offsetof(System_status_var, select_scan_count),
9092      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9093     {"Slave_open_temp_tables", (char *)&show_slave_open_temp_tables, SHOW_FUNC,
9094      SHOW_SCOPE_GLOBAL},
9095     {"Slave_retried_transactions", (char *)&show_slave_retried_trans, SHOW_FUNC,
9096      SHOW_SCOPE_GLOBAL},
9097     {"Slave_heartbeat_period", (char *)&show_heartbeat_period, SHOW_FUNC,
9098      SHOW_SCOPE_GLOBAL},
9099     {"Slave_received_heartbeats", (char *)&show_slave_received_heartbeats,
9100      SHOW_FUNC, SHOW_SCOPE_GLOBAL},
9101     {"Slave_last_heartbeat", (char *)&show_slave_last_heartbeat, SHOW_FUNC,
9102      SHOW_SCOPE_GLOBAL},
9103 #ifndef DBUG_OFF
9104     {"Slave_rows_last_search_algorithm_used",
9105      (char *)&show_slave_rows_last_search_algorithm_used, SHOW_FUNC,
9106      SHOW_SCOPE_GLOBAL},
9107 #endif
9108     {"Slave_running", (char *)&show_slave_running, SHOW_FUNC,
9109      SHOW_SCOPE_GLOBAL},
9110     {"Slow_launch_threads",
9111      (char *)&Per_thread_connection_handler::slow_launch_threads, SHOW_LONG,
9112      SHOW_SCOPE_ALL},
9113     {"Slow_queries", (char *)offsetof(System_status_var, long_query_count),
9114      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9115     {"Sort_merge_passes",
9116      (char *)offsetof(System_status_var, filesort_merge_passes),
9117      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9118     {"Sort_range", (char *)offsetof(System_status_var, filesort_range_count),
9119      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9120     {"Sort_rows", (char *)offsetof(System_status_var, filesort_rows),
9121      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9122     {"Sort_scan", (char *)offsetof(System_status_var, filesort_scan_count),
9123      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9124     {"Ssl_accept_renegotiates",
9125      (char *)&Ssl_mysql_main_status::show_ssl_ctx_sess_accept_renegotiate,
9126      SHOW_FUNC, SHOW_SCOPE_GLOBAL},
9127     {"Ssl_accepts", (char *)&Ssl_mysql_main_status::show_ssl_ctx_sess_accept,
9128      SHOW_FUNC, SHOW_SCOPE_GLOBAL},
9129     {"Ssl_callback_cache_hits",
9130      (char *)&Ssl_mysql_main_status::show_ssl_ctx_sess_cb_hits, SHOW_FUNC,
9131      SHOW_SCOPE_GLOBAL},
9132     {"Ssl_cipher", (char *)&show_ssl_get_cipher, SHOW_FUNC, SHOW_SCOPE_ALL},
9133     {"Ssl_cipher_list", (char *)&show_ssl_get_cipher_list, SHOW_FUNC,
9134      SHOW_SCOPE_ALL},
9135     {"Ssl_client_connects",
9136      (char *)&Ssl_mysql_main_status::show_ssl_ctx_sess_connect, SHOW_FUNC,
9137      SHOW_SCOPE_GLOBAL},
9138     {"Ssl_connect_renegotiates",
9139      (char *)&Ssl_mysql_main_status::show_ssl_ctx_sess_connect_renegotiate,
9140      SHOW_FUNC, SHOW_SCOPE_GLOBAL},
9141     {"Ssl_ctx_verify_depth",
9142      (char *)&Ssl_mysql_main_status::show_ssl_ctx_get_verify_depth, SHOW_FUNC,
9143      SHOW_SCOPE_GLOBAL},
9144     {"Ssl_ctx_verify_mode",
9145      (char *)&Ssl_mysql_main_status::show_ssl_ctx_get_verify_mode, SHOW_FUNC,
9146      SHOW_SCOPE_GLOBAL},
9147     {"Ssl_default_timeout", (char *)&show_ssl_get_default_timeout, SHOW_FUNC,
9148      SHOW_SCOPE_ALL},
9149     {"Ssl_finished_accepts",
9150      (char *)&Ssl_mysql_main_status::show_ssl_ctx_sess_accept_good, SHOW_FUNC,
9151      SHOW_SCOPE_GLOBAL},
9152     {"Ssl_finished_connects",
9153      (char *)&Ssl_mysql_main_status::show_ssl_ctx_sess_connect_good, SHOW_FUNC,
9154      SHOW_SCOPE_GLOBAL},
9155     {"Ssl_session_cache_hits",
9156      (char *)&Ssl_mysql_main_status::show_ssl_ctx_sess_hits, SHOW_FUNC,
9157      SHOW_SCOPE_GLOBAL},
9158     {"Ssl_session_cache_misses",
9159      (char *)&Ssl_mysql_main_status::show_ssl_ctx_sess_misses, SHOW_FUNC,
9160      SHOW_SCOPE_GLOBAL},
9161     {"Ssl_session_cache_mode",
9162      (char *)&Ssl_mysql_main_status::show_ssl_ctx_get_session_cache_mode,
9163      SHOW_FUNC, SHOW_SCOPE_GLOBAL},
9164     {"Ssl_session_cache_overflows",
9165      (char *)&Ssl_mysql_main_status::show_ssl_ctx_sess_cache_full, SHOW_FUNC,
9166      SHOW_SCOPE_GLOBAL},
9167     {"Ssl_session_cache_size",
9168      (char *)&Ssl_mysql_main_status::show_ssl_ctx_sess_get_cache_size,
9169      SHOW_FUNC, SHOW_SCOPE_GLOBAL},
9170     {"Ssl_session_cache_timeouts",
9171      (char *)&Ssl_mysql_main_status::show_ssl_ctx_sess_timeouts, SHOW_FUNC,
9172      SHOW_SCOPE_GLOBAL},
9173     {"Ssl_sessions_reused", (char *)&show_ssl_session_reused, SHOW_FUNC,
9174      SHOW_SCOPE_ALL},
9175     {"Ssl_used_session_cache_entries",
9176      (char *)&Ssl_mysql_main_status::show_ssl_ctx_sess_number, SHOW_FUNC,
9177      SHOW_SCOPE_GLOBAL},
9178     {"Ssl_verify_depth", (char *)&show_ssl_get_verify_depth, SHOW_FUNC,
9179      SHOW_SCOPE_ALL},
9180     {"Ssl_verify_mode", (char *)&show_ssl_get_verify_mode, SHOW_FUNC,
9181      SHOW_SCOPE_ALL},
9182     {"Ssl_version", (char *)&show_ssl_get_version, SHOW_FUNC, SHOW_SCOPE_ALL},
9183     {"Ssl_server_not_before",
9184      (char *)&Ssl_mysql_main_status::show_ssl_get_server_not_before, SHOW_FUNC,
9185      SHOW_SCOPE_ALL},
9186     {"Ssl_server_not_after",
9187      (char *)&Ssl_mysql_main_status::show_ssl_get_server_not_after, SHOW_FUNC,
9188      SHOW_SCOPE_ALL},
9189     {"Current_tls_ca", (char *)&Ssl_mysql_main_status::show_ssl_get_ssl_ca,
9190      SHOW_FUNC, SHOW_SCOPE_GLOBAL},
9191     {"Current_tls_capath",
9192      (char *)&Ssl_mysql_main_status::show_ssl_get_ssl_capath, SHOW_FUNC,
9193      SHOW_SCOPE_GLOBAL},
9194     {"Current_tls_cert", (char *)&Ssl_mysql_main_status::show_ssl_get_ssl_cert,
9195      SHOW_FUNC, SHOW_SCOPE_GLOBAL},
9196     {"Current_tls_key", (char *)&Ssl_mysql_main_status::show_ssl_get_ssl_key,
9197      SHOW_FUNC, SHOW_SCOPE_GLOBAL},
9198     {"Current_tls_version",
9199      (char *)&Ssl_mysql_main_status::show_ssl_get_tls_version, SHOW_FUNC,
9200      SHOW_SCOPE_GLOBAL},
9201     {"Current_tls_cipher",
9202      (char *)&Ssl_mysql_main_status::show_ssl_get_ssl_cipher, SHOW_FUNC,
9203      SHOW_SCOPE_GLOBAL},
9204     {"Current_tls_ciphersuites",
9205      (char *)&Ssl_mysql_main_status::show_ssl_get_tls_ciphersuites, SHOW_FUNC,
9206      SHOW_SCOPE_GLOBAL},
9207     {"Current_tls_crl", (char *)&Ssl_mysql_main_status::show_ssl_get_ssl_crl,
9208      SHOW_FUNC, SHOW_SCOPE_GLOBAL},
9209     {"Current_tls_crlpath",
9210      (char *)&Ssl_mysql_main_status::show_ssl_get_ssl_crlpath, SHOW_FUNC,
9211      SHOW_SCOPE_GLOBAL},
9212     {"Rsa_public_key", (char *)&show_rsa_public_key, SHOW_FUNC,
9213      SHOW_SCOPE_GLOBAL},
9214     {"Table_locks_immediate", (char *)&locks_immediate, SHOW_LONG,
9215      SHOW_SCOPE_GLOBAL},
9216     {"Table_locks_waited", (char *)&locks_waited, SHOW_LONG, SHOW_SCOPE_GLOBAL},
9217     {"Table_open_cache_hits",
9218      (char *)offsetof(System_status_var, table_open_cache_hits),
9219      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9220     {"Table_open_cache_misses",
9221      (char *)offsetof(System_status_var, table_open_cache_misses),
9222      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9223     {"Table_open_cache_overflows",
9224      (char *)offsetof(System_status_var, table_open_cache_overflows),
9225      SHOW_LONGLONG_STATUS, SHOW_SCOPE_ALL},
9226     {"Tc_log_max_pages_used", (char *)&tc_log_max_pages_used, SHOW_LONG,
9227      SHOW_SCOPE_GLOBAL},
9228     {"Tc_log_page_size", (char *)&tc_log_page_size, SHOW_LONG_NOFLUSH,
9229      SHOW_SCOPE_GLOBAL},
9230     {"Tc_log_page_waits", (char *)&tc_log_page_waits, SHOW_LONG,
9231      SHOW_SCOPE_GLOBAL},
9232     {"Threads_cached",
9233      (char *)&Per_thread_connection_handler::blocked_pthread_count,
9234      SHOW_LONG_NOFLUSH, SHOW_SCOPE_GLOBAL},
9235     {"Threads_connected", (char *)&Connection_handler_manager::connection_count,
9236      SHOW_INT, SHOW_SCOPE_GLOBAL},
9237     {"Threads_created", (char *)&show_num_thread_created, SHOW_FUNC,
9238      SHOW_SCOPE_GLOBAL},
9239     {"Threads_running", (char *)&show_num_thread_running, SHOW_FUNC,
9240      SHOW_SCOPE_GLOBAL},
9241     {"Uptime", (char *)&show_starttime, SHOW_FUNC, SHOW_SCOPE_GLOBAL},
9242 #ifdef ENABLED_PROFILING
9243     {"Uptime_since_flush_status", (char *)&show_flushstatustime, SHOW_FUNC,
9244      SHOW_SCOPE_GLOBAL},
9245 #endif
9246     {NullS, NullS, SHOW_LONG, SHOW_SCOPE_ALL}};
9247 
add_terminator(vector<my_option> * options)9248 void add_terminator(vector<my_option> *options) {
9249   my_option empty_element = {nullptr, 0,          nullptr, nullptr, nullptr,
9250                              nullptr, GET_NO_ARG, NO_ARG,  0,       0,
9251                              0,       nullptr,    0,       nullptr};
9252   options->push_back(empty_element);
9253 }
9254 
print_server_version(void)9255 static void print_server_version(void) {
9256   set_server_version();
9257 
9258   print_explicit_version(server_version);
9259 }
9260 
9261 /** Compares two options' names, treats - and _ the same */
operator <(const my_option & a,const my_option & b)9262 static bool operator<(const my_option &a, const my_option &b) {
9263   const char *sa = a.name;
9264   const char *sb = b.name;
9265   for (; *sa || *sb; sa++, sb++) {
9266     if (*sa < *sb) {
9267       if (*sa == '-' && *sb == '_')
9268         continue;
9269       else
9270         return true;
9271     }
9272     if (*sa > *sb) {
9273       if (*sa == '_' && *sb == '-')
9274         continue;
9275       else
9276         return false;
9277     }
9278   }
9279   DBUG_ASSERT(a.name == b.name);
9280   return false;
9281 }
9282 
print_help()9283 static void print_help() {
9284   MEM_ROOT mem_root;
9285   init_alloc_root(key_memory_help, &mem_root, 4096, 4096);
9286 
9287   all_options.pop_back();
9288   sys_var_add_options(&all_options, sys_var::PARSE_EARLY);
9289   for (my_option *opt = my_long_early_options; opt->name != nullptr; opt++) {
9290     all_options.push_back(*opt);
9291   }
9292   add_plugin_options(&all_options, &mem_root);
9293   std::sort(all_options.begin(), all_options.end(), std::less<my_option>());
9294   add_terminator(&all_options);
9295 
9296   my_print_help(&all_options[0]);
9297   my_print_variables(&all_options[0]);
9298 
9299   free_root(&mem_root, MYF(0));
9300   vector<my_option>().swap(all_options);  // Deletes the vector contents.
9301 }
9302 
usage(void)9303 static void usage(void) {
9304   DBUG_TRACE;
9305   if (!(default_charset_info = get_charset_by_csname(
9306             default_character_set_name, MY_CS_PRIMARY, MYF(MY_WME))))
9307     exit(MYSQLD_ABORT_EXIT);
9308   if (!default_collation_name)
9309     default_collation_name = default_charset_info->name;
9310   if (is_help_or_validate_option() || opt_verbose) {
9311     my_progname = my_progname + dirname_length(my_progname);
9312   }
9313   print_server_version();
9314   puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
9315   puts("Starts the MySQL database server.\n");
9316   printf("Usage: %s [OPTIONS]\n", my_progname);
9317   if (!opt_verbose)
9318     puts(
9319         "\nFor more help options (several pages), use mysqld --verbose "
9320         "--help.");
9321   else {
9322 #ifdef _WIN32
9323     puts(
9324         "NT and Win32 specific options:\n\
9325   --install                     Install the default service (NT).\n\
9326   --install-manual              Install the default service started manually (NT).\n\
9327   --install service_name        Install an optional service (NT).\n\
9328   --install-manual service_name Install an optional service started manually (NT).\n\
9329   --remove                      Remove the default service from the service list (NT).\n\
9330   --remove service_name         Remove the service_name from the service list (NT).\n\
9331   --enable-named-pipe           Only to be used for the default server (NT).\n\
9332   --standalone                  Dummy option to start as a standalone server (NT).\
9333 ");
9334     puts("");
9335 #endif
9336     print_defaults(MYSQL_CONFIG_NAME, load_default_groups);
9337     puts("");
9338     set_ports();
9339 
9340     /* Print out all the options including plugin supplied options */
9341     print_help();
9342 
9343     if (!dynamic_plugins_are_initialized) {
9344       puts(
9345           "\n\
9346 Plugins have parameters that are not reflected in this list\n\
9347 because execution stopped before plugins were initialized.");
9348     }
9349 
9350     puts(
9351         "\n\
9352 To see what values a running MySQL server is using, type\n\
9353 'mysqladmin variables' instead of 'mysqld --verbose --help'.");
9354   }
9355 }
9356 
9357 /**
9358   Initialize MySQL global variables to default values.
9359 
9360   @note
9361     The reason to set a lot of global variables to zero is that
9362     on some exotic platforms global variables are
9363     not set to 0 when a program starts.
9364 
9365     We don't need to set variables refered to in my_long_options
9366     as these are initialized by my_getopt.
9367 */
9368 
mysql_init_variables()9369 static int mysql_init_variables() {
9370   /* Things reset to zero */
9371   opt_skip_slave_start = false;
9372   pidfile_name[0] = 0;
9373   myisam_test_invalid_symlink = test_if_data_home_dir;
9374   opt_general_log = opt_slow_log = false;
9375   opt_disable_networking = opt_skip_show_db = false;
9376   opt_skip_name_resolve = false;
9377   opt_general_logname = opt_binlog_index_name = opt_slow_logname = nullptr;
9378   opt_tc_log_file = "tc.log";  // no hostname in tc_log file name !
9379   opt_myisam_log = false;
9380   mqh_used = false;
9381   cleanup_done = 0;
9382   server_id_supplied = false;
9383   test_flags = select_errors = ha_open_options = 0;
9384   atomic_slave_open_temp_tables = 0;
9385   opt_endinfo = using_udf_functions = false;
9386   opt_using_transactions = false;
9387   set_connection_events_loop_aborted(false);
9388   set_mysqld_offline_mode(false);
9389   set_mysqld_partial_revokes(opt_partial_revokes);
9390   server_operational_state = SERVER_BOOTING;
9391   aborted_threads = 0;
9392   delayed_insert_threads = delayed_insert_writes = delayed_rows_in_use = 0;
9393   delayed_insert_errors = 0;
9394   specialflag = 0;
9395   binlog_cache_use = binlog_cache_disk_use = 0;
9396   mysqld_user = mysqld_chroot = opt_init_file = opt_bin_logname = nullptr;
9397   prepared_stmt_count = 0;
9398   mysqld_unix_port = opt_mysql_tmpdir = my_bind_addr_str = NullS;
9399   new (&mysql_tmpdir_list) MY_TMPDIR;
9400   memset(&global_status_var, 0, sizeof(global_status_var));
9401   opt_large_pages = false;
9402   opt_super_large_pages = false;
9403 #if defined(ENABLED_DEBUG_SYNC)
9404   opt_debug_sync_timeout = 0;
9405 #endif /* defined(ENABLED_DEBUG_SYNC) */
9406   server_uuid[0] = 0;
9407 
9408   /* Character sets */
9409   system_charset_info = &my_charset_utf8_general_ci;
9410   files_charset_info = &my_charset_utf8_general_ci;
9411   national_charset_info = &my_charset_utf8_general_ci;
9412   table_alias_charset = &my_charset_bin;
9413   character_set_filesystem = &my_charset_bin;
9414 
9415   opt_specialflag = 0;
9416   pidfile_name_ptr = pidfile_name;
9417   lc_messages_dir_ptr = lc_messages_dir;
9418   protocol_version = PROTOCOL_VERSION;
9419   what_to_log = ~(1L << (uint)COM_TIME);
9420   refresh_version = 1L; /* Increments on each reload */
9421   my_stpcpy(server_version, MYSQL_SERVER_VERSION);
9422   key_caches.empty();
9423   if (!(dflt_key_cache = get_or_create_key_cache(
9424             default_key_cache_base.str, default_key_cache_base.length))) {
9425     LogErr(ERROR_LEVEL, ER_KEYCACHE_OOM);
9426     return 1;
9427   }
9428   /* set key_cache_hash.default_value = dflt_key_cache */
9429   multi_keycache_init();
9430 
9431   /* Replication parameters */
9432   master_info_file = "master.info";
9433   relay_log_info_file = "relay-log.info";
9434   report_user = report_password = report_host = nullptr; /* TO BE DELETED */
9435   opt_relay_logname = opt_relaylog_index_name = nullptr;
9436   opt_relaylog_index_name_supplied = false;
9437   opt_relay_logname_supplied = false;
9438   log_bin_basename = nullptr;
9439   log_bin_index = nullptr;
9440 
9441   /* Handler variables */
9442   total_ha_2pc = 0;
9443   /* Variables in libraries */
9444   charsets_dir = nullptr;
9445   default_character_set_name = MYSQL_DEFAULT_CHARSET_NAME;
9446   default_collation_name = compiled_default_collation_name;
9447   character_set_filesystem_name = "binary";
9448   lc_messages = mysqld_default_locale_name;
9449   lc_time_names_name = mysqld_default_locale_name;
9450 
9451   /* Variables that depends on compile options */
9452 #ifndef DBUG_OFF
9453   default_dbug_option =
9454       IF_WIN("d:t:i:O,\\mysqld.trace", "d:t:i:o,/tmp/mysqld.trace");
9455 #endif
9456 #ifdef ENABLED_PROFILING
9457   have_profiling = SHOW_OPTION_YES;
9458 #else
9459   have_profiling = SHOW_OPTION_NO;
9460 #endif
9461 
9462   have_symlink = SHOW_OPTION_YES;
9463 
9464   have_dlopen = SHOW_OPTION_YES;
9465 
9466   have_query_cache = SHOW_OPTION_NO;
9467 
9468   have_geometry = SHOW_OPTION_YES;
9469 
9470   have_rtree_keys = SHOW_OPTION_YES;
9471 
9472   /* Always true */
9473   have_compress = SHOW_OPTION_YES;
9474 #if defined(_WIN32)
9475   shared_memory_base_name = default_shared_memory_base_name;
9476 #endif
9477 
9478   return 0;
9479 }
9480 
9481 /**
9482   Check if it is a global replication filter setting.
9483 
9484   @param argument The setting of startup option --replicate-*.
9485 
9486   @retval
9487     0    OK
9488   @retval
9489     1    Error
9490 */
is_rpl_global_filter_setting(char * argument)9491 static bool is_rpl_global_filter_setting(char *argument) {
9492   DBUG_TRACE;
9493 
9494   bool res = false;
9495   char *p = strchr(argument, ':');
9496   if (p == nullptr) res = true;
9497 
9498   return res;
9499 }
9500 
9501 /**
9502   Extract channel name and filter value from argument.
9503 
9504   @param [out] channel_name The name of the channel.
9505   @param [out] filter_val The value of filter.
9506   @param argument The setting of startup option --replicate-*.
9507 */
parse_filter_arg(char ** channel_name,char ** filter_val,char * argument)9508 void parse_filter_arg(char **channel_name, char **filter_val, char *argument) {
9509   DBUG_TRACE;
9510 
9511   char *p = strchr(argument, ':');
9512 
9513   DBUG_ASSERT(p != nullptr);
9514 
9515   /*
9516     If argument='channel_1:db1', then channel_name='channel_1'
9517     and filter_val='db1'; If argument=':db1', then channel_name=''
9518     and filter_val='db1'.
9519   */
9520   *channel_name = argument;
9521   *filter_val = p + 1;
9522   *p = 0;
9523 }
9524 
9525 /**
9526   Extract channel name and filter value from argument.
9527 
9528   @param [out] key The db is rewritten from.
9529   @param [out] val The db is rewritten to.
9530   @param argument The value of filter.
9531 
9532   @retval
9533     0    OK
9534   @retval
9535     1    Error
9536 */
parse_replicate_rewrite_db(char ** key,char ** val,char * argument)9537 static int parse_replicate_rewrite_db(char **key, char **val, char *argument) {
9538   DBUG_TRACE;
9539   char *p;
9540   *key = argument;
9541 
9542   if (!(p = strstr(argument, "->"))) {
9543     LogErr(ERROR_LEVEL, ER_RPL_REWRITEDB_MISSING_ARROW);
9544     return 1;
9545   }
9546   *val = p + 2;
9547 
9548   while (p > argument && my_isspace(mysqld_charset, p[-1])) p--;
9549   *p = 0;
9550 
9551   if (!**key) {
9552     LogErr(ERROR_LEVEL, ER_RPL_REWRITEDB_EMPTY_FROM);
9553     return 1;
9554   }
9555   while (**val && my_isspace(mysqld_charset, **val)) (*val)++;
9556   if (!**val) {
9557     LogErr(ERROR_LEVEL, ER_RPL_REWRITEDB_EMPTY_TO);
9558     return 1;
9559   }
9560 
9561   return 0;
9562 }
9563 
mysqld_get_one_option(int optid,const struct my_option * opt MY_ATTRIBUTE ((unused)),char * argument)9564 bool mysqld_get_one_option(int optid,
9565                            const struct my_option *opt MY_ATTRIBUTE((unused)),
9566                            char *argument) {
9567   Rpl_filter *rpl_filter = nullptr;
9568   char *filter_val;
9569   char *channel_name;
9570 
9571   switch (optid) {
9572     case '#':
9573 #ifndef DBUG_OFF
9574       DBUG_SET_INITIAL(argument ? argument : default_dbug_option);
9575 #endif
9576       opt_endinfo = true; /* unireg: memory allocation */
9577       break;
9578     case 'a':
9579       global_system_variables.sql_mode = MODE_ANSI;
9580       global_system_variables.transaction_isolation = ISO_SERIALIZABLE;
9581       break;
9582     case 'b':
9583       strmake(mysql_home, argument, sizeof(mysql_home) - 1);
9584       mysql_home_ptr = mysql_home;
9585       break;
9586     case 'C':
9587       if (default_collation_name == compiled_default_collation_name)
9588         default_collation_name = nullptr;
9589       break;
9590     case 'h':
9591       strmake(mysql_real_data_home, argument, sizeof(mysql_real_data_home) - 1);
9592       /* Correct pointer set by my_getopt */
9593       mysql_real_data_home_ptr = mysql_real_data_home;
9594       break;
9595     case 'u':
9596       if (!mysqld_user || !strcmp(mysqld_user, argument))
9597         mysqld_user = argument;
9598       else
9599         LogErr(WARNING_LEVEL, ER_THE_USER_ABIDES, argument, mysqld_user);
9600       break;
9601     case 's':
9602       if (argument && argument[0] == '0') {
9603         LogErr(WARNING_LEVEL, ER_DEPRECATE_MSG_NO_REPLACEMENT,
9604                "Disabling symbolic links using --skip-symbolic-links"
9605                " (or equivalent) is the default. Consider not using"
9606                " this option as it");
9607       } else {
9608         LogErr(WARNING_LEVEL, ER_DEPRECATE_MSG_NO_REPLACEMENT,
9609                "Enabling symbolic using --symbolic-links/-s (or equivalent)");
9610       }
9611       break;
9612     case 'L':
9613       push_deprecated_warn(nullptr, "--language/-l", "'--lc-messages-dir'");
9614       /* Note:  fall-through */
9615     case OPT_LC_MESSAGES_DIRECTORY:
9616       strmake(lc_messages_dir, argument, sizeof(lc_messages_dir) - 1);
9617       lc_messages_dir_ptr = lc_messages_dir;
9618       break;
9619     case OPT_BINLOG_FORMAT:
9620       binlog_format_used = true;
9621       break;
9622     case OPT_BINLOG_MAX_FLUSH_QUEUE_TIME:
9623       push_deprecated_warn_no_replacement(nullptr,
9624                                           "--binlog_max_flush_queue_time");
9625       break;
9626     case OPT_EXPIRE_LOGS_DAYS:
9627       push_deprecated_warn(nullptr, "expire-logs-days",
9628                            "binlog_expire_logs_seconds");
9629       expire_logs_days_supplied = true;
9630       break;
9631     case OPT_BINLOG_EXPIRE_LOGS_SECONDS:
9632       binlog_expire_logs_seconds_supplied = true;
9633       break;
9634 #ifndef XTRABACKUP
9635     case OPT_SSL_KEY:
9636     case OPT_SSL_CERT:
9637     case OPT_SSL_CA:
9638     case OPT_SSL_CAPATH:
9639     case OPT_SSL_CIPHER:
9640     case OPT_TLS_CIPHERSUITES:
9641     case OPT_SSL_CRL:
9642     case OPT_SSL_CRLPATH:
9643     case OPT_TLS_VERSION:
9644       /*
9645         Enable use of SSL if we are using any ssl option.
9646         One can disable SSL later by using --skip-ssl or --ssl=0.
9647       */
9648       opt_use_ssl = true;
9649       break;
9650     case OPT_ADMIN_SSL_KEY:
9651     case OPT_ADMIN_SSL_CERT:
9652     case OPT_ADMIN_SSL_CA:
9653     case OPT_ADMIN_SSL_CAPATH:
9654     case OPT_ADMIN_SSL_CIPHER:
9655     case OPT_ADMIN_TLS_CIPHERSUITES:
9656     case OPT_ADMIN_SSL_CRL:
9657     case OPT_ADMIN_SSL_CRLPATH:
9658     case OPT_ADMIN_TLS_VERSION:
9659       /*
9660         Enable use of SSL if we are using any ssl option.
9661         One can disable SSL later by using --skip-admin-ssl or --admin-ssl=0.
9662       */
9663       g_admin_ssl_configured = true;
9664       opt_use_admin_ssl = true;
9665       break;
9666 #endif /* XTRABACKUP */
9667     case 'V':
9668       print_server_version();
9669       exit(MYSQLD_SUCCESS_EXIT);
9670     case 'T':
9671       test_flags = argument ? (uint)atoi(argument) : 0;
9672       opt_endinfo = true;
9673       break;
9674     case (int)OPT_ISAM_LOG:
9675       opt_myisam_log = true;
9676       break;
9677     case (int)OPT_BIN_LOG:
9678       opt_bin_log = (argument != disabled_my_option);
9679       if (!opt_bin_log) {
9680         // Clear the binlog basename used by any previous --log-bin
9681         if (opt_bin_logname) {
9682           my_free(opt_bin_logname);
9683           opt_bin_logname = nullptr;
9684         }
9685       }
9686       log_bin_supplied = true;
9687       break;
9688     case (int)OPT_REPLICATE_IGNORE_DB: {
9689       if (is_rpl_global_filter_setting(argument)) {
9690         rpl_global_filter.add_ignore_db(argument);
9691         rpl_global_filter.ignore_db_statistics.set_all(
9692             CONFIGURED_BY_STARTUP_OPTIONS);
9693       } else {
9694         parse_filter_arg(&channel_name, &filter_val, argument);
9695         rpl_filter = rpl_channel_filters.get_channel_filter(channel_name);
9696         rpl_filter->add_ignore_db(filter_val);
9697         rpl_filter->ignore_db_statistics.set_all(
9698             CONFIGURED_BY_STARTUP_OPTIONS_FOR_CHANNEL);
9699       }
9700       break;
9701     }
9702     case (int)OPT_REPLICATE_DO_DB: {
9703       if (is_rpl_global_filter_setting(argument)) {
9704         rpl_global_filter.add_do_db(argument);
9705         rpl_global_filter.do_db_statistics.set_all(
9706             CONFIGURED_BY_STARTUP_OPTIONS);
9707       } else {
9708         parse_filter_arg(&channel_name, &filter_val, argument);
9709         rpl_filter = rpl_channel_filters.get_channel_filter(channel_name);
9710         rpl_filter->add_do_db(filter_val);
9711         rpl_filter->do_db_statistics.set_all(
9712             CONFIGURED_BY_STARTUP_OPTIONS_FOR_CHANNEL);
9713       }
9714       break;
9715     }
9716     case (int)OPT_REPLICATE_REWRITE_DB: {
9717       char *key, *val;
9718       if (is_rpl_global_filter_setting(argument)) {
9719         if (parse_replicate_rewrite_db(&key, &val, argument)) return true;
9720         rpl_global_filter.add_db_rewrite(key, val);
9721         rpl_global_filter.rewrite_db_statistics.set_all(
9722             CONFIGURED_BY_STARTUP_OPTIONS);
9723       } else {
9724         parse_filter_arg(&channel_name, &filter_val, argument);
9725         rpl_filter = rpl_channel_filters.get_channel_filter(channel_name);
9726         if (parse_replicate_rewrite_db(&key, &val, filter_val)) return true;
9727         rpl_filter->add_db_rewrite(key, val);
9728         rpl_filter->rewrite_db_statistics.set_all(
9729             CONFIGURED_BY_STARTUP_OPTIONS_FOR_CHANNEL);
9730       }
9731       break;
9732     }
9733 
9734     case (int)OPT_BINLOG_IGNORE_DB: {
9735       binlog_filter->add_ignore_db(argument);
9736       break;
9737     }
9738     case (int)OPT_BINLOG_DO_DB: {
9739       binlog_filter->add_do_db(argument);
9740       break;
9741     }
9742     case (int)OPT_REPLICATE_DO_TABLE: {
9743       if (is_rpl_global_filter_setting(argument)) {
9744         if (rpl_global_filter.add_do_table_array(argument)) {
9745           LogErr(ERROR_LEVEL, ER_RPL_CANT_ADD_DO_TABLE, argument);
9746           return true;
9747         }
9748         rpl_global_filter.do_table_statistics.set_all(
9749             CONFIGURED_BY_STARTUP_OPTIONS);
9750       } else {
9751         parse_filter_arg(&channel_name, &filter_val, argument);
9752         rpl_filter = rpl_channel_filters.get_channel_filter(channel_name);
9753         if (rpl_filter->add_do_table_array(filter_val)) {
9754           LogErr(ERROR_LEVEL, ER_RPL_CANT_ADD_DO_TABLE, argument);
9755           return true;
9756         }
9757         rpl_filter->do_table_statistics.set_all(
9758             CONFIGURED_BY_STARTUP_OPTIONS_FOR_CHANNEL);
9759       }
9760       break;
9761     }
9762     case (int)OPT_REPLICATE_WILD_DO_TABLE: {
9763       if (is_rpl_global_filter_setting(argument)) {
9764         if (rpl_global_filter.add_wild_do_table(argument)) {
9765           LogErr(ERROR_LEVEL, ER_RPL_FILTER_ADD_WILD_DO_TABLE_FAILED, argument);
9766           return true;
9767         }
9768         rpl_global_filter.wild_do_table_statistics.set_all(
9769             CONFIGURED_BY_STARTUP_OPTIONS);
9770       } else {
9771         parse_filter_arg(&channel_name, &filter_val, argument);
9772         rpl_filter = rpl_channel_filters.get_channel_filter(channel_name);
9773         if (rpl_filter->add_wild_do_table(filter_val)) {
9774           LogErr(ERROR_LEVEL, ER_RPL_FILTER_ADD_WILD_DO_TABLE_FAILED, argument);
9775           return true;
9776         }
9777         rpl_filter->wild_do_table_statistics.set_all(
9778             CONFIGURED_BY_STARTUP_OPTIONS_FOR_CHANNEL);
9779       }
9780       break;
9781     }
9782     case (int)OPT_REPLICATE_WILD_IGNORE_TABLE: {
9783       if (is_rpl_global_filter_setting(argument)) {
9784         if (rpl_global_filter.add_wild_ignore_table(argument)) {
9785           LogErr(ERROR_LEVEL, ER_RPL_FILTER_ADD_WILD_IGNORE_TABLE_FAILED,
9786                  argument);
9787           return true;
9788         }
9789         rpl_global_filter.wild_ignore_table_statistics.set_all(
9790             CONFIGURED_BY_STARTUP_OPTIONS);
9791       } else {
9792         parse_filter_arg(&channel_name, &filter_val, argument);
9793         rpl_filter = rpl_channel_filters.get_channel_filter(channel_name);
9794         if (rpl_filter->add_wild_ignore_table(filter_val)) {
9795           LogErr(ERROR_LEVEL, ER_RPL_FILTER_ADD_WILD_IGNORE_TABLE_FAILED,
9796                  argument);
9797           return true;
9798         }
9799         rpl_filter->wild_ignore_table_statistics.set_all(
9800             CONFIGURED_BY_STARTUP_OPTIONS_FOR_CHANNEL);
9801       }
9802       break;
9803     }
9804     case (int)OPT_REPLICATE_IGNORE_TABLE: {
9805       if (is_rpl_global_filter_setting(argument)) {
9806         if (rpl_global_filter.add_ignore_table_array(argument)) {
9807           LogErr(ERROR_LEVEL, ER_RPL_CANT_ADD_IGNORE_TABLE, argument);
9808           return true;
9809         }
9810         rpl_global_filter.ignore_table_statistics.set_all(
9811             CONFIGURED_BY_STARTUP_OPTIONS);
9812       } else {
9813         parse_filter_arg(&channel_name, &filter_val, argument);
9814         rpl_filter = rpl_channel_filters.get_channel_filter(channel_name);
9815         if (rpl_filter->add_ignore_table_array(filter_val)) {
9816           LogErr(ERROR_LEVEL, ER_RPL_CANT_ADD_IGNORE_TABLE, argument);
9817           return true;
9818         }
9819         rpl_filter->ignore_table_statistics.set_all(
9820             CONFIGURED_BY_STARTUP_OPTIONS_FOR_CHANNEL);
9821       }
9822       break;
9823     }
9824     case (int)OPT_MASTER_RETRY_COUNT:
9825       push_deprecated_warn(nullptr, "--master-retry-count",
9826                            "'CHANGE MASTER TO master_retry_count = <num>'");
9827       break;
9828     case (int)OPT_SKIP_NEW:
9829       opt_specialflag |= SPECIAL_NO_NEW_FUNC;
9830       delay_key_write_options = DELAY_KEY_WRITE_NONE;
9831       myisam_concurrent_insert = 0;
9832       myisam_recover_options = HA_RECOVER_OFF;
9833       sp_automatic_privileges = false;
9834       my_enable_symlinks = false;
9835       ha_open_options &= ~(HA_OPEN_ABORT_IF_CRASHED | HA_OPEN_DELAY_KEY_WRITE);
9836       break;
9837     case (int)OPT_SKIP_HOST_CACHE:
9838       opt_specialflag |= SPECIAL_NO_HOST_CACHE;
9839       break;
9840     case (int)OPT_SKIP_RESOLVE:
9841       if (argument && (argument == disabled_my_option ||
9842                        !my_strcasecmp(system_charset_info, argument, "OFF")))
9843         opt_skip_name_resolve = false;
9844       else {
9845         opt_skip_name_resolve = true;
9846         opt_specialflag |= SPECIAL_NO_RESOLVE;
9847       }
9848       break;
9849     case (int)OPT_WANT_CORE:
9850       test_flags |= TEST_CORE_ON_SIGNAL;
9851       break;
9852     case (int)OPT_SKIP_STACK_TRACE:
9853       test_flags |= TEST_NO_STACKTRACE;
9854       break;
9855     case OPT_SERVER_ID:
9856       /*
9857        Consider that one received a Server Id when 2 conditions are present:
9858        1) The argument is on the list
9859        2) There is a value present
9860       */
9861       server_id_supplied = (*argument != 0);
9862       break;
9863     case OPT_LOWER_CASE_TABLE_NAMES:
9864       lower_case_table_names_used = true;
9865       break;
9866 #if defined(ENABLED_DEBUG_SYNC)
9867     case OPT_DEBUG_SYNC_TIMEOUT:
9868       /*
9869         Debug Sync Facility. See debug_sync.cc.
9870         Default timeout for WAIT_FOR action.
9871         Default value is zero (facility disabled).
9872         If option is given without an argument, supply a non-zero value.
9873       */
9874       if (!argument) {
9875         /* purecov: begin tested */
9876         opt_debug_sync_timeout = DEBUG_SYNC_DEFAULT_WAIT_TIMEOUT;
9877         /* purecov: end */
9878       }
9879       break;
9880 #endif /* defined(ENABLED_DEBUG_SYNC) */
9881     case OPT_LOG_ERROR:
9882       /*
9883         "No --log-error" == "write errors to stderr",
9884         "--log-error without argument" == "write errors to a file".
9885       */
9886       if (argument == nullptr) /* no argument */
9887         log_error_dest = "";
9888       break;
9889 
9890     case OPT_EARLY_PLUGIN_LOAD:
9891       free_list(opt_early_plugin_load_list_ptr);
9892       opt_early_plugin_load_list_ptr->push_back(new i_string(argument));
9893       break;
9894     case OPT_PLUGIN_LOAD:
9895       free_list(opt_plugin_load_list_ptr);
9896       /* fall through */
9897     case OPT_PLUGIN_LOAD_ADD:
9898       opt_plugin_load_list_ptr->push_back(new i_string(argument));
9899       break;
9900     case OPT_PFS_INSTRUMENT: {
9901 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
9902       /*
9903         Parse instrument name and value from argument string. Handle leading
9904         and trailing spaces. Also handle single quotes.
9905 
9906         Acceptable:
9907           performance_schema_instrument = ' foo/%/bar/  =  ON  '
9908           performance_schema_instrument = '%=OFF'
9909         Not acceptable:
9910           performance_schema_instrument = '' foo/%/bar = ON ''
9911           performance_schema_instrument = '%='OFF''
9912       */
9913       char *name = argument, *p = nullptr, *val = nullptr;
9914       bool quote = false; /* true if quote detected */
9915       bool error = true;  /* false if no errors detected */
9916       const int PFS_BUFFER_SIZE = 128;
9917       char orig_argument[PFS_BUFFER_SIZE + 1];
9918       orig_argument[0] = 0;
9919 
9920       if (!argument) goto pfs_error;
9921 
9922       /* Save original argument string for error reporting */
9923       strncpy(orig_argument, argument, PFS_BUFFER_SIZE);
9924 
9925       /* Split instrument name and value at the equal sign */
9926       if (!(p = strchr(argument, '='))) goto pfs_error;
9927 
9928       /* Get option value */
9929       val = p + 1;
9930       if (!*val) goto pfs_error;
9931 
9932       /* Trim leading spaces and quote from the instrument name */
9933       while (*name && (my_isspace(mysqld_charset, *name) || (*name == '\''))) {
9934         /* One quote allowed */
9935         if (*name == '\'') {
9936           if (!quote)
9937             quote = true;
9938           else
9939             goto pfs_error;
9940         }
9941         name++;
9942       }
9943 
9944       /* Trim trailing spaces from instrument name */
9945       while ((p > name) && my_isspace(mysqld_charset, p[-1])) p--;
9946       *p = 0;
9947 
9948       /* Remove trailing slash from instrument name */
9949       if (p > name && (p[-1] == '/')) p[-1] = 0;
9950 
9951       if (!*name) goto pfs_error;
9952 
9953       /* Trim leading spaces from option value */
9954       while (*val && my_isspace(mysqld_charset, *val)) val++;
9955 
9956       /* Trim trailing spaces and matching quote from value */
9957       p = val + strlen(val);
9958       while (p > val && (my_isspace(mysqld_charset, p[-1]) || p[-1] == '\'')) {
9959         /* One matching quote allowed */
9960         if (p[-1] == '\'') {
9961           if (quote)
9962             quote = false;
9963           else
9964             goto pfs_error;
9965         }
9966         p--;
9967       }
9968 
9969       *p = 0;
9970 
9971       if (!*val) goto pfs_error;
9972 
9973       /* Add instrument name and value to array of configuration options */
9974       if (add_pfs_instr_to_array(name, val)) goto pfs_error;
9975 
9976       error = false;
9977 
9978     pfs_error:
9979       if (error) {
9980         LogErr(WARNING_LEVEL, ER_INVALID_INSTRUMENT, orig_argument);
9981         return false;
9982       }
9983 #endif /* WITH_PERFSCHEMA_STORAGE_ENGINE */
9984       break;
9985     }
9986     case OPT_THREAD_CACHE_SIZE:
9987       thread_cache_size_specified = true;
9988       break;
9989     case OPT_HOST_CACHE_SIZE:
9990       host_cache_size_specified = true;
9991       break;
9992     case OPT_TABLE_DEFINITION_CACHE:
9993       table_definition_cache_specified = true;
9994       break;
9995     case OPT_SKIP_INNODB:
9996       LogErr(WARNING_LEVEL, ER_INNODB_MANDATORY);
9997       break;
9998     case OPT_AVOID_TEMPORAL_UPGRADE:
9999       push_deprecated_warn_no_replacement(nullptr, "avoid_temporal_upgrade");
10000       break;
10001     case OPT_SHOW_OLD_TEMPORALS:
10002       push_deprecated_warn_no_replacement(nullptr, "show_old_temporals");
10003       break;
10004     case 'p':
10005       if (argument) {
10006         char *start = argument;
10007         my_free(opt_keyring_migration_password);
10008         opt_keyring_migration_password =
10009             my_strdup(PSI_NOT_INSTRUMENTED, argument, MYF(MY_FAE));
10010         while (*argument) *argument++ = 'x';
10011         if (*start) start[1] = 0;
10012       } else
10013         opt_keyring_migration_password = get_tty_password(NullS);
10014       migrate_connect_options = true;
10015       break;
10016     case OPT_KEYRING_MIGRATION_USER:
10017     case OPT_KEYRING_MIGRATION_HOST:
10018     case OPT_KEYRING_MIGRATION_SOCKET:
10019     case OPT_KEYRING_MIGRATION_PORT:
10020       migrate_connect_options = true;
10021       break;
10022     case OPT_LOG_SLAVE_UPDATES:
10023       log_slave_updates_supplied = true;
10024       break;
10025     case OPT_SLAVE_PRESERVE_COMMIT_ORDER:
10026       slave_preserve_commit_order_supplied = true;
10027       break;
10028     case OPT_ENFORCE_GTID_CONSISTENCY: {
10029       const char *wrong_value =
10030           fixup_enforce_gtid_consistency_command_line(argument);
10031       if (wrong_value != nullptr)
10032         LogErr(WARNING_LEVEL, ER_INVALID_VALUE_FOR_ENFORCE_GTID_CONSISTENCY,
10033                wrong_value);
10034     } break;
10035     case OPT_NAMED_PIPE_FULL_ACCESS_GROUP:
10036 #ifdef _WIN32
10037       if (!is_valid_named_pipe_full_access_group(argument)) {
10038         LogErr(ERROR_LEVEL, ER_INVALID_NAMED_PIPE_FULL_ACCESS_GROUP);
10039         return 1;
10040       }
10041 #endif  // _WIN32
10042       break;
10043     case OPT_RELAY_LOG_INFO_FILE:
10044       push_deprecated_warn_no_replacement(nullptr, "--relay-log-info-file");
10045       break;
10046     case OPT_MASTER_INFO_FILE:
10047       push_deprecated_warn_no_replacement(nullptr, "--master-info-file");
10048       break;
10049     case OPT_LOG_BIN_USE_V1_ROW_EVENTS:
10050       push_deprecated_warn_no_replacement(nullptr,
10051                                           "--log-bin-use-v1-row-events");
10052       break;
10053     case OPT_SLAVE_ROWS_SEARCH_ALGORITHMS:
10054       push_deprecated_warn_no_replacement(nullptr,
10055                                           "--slave-rows-search-algorithms");
10056       break;
10057   }
10058   return false;
10059 }
10060 
10061 /** Handle arguments for multiple key caches. */
10062 
mysql_getopt_value(const char * keyname,size_t key_length,const struct my_option * option,int * error)10063 static void *mysql_getopt_value(const char *keyname, size_t key_length,
10064                                 const struct my_option *option, int *error) {
10065   if (error) *error = 0;
10066   switch (option->id) {
10067     case OPT_KEY_BUFFER_SIZE:
10068     case OPT_KEY_CACHE_BLOCK_SIZE:
10069     case OPT_KEY_CACHE_DIVISION_LIMIT:
10070     case OPT_KEY_CACHE_AGE_THRESHOLD: {
10071       KEY_CACHE *key_cache;
10072       if (!(key_cache = get_or_create_key_cache(keyname, key_length))) {
10073         if (error) *error = EXIT_OUT_OF_MEMORY;
10074         return nullptr;
10075       }
10076       switch (option->id) {
10077         case OPT_KEY_BUFFER_SIZE:
10078           return &key_cache->param_buff_size;
10079         case OPT_KEY_CACHE_BLOCK_SIZE:
10080           return &key_cache->param_block_size;
10081         case OPT_KEY_CACHE_DIVISION_LIMIT:
10082           return &key_cache->param_division_limit;
10083         case OPT_KEY_CACHE_AGE_THRESHOLD:
10084           return &key_cache->param_age_threshold;
10085       }
10086     }
10087   }
10088   return option->value;
10089 }
10090 
10091 /**
10092   Get server options from the command line,
10093   and perform related server initializations.
10094   @param [in, out] argc_ptr       command line options (count)
10095   @param [in, out] argv_ptr       command line options (values)
10096   @return 0 on success
10097 
10098   @todo
10099   - FIXME add EXIT_TOO_MANY_ARGUMENTS to "mysys_err.h" and return that code?
10100 */
get_options(int * argc_ptr,char *** argv_ptr)10101 static int get_options(int *argc_ptr, char ***argv_ptr) {
10102   int ho_error;
10103 
10104   my_getopt_register_get_addr(mysql_getopt_value);
10105 
10106   /* prepare all_options array */
10107   all_options.reserve(array_elements(my_long_options));
10108   for (my_option *opt = my_long_options;
10109        opt < my_long_options + array_elements(my_long_options) - 1; opt++) {
10110     all_options.push_back(*opt);
10111   }
10112   sys_var_add_options(&all_options, sys_var::PARSE_NORMAL);
10113   add_terminator(&all_options);
10114 
10115   if (is_help_or_validate_option() || opt_initialize) {
10116     /*
10117       Show errors during --help, but mute everything else so the info the
10118       user actually wants isn't lost in the spam.  (For --help --verbose,
10119       we need to set up far enough to be able to print variables provided
10120       by plugins, so a good number of warnings/notes might get printed.)
10121       Likewise for --initialize.
10122     */
10123     struct my_option *opt = &all_options[0];
10124     for (; opt->name; opt++)
10125       if (!strcmp("log_error_verbosity", opt->name))
10126         opt->def_value = opt_initialize ? 2 : 1;
10127   }
10128 
10129   /* Skip unknown options so that they may be processed later by plugins */
10130   my_getopt_skip_unknown = true;
10131 
10132   if ((ho_error = handle_options(argc_ptr, argv_ptr, &all_options[0],
10133                                  mysqld_get_one_option)))
10134     return ho_error;
10135 
10136   // update verbosity in filter engine, if needed
10137   log_builtins_filter_update_verbosity(log_error_verbosity);
10138 
10139   // update suppression list in filter engine
10140   {
10141     int rr;
10142     // try to set the list
10143     if (((rr = log_builtins_filter_parse_suppression_list(
10144               opt_log_error_suppression_list, false)) != 0) ||
10145         ((rr = log_builtins_filter_parse_suppression_list(
10146               opt_log_error_suppression_list, true)) != 0)) {
10147       rr = -(rr + 1);
10148       LogErr(ERROR_LEVEL, ER_CANT_SET_ERROR_SUPPRESSION_LIST_FROM_COMMAND_LINE,
10149              "log_error_suppression_list", &opt_log_error_suppression_list[rr]);
10150 
10151       /*
10152         We were given an illegal value at start-up, so the default will be
10153         used instead. We have reported the problem (and the dodgy value);
10154         let's now point our variable back at the default (i.e. the value
10155         actually used) so SELECT @@GLOBAL.log_error_suppression_list will
10156         render correct results.
10157       */
10158       sys_var *var =
10159           intern_find_sys_var(STRING_WITH_LEN("log_error_suppression_list"));
10160       if (var != nullptr) {
10161         opt_log_error_suppression_list = (char *)var->get_default();
10162         /*
10163           During unit-testing, the log subsystem is not initialized,
10164           so while the default should always check out as a valid
10165           argument, actually setting it will still fail in this
10166           particular case as we cannot acquire the rule-set or its
10167           lock.
10168         */
10169         if (log_builtins_filter_parse_suppression_list(
10170                 opt_log_error_suppression_list, false) == 0) {
10171           log_builtins_filter_parse_suppression_list(
10172               opt_log_error_suppression_list, true);
10173         } else {
10174           DBUG_ASSERT(false); /* purecov: inspected */
10175         }
10176       }
10177     }
10178   }
10179 
10180   if (!is_help_or_validate_option())
10181     vector<my_option>().swap(all_options);  // Deletes the vector contents.
10182 
10183   /* Add back the program name handle_options removes */
10184   (*argc_ptr)++;
10185   (*argv_ptr)--;
10186 
10187   /*
10188     Options have been parsed. Now some of them need additional special
10189     handling, like custom value checking, checking of incompatibilites
10190     between options, setting of multiple variables, etc.
10191     Do them here.
10192   */
10193 
10194   if (!opt_help && opt_verbose) LogErr(ERROR_LEVEL, ER_VERBOSE_REQUIRES_HELP);
10195 
10196   if ((opt_log_slow_admin_statements || opt_log_queries_not_using_indexes ||
10197        opt_log_slow_slave_statements) &&
10198       !opt_slow_log)
10199     LogErr(WARNING_LEVEL, ER_POINTLESS_WITHOUT_SLOWLOG);
10200 
10201   if (global_system_variables.net_buffer_length >
10202       global_system_variables.max_allowed_packet) {
10203     LogErr(WARNING_LEVEL, ER_WASTEFUL_NET_BUFFER_SIZE,
10204            global_system_variables.net_buffer_length,
10205            global_system_variables.max_allowed_packet);
10206   }
10207 
10208   /*
10209     TIMESTAMP columns get implicit DEFAULT values when
10210     --explicit_defaults_for_timestamp is not set.
10211     This behavior is deprecated now.
10212   */
10213   if (!is_help_or_validate_option() &&
10214       !global_system_variables.explicit_defaults_for_timestamp)
10215     LogErr(WARNING_LEVEL, ER_DEPRECATED_TIMESTAMP_IMPLICIT_DEFAULTS);
10216 
10217   if (!is_help_or_validate_option() &&
10218       opt_mi_repository_id == INFO_REPOSITORY_FILE)
10219     push_deprecated_warn(nullptr, "--master-info-repository=FILE",
10220                          "'--master-info-repository=TABLE'");
10221 
10222   if (!is_help_or_validate_option() &&
10223       opt_rli_repository_id == INFO_REPOSITORY_FILE)
10224     push_deprecated_warn(nullptr, "--relay-log-info-repository=FILE",
10225                          "'--relay-log-info-repository=TABLE'");
10226 
10227   opt_init_connect.length = strlen(opt_init_connect.str);
10228   opt_init_slave.length = strlen(opt_init_slave.str);
10229   opt_mandatory_roles.length = strlen(opt_mandatory_roles.str);
10230 
10231   if (global_system_variables.low_priority_updates)
10232     thr_upgraded_concurrent_insert_lock = TL_WRITE_LOW_PRIORITY;
10233 
10234   if (ft_boolean_check_syntax_string(
10235           pointer_cast<const uchar *>(ft_boolean_syntax))) {
10236     LogErr(ERROR_LEVEL, ER_FT_BOOL_SYNTAX_INVALID, ft_boolean_syntax);
10237     return 1;
10238   }
10239 
10240   if (opt_noacl && !is_help_or_validate_option()) opt_disable_networking = true;
10241 
10242   if (opt_disable_networking) mysqld_port = 0;
10243 
10244   if (opt_skip_show_db) opt_specialflag |= SPECIAL_SKIP_SHOW_DB;
10245 
10246   if (myisam_flush) flush_time = 0;
10247 
10248   if (opt_slave_skip_errors) add_slave_skip_errors(opt_slave_skip_errors);
10249 
10250   if (global_system_variables.max_join_size == HA_POS_ERROR)
10251     global_system_variables.option_bits |= OPTION_BIG_SELECTS;
10252   else
10253     global_system_variables.option_bits &= ~OPTION_BIG_SELECTS;
10254 
10255   // Synchronize @@global.autocommit value on --autocommit
10256   const ulonglong turn_bit_on =
10257       opt_autocommit ? OPTION_AUTOCOMMIT : OPTION_NOT_AUTOCOMMIT;
10258   global_system_variables.option_bits =
10259       (global_system_variables.option_bits &
10260        ~(OPTION_NOT_AUTOCOMMIT | OPTION_AUTOCOMMIT)) |
10261       turn_bit_on;
10262 
10263   // Synchronize @@global.autocommit metadata on --autocommit
10264   my_option *opt = &my_long_options[3];
10265   DBUG_ASSERT(strcmp(opt->name, "autocommit") == 0);
10266   DBUG_ASSERT(opt->arg_source != nullptr);
10267   Sys_autocommit_ptr->set_source_name(opt->arg_source->m_path_name);
10268   Sys_autocommit_ptr->set_source(opt->arg_source->m_source);
10269 
10270   global_system_variables.sql_mode =
10271       expand_sql_mode(global_system_variables.sql_mode, nullptr);
10272 
10273   if (!my_enable_symlinks) have_symlink = SHOW_OPTION_DISABLED;
10274 
10275   if (opt_debugging) {
10276     /* Allow break with SIGINT, no core or stack trace */
10277     test_flags |= TEST_SIGINT | TEST_NO_STACKTRACE;
10278     test_flags &= ~TEST_CORE_ON_SIGNAL;
10279   }
10280   /* Set global MyISAM variables from delay_key_write_options */
10281   fix_delay_key_write(nullptr, nullptr, OPT_GLOBAL);
10282 
10283 #ifndef _WIN32
10284   if (mysqld_chroot) set_root(mysqld_chroot);
10285 #endif
10286   if (fix_paths()) return 1;
10287 
10288   /*
10289     Set some global variables from the global_system_variables
10290     In most cases the global variables will not be used
10291   */
10292   my_disable_locking = myisam_single_user = (opt_external_locking == 0);
10293   my_default_record_cache_size = global_system_variables.read_buff_size;
10294 
10295   global_system_variables.long_query_time =
10296       (ulonglong)(global_system_variables.long_query_time_double * 1e6);
10297 
10298   if (opt_short_log_format) opt_specialflag |= SPECIAL_SHORT_LOG_FORMAT;
10299 
10300   if (Connection_handler_manager::init()) {
10301     LogErr(ERROR_LEVEL, ER_CONNECTION_HANDLING_OOM);
10302     return 1;
10303   }
10304   if (Global_THD_manager::create_instance()) {
10305     LogErr(ERROR_LEVEL, ER_THREAD_HANDLING_OOM);
10306     return 1;
10307   }
10308 
10309   /* If --super-read-only was specified, set read_only to 1 */
10310   read_only = super_read_only ? super_read_only : read_only;
10311   opt_readonly = read_only;
10312 
10313   return 0;
10314 }
10315 
10316 /*
10317   Create version name for running mysqld version
10318   We automaticly add suffixes -debug, -valgrind, -asan, -ubsan
10319   to the version name to make the version more descriptive.
10320   (MYSQL_SERVER_SUFFIX is set by the compilation environment)
10321 */
10322 
10323 /*
10324   The following code is quite ugly as there is no portable way to easily set a
10325   string to the value of a macro
10326 */
10327 #ifdef MYSQL_SERVER_SUFFIX
10328 #define MYSQL_SERVER_SUFFIX_STR STRINGIFY_ARG(MYSQL_SERVER_SUFFIX)
10329 #else
10330 #define MYSQL_SERVER_SUFFIX_STR MYSQL_SERVER_SUFFIX_DEF
10331 #endif
10332 
set_server_version(void)10333 static void set_server_version(void) {
10334   char *end MY_ATTRIBUTE((unused)) = strxmov(
10335       server_version, MYSQL_SERVER_VERSION, MYSQL_SERVER_SUFFIX_STR, NullS);
10336 #ifndef DBUG_OFF
10337   if (!strstr(MYSQL_SERVER_SUFFIX_STR, "-debug"))
10338     end = my_stpcpy(end, "-debug");
10339 #endif
10340 #ifdef HAVE_VALGRIND
10341   if (SERVER_VERSION_LENGTH - (end - server_version) >
10342       static_cast<int>(sizeof("-valgrind")))
10343     end = my_stpcpy(end, "-valgrind");
10344 #endif
10345 #ifdef HAVE_ASAN
10346   if (SERVER_VERSION_LENGTH - (end - server_version) >
10347       static_cast<int>(sizeof("-asan")))
10348     end = my_stpcpy(end, "-asan");
10349 #endif
10350 #ifdef HAVE_LSAN
10351   if (SERVER_VERSION_LENGTH - (end - server_version) >
10352       static_cast<int>(sizeof("-lsan")))
10353     end = my_stpcpy(end, "-lsan");
10354 #endif
10355 #ifdef HAVE_UBSAN
10356   if (SERVER_VERSION_LENGTH - (end - server_version) >
10357       static_cast<int>(sizeof("-ubsan")))
10358     end = my_stpcpy(end, "-ubsan");
10359 #endif
10360 #ifdef HAVE_TSAN
10361   if (SERVER_VERSION_LENGTH - (end - server_version) >
10362       static_cast<int>(sizeof("-tsan")))
10363     end = my_stpcpy(end, "-tsan");
10364 #endif
10365 }
10366 
get_relative_path(const char * path)10367 static const char *get_relative_path(const char *path) {
10368   if (test_if_hard_path(path) && is_prefix(path, DEFAULT_MYSQL_HOME) &&
10369       strcmp(DEFAULT_MYSQL_HOME, FN_ROOTDIR)) {
10370     path += strlen(DEFAULT_MYSQL_HOME);
10371     while (is_directory_separator(*path)) path++;
10372   }
10373   return path;
10374 }
10375 
10376 /**
10377   Test a file path to determine if the path is compatible with the secure file
10378   path restriction.
10379 
10380   @param path null terminated character string
10381 
10382   @retval true The path is secure
10383   @retval false The path isn't secure
10384 */
10385 
is_secure_file_path(const char * path)10386 bool is_secure_file_path(const char *path) {
10387   char buff1[FN_REFLEN], buff2[FN_REFLEN];
10388   size_t opt_secure_file_priv_len;
10389   /*
10390     All paths are secure if opt_secure_file_priv is 0
10391   */
10392   if (!opt_secure_file_priv[0]) return true;
10393 
10394   opt_secure_file_priv_len = strlen(opt_secure_file_priv);
10395 
10396   if (strlen(path) >= FN_REFLEN) return false;
10397 
10398   if (!my_strcasecmp(system_charset_info, opt_secure_file_priv, "NULL"))
10399     return false;
10400 
10401   if (my_realpath(buff1, path, 0)) {
10402     /*
10403       The supplied file path might have been a file and not a directory.
10404     */
10405     int length = (int)dirname_length(path);
10406     if (length >= FN_REFLEN) return false;
10407     memcpy(buff2, path, length);
10408     buff2[length] = '\0';
10409     if (length == 0 || my_realpath(buff1, buff2, 0)) return false;
10410   }
10411   convert_dirname(buff2, buff1, NullS);
10412   if (!lower_case_file_system) {
10413     if (strncmp(opt_secure_file_priv, buff2, opt_secure_file_priv_len))
10414       return false;
10415   } else {
10416     if (files_charset_info->coll->strnncoll(
10417             files_charset_info, (uchar *)buff2, strlen(buff2),
10418             pointer_cast<const uchar *>(opt_secure_file_priv),
10419             opt_secure_file_priv_len, true))
10420       return false;
10421   }
10422   return true;
10423 }
10424 
10425 /**
10426   check_secure_file_priv_path : Checks path specified through
10427   --secure-file-priv and raises warning in following cases:
10428   1. If path is empty string or NULL and mysqld is not running
10429      with --initialize (bootstrap mode).
10430   2. If path can access data directory
10431   3. If path points to a directory which is accessible by
10432      all OS users (non-Windows build only)
10433 
10434   It throws error in following cases:
10435 
10436   1. If path normalization fails
10437   2. If it can not get stats of the directory
10438 
10439   Assumptions :
10440   1. Data directory path has been normalized
10441   2. opt_secure_file_priv has been normalized unless it is set
10442      to "NULL".
10443 
10444   @returns Status of validation
10445     @retval true : Validation is successful with/without warnings
10446     @retval false : Validation failed. Error is raised.
10447 */
10448 
check_secure_file_priv_path()10449 static bool check_secure_file_priv_path() {
10450   char datadir_buffer[FN_REFLEN + 1] = {0};
10451   char plugindir_buffer[FN_REFLEN + 1] = {0};
10452   char whichdir[20] = {0};
10453   size_t opt_plugindir_len = 0;
10454   size_t opt_datadir_len = 0;
10455   size_t opt_secure_file_priv_len = 0;
10456   bool warn = false;
10457   bool case_insensitive_fs;
10458 #ifndef _WIN32
10459   MY_STAT dir_stat;
10460 #endif
10461 
10462   if (!opt_secure_file_priv[0]) {
10463     if (opt_initialize) {
10464       /*
10465         Do not impose --secure-file-priv restriction
10466         in bootstrap mode
10467       */
10468       LogErr(INFORMATION_LEVEL, ER_SEC_FILE_PRIV_IGNORED);
10469     } else {
10470       LogErr(WARNING_LEVEL, ER_SEC_FILE_PRIV_EMPTY);
10471     }
10472     return true;
10473   }
10474 
10475   /*
10476     Setting --secure-file-priv to NULL would disable
10477     reading/writing from/to file
10478   */
10479   if (!my_strcasecmp(system_charset_info, opt_secure_file_priv, "NULL")) {
10480     LogErr(INFORMATION_LEVEL, ER_SEC_FILE_PRIV_NULL);
10481     return true;
10482   }
10483 
10484   /*
10485     Check if --secure-file-priv can access data directory
10486   */
10487   opt_secure_file_priv_len = strlen(opt_secure_file_priv);
10488 
10489   /*
10490     Adds dir seperator at the end.
10491     This is required in subsequent comparison
10492   */
10493   convert_dirname(datadir_buffer, mysql_unpacked_real_data_home, NullS);
10494   opt_datadir_len = strlen(datadir_buffer);
10495 
10496   case_insensitive_fs = (test_if_case_insensitive(datadir_buffer) == 1);
10497 
10498   if (!case_insensitive_fs) {
10499     if (!strncmp(datadir_buffer, opt_secure_file_priv,
10500                  opt_datadir_len < opt_secure_file_priv_len
10501                      ? opt_datadir_len
10502                      : opt_secure_file_priv_len)) {
10503       warn = true;
10504       strcpy(whichdir, "Data directory");
10505     }
10506   } else {
10507     if (!files_charset_info->coll->strnncoll(
10508             files_charset_info, (uchar *)datadir_buffer, opt_datadir_len,
10509             pointer_cast<const uchar *>(opt_secure_file_priv),
10510             opt_secure_file_priv_len, true)) {
10511       warn = true;
10512       strcpy(whichdir, "Data directory");
10513     }
10514   }
10515 
10516   /*
10517     Don't bother comparing --secure-file-priv with --plugin-dir
10518     if we already have a match against --datdir or
10519     --plugin-dir is not pointing to a valid directory.
10520   */
10521   if (!warn && !my_realpath(plugindir_buffer, opt_plugin_dir, 0)) {
10522     convert_dirname(plugindir_buffer, plugindir_buffer, NullS);
10523     opt_plugindir_len = strlen(plugindir_buffer);
10524 
10525     if (!case_insensitive_fs) {
10526       if (!strncmp(plugindir_buffer, opt_secure_file_priv,
10527                    opt_plugindir_len < opt_secure_file_priv_len
10528                        ? opt_plugindir_len
10529                        : opt_secure_file_priv_len)) {
10530         warn = true;
10531         strcpy(whichdir, "Plugin directory");
10532       }
10533     } else {
10534       if (!files_charset_info->coll->strnncoll(
10535               files_charset_info, (uchar *)plugindir_buffer, opt_plugindir_len,
10536               pointer_cast<const uchar *>(opt_secure_file_priv),
10537               opt_secure_file_priv_len, true)) {
10538         warn = true;
10539         strcpy(whichdir, "Plugin directory");
10540       }
10541     }
10542   }
10543 
10544   if (warn)
10545     LogErr(WARNING_LEVEL, ER_SEC_FILE_PRIV_DIRECTORY_INSECURE, whichdir);
10546 
10547 #ifndef _WIN32
10548   /*
10549      Check for --secure-file-priv directory's permission
10550   */
10551   if (!(my_stat(opt_secure_file_priv, &dir_stat, MYF(0)))) {
10552     LogErr(ERROR_LEVEL, ER_SEC_FILE_PRIV_CANT_STAT);
10553     return false;
10554   }
10555 
10556   if (dir_stat.st_mode & S_IRWXO)
10557     LogErr(WARNING_LEVEL, ER_SEC_FILE_PRIV_DIRECTORY_PERMISSIONS);
10558 #endif
10559   return true;
10560 }
10561 
fix_paths(void)10562 static int fix_paths(void) {
10563   char buff[FN_REFLEN];
10564   bool secure_file_priv_nonempty = false;
10565   convert_dirname(mysql_home, mysql_home, NullS);
10566   /* Resolve symlinks to allow 'mysql_home' to be a relative symlink */
10567   my_realpath(mysql_home, mysql_home, MYF(0));
10568   /* Ensure that mysql_home ends in FN_LIBCHAR */
10569   char *pos = strend(mysql_home);
10570   if (pos == mysql_home || pos[-1] != FN_LIBCHAR) {
10571     pos[0] = FN_LIBCHAR;
10572     pos[1] = 0;
10573   }
10574   convert_dirname(lc_messages_dir, lc_messages_dir, NullS);
10575   convert_dirname(mysql_real_data_home, mysql_real_data_home, NullS);
10576   (void)my_load_path(mysql_home, mysql_home, "");  // Resolve current dir
10577   (void)my_load_path(mysql_real_data_home, mysql_real_data_home, mysql_home);
10578   (void)my_load_path(pidfile_name, pidfile_name_ptr, mysql_real_data_home);
10579 
10580   convert_dirname(
10581       opt_plugin_dir,
10582       opt_plugin_dir_ptr ? opt_plugin_dir_ptr : get_relative_path(PLUGINDIR),
10583       NullS);
10584   (void)my_load_path(opt_plugin_dir, opt_plugin_dir, mysql_home);
10585   opt_plugin_dir_ptr = opt_plugin_dir;
10586 
10587   my_realpath(mysql_unpacked_real_data_home, mysql_real_data_home, MYF(0));
10588   mysql_unpacked_real_data_home_len = strlen(mysql_unpacked_real_data_home);
10589   if (mysql_unpacked_real_data_home[mysql_unpacked_real_data_home_len - 1] ==
10590       FN_LIBCHAR)
10591     --mysql_unpacked_real_data_home_len;
10592 
10593   const char *sharedir = get_relative_path(SHAREDIR);
10594   if (test_if_hard_path(sharedir))
10595     strmake(buff, sharedir, sizeof(buff) - 1); /* purecov: tested */
10596   else
10597     strxnmov(buff, sizeof(buff) - 1, mysql_home, sharedir, NullS);
10598   convert_dirname(buff, buff, NullS);
10599   (void)my_load_path(lc_messages_dir, lc_messages_dir, buff);
10600 
10601   /* If --character-sets-dir isn't given, use shared library dir */
10602   if (charsets_dir)
10603     strmake(mysql_charsets_dir, charsets_dir, sizeof(mysql_charsets_dir) - 1);
10604   else
10605     strxnmov(mysql_charsets_dir, sizeof(mysql_charsets_dir) - 1, buff,
10606              CHARSET_DIR, NullS);
10607   (void)my_load_path(mysql_charsets_dir, mysql_charsets_dir, buff);
10608   convert_dirname(mysql_charsets_dir, mysql_charsets_dir, NullS);
10609   charsets_dir = mysql_charsets_dir;
10610 
10611   if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir)) return 1;
10612   if (!opt_mysql_tmpdir) opt_mysql_tmpdir = mysql_tmpdir;
10613   if (!slave_load_tmpdir) slave_load_tmpdir = mysql_tmpdir;
10614 
10615   if (opt_help) return 0;
10616   /*
10617     Convert the secure-file-priv option to system format, allowing
10618     a quick strcmp to check if read or write is in an allowed dir
10619   */
10620   if (opt_initialize) opt_secure_file_priv = "";
10621   secure_file_priv_nonempty = opt_secure_file_priv[0] ? true : false;
10622 
10623   if (secure_file_priv_nonempty && strlen(opt_secure_file_priv) > FN_REFLEN) {
10624     LogErr(WARNING_LEVEL, ER_SEC_FILE_PRIV_ARGUMENT_TOO_LONG, FN_REFLEN - 1);
10625     return 1;
10626   }
10627 
10628   memset(buff, 0, sizeof(buff));
10629   if (secure_file_priv_nonempty &&
10630       my_strcasecmp(system_charset_info, opt_secure_file_priv, "NULL")) {
10631     int retval = my_realpath(buff, opt_secure_file_priv, MYF(MY_WME));
10632     if (!retval) {
10633       convert_dirname(secure_file_real_path, buff, NullS);
10634 #ifdef WIN32
10635       MY_DIR *dir = my_dir(secure_file_real_path, MYF(MY_DONT_SORT + MY_WME));
10636       if (!dir) {
10637         retval = 1;
10638       } else {
10639         my_dirend(dir);
10640       }
10641 #endif
10642     }
10643 
10644     if (retval) {
10645       LogErr(ERROR_LEVEL, ER_SEC_FILE_PRIV_CANT_ACCESS_DIR,
10646              opt_secure_file_priv);
10647       return 1;
10648     }
10649     opt_secure_file_priv = secure_file_real_path;
10650   }
10651 
10652   if (!check_secure_file_priv_path()) return 1;
10653 
10654   return 0;
10655 }
10656 
10657 /**
10658   Check if file system used for databases is case insensitive.
10659 
10660   @param dir_name     Directory to test
10661 
10662   @retval
10663     -1  Don't know (Test failed)
10664   @retval
10665     0   File system is case sensitive
10666   @retval
10667     1   File system is case insensitive
10668 */
10669 
test_if_case_insensitive(const char * dir_name)10670 static int test_if_case_insensitive(const char *dir_name) {
10671   int result = 0;
10672   File file;
10673   char buff[FN_REFLEN], buff2[FN_REFLEN];
10674   MY_STAT stat_info;
10675   const char *const tmp_file_name = "mysqld_tmp_file_case_insensitive_test";
10676   DBUG_TRACE;
10677 
10678   fn_format(buff, tmp_file_name, dir_name, ".lower-test",
10679             MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR);
10680   fn_format(buff2, tmp_file_name, dir_name, ".LOWER-TEST",
10681             MY_UNPACK_FILENAME | MY_REPLACE_EXT | MY_REPLACE_DIR);
10682   mysql_file_delete(key_file_casetest, buff2, MYF(0));
10683   if ((file = mysql_file_create(key_file_casetest, buff, 0666, O_RDWR,
10684                                 MYF(0))) < 0) {
10685     LogErr(WARNING_LEVEL, ER_CANT_CREATE_TEST_FILE, buff);
10686     return -1;
10687   }
10688   mysql_file_close(file, MYF(0));
10689   if (mysql_file_stat(key_file_casetest, buff2, &stat_info, MYF(0)))
10690     result = 1;  // Can access file
10691   mysql_file_delete(key_file_casetest, buff, MYF(MY_WME));
10692   DBUG_PRINT("exit", ("result: %d", result));
10693   return result;
10694 }
10695 
10696 /**
10697   Create file to store pid number.
10698 */
create_pid_file()10699 static bool create_pid_file() {
10700   File file;
10701   bool check_parent_path = true, is_path_accessible = true;
10702   char pid_filepath[FN_REFLEN], *pos = nullptr;
10703   /* Copy pid file name to get pid file path */
10704   strcpy(pid_filepath, pidfile_name);
10705 
10706   /* Iterate through the entire path to check if even one of the sub-dirs
10707      is world-writable */
10708   while (check_parent_path && (pos = strrchr(pid_filepath, FN_LIBCHAR)) &&
10709          (pos != pid_filepath)) /* shouldn't check root */
10710   {
10711     *pos = '\0'; /* Trim the inner-most dir */
10712     switch (is_file_or_dir_world_writable(pid_filepath)) {
10713       case -2:
10714         is_path_accessible = false;
10715         break;
10716       case -1:
10717         LogErr(ERROR_LEVEL, ER_CANT_CHECK_PID_PATH, strerror(errno));
10718         exit(MYSQLD_ABORT_EXIT);
10719       case 1:
10720         LogErr(WARNING_LEVEL, ER_PID_FILE_PRIV_DIRECTORY_INSECURE,
10721                pid_filepath);
10722         check_parent_path = false;
10723         break;
10724       case 0:
10725         continue; /* Keep checking the parent dir */
10726     }
10727   }
10728   if (!is_path_accessible) {
10729     LogErr(WARNING_LEVEL, ER_PID_FILEPATH_LOCATIONS_INACCESSIBLE);
10730   }
10731   if ((file = mysql_file_create(key_file_pid, pidfile_name, 0664,
10732                                 O_WRONLY | O_TRUNC, MYF(MY_WME))) >= 0) {
10733     char buff[MAX_BIGINT_WIDTH + 1], *end;
10734     end = longlong10_to_str(getpid(), buff, -10);
10735     *end++ = '\n';
10736     if (!mysql_file_write(file, (uchar *)buff, (uint)(end - buff),
10737                           MYF(MY_WME | MY_NABP))) {
10738       mysql_file_close(file, MYF(0));
10739       pid_file_created = true;
10740       return false;
10741     }
10742     mysql_file_close(file, MYF(0));
10743   }
10744   LogErr(ERROR_LEVEL, ER_CANT_CREATE_PID_FILE, strerror(errno));
10745   return true;
10746 }
10747 
10748 /**
10749   Remove the process' pid file.
10750 
10751   @param  flags  file operation flags
10752 */
10753 
delete_pid_file(myf flags)10754 static void delete_pid_file(myf flags) {
10755   File file;
10756   if (opt_initialize || !pid_file_created ||
10757       !(file = mysql_file_open(key_file_pid, pidfile_name, O_RDONLY, flags)))
10758     return;
10759 
10760   if (file == -1) {
10761     LogErr(INFORMATION_LEVEL, ER_CANT_REMOVE_PID_FILE, strerror(errno));
10762     return;
10763   }
10764 
10765   uchar buff[MAX_BIGINT_WIDTH + 1];
10766   /* Make sure that the pid file was created by the same process. */
10767   size_t error = mysql_file_read(file, buff, sizeof(buff), flags);
10768   mysql_file_close(file, flags);
10769   buff[sizeof(buff) - 1] = '\0';
10770   if (error != MY_FILE_ERROR && atol((char *)buff) == (long)getpid()) {
10771     mysql_file_delete(key_file_pid, pidfile_name, flags);
10772     pid_file_created = false;
10773   }
10774   return;
10775 }
10776 
10777 /**
10778   Delete mysql.ibd after aborting upgrade.
10779 */
delete_dictionary_tablespace()10780 static void delete_dictionary_tablespace() {
10781   char path[FN_REFLEN + 1];
10782   bool not_used;
10783 
10784   build_table_filename(path, sizeof(path) - 1, "", "mysql", ".ibd", 0,
10785                        &not_used);
10786   (void)mysql_file_delete(key_file_misc, path, MYF(MY_WME));
10787 
10788   // Drop file which tracks progress of upgrade.
10789   dd::upgrade_57::Upgrade_status().remove();
10790 }
10791 
10792 /**
10793   Returns the current state of the server : booting, operational or shutting
10794   down.
10795 
10796   @return
10797     SERVER_BOOTING        Server is not operational. It is starting.
10798     SERVER_OPERATING      Server is fully initialized and operating.
10799     SERVER_SHUTTING_DOWN  Server is shutting down.
10800 */
get_server_state()10801 enum_server_operational_state get_server_state() {
10802   return server_operational_state;
10803 }
10804 
10805 /**
10806   Reset status for all threads.
10807 */
10808 class Reset_thd_status : public Do_THD_Impl {
10809  public:
Reset_thd_status()10810   Reset_thd_status() {}
operator ()(THD * thd)10811   virtual void operator()(THD *thd) {
10812     /* Update the global status if not done so already. */
10813     if (!thd->status_var_aggregated) {
10814       add_to_status(&global_status_var, &thd->status_var);
10815     }
10816     reset_system_status_vars(&thd->status_var);
10817   }
10818 };
10819 
10820 /**
10821   Reset global and session status variables.
10822 */
refresh_status()10823 void refresh_status() {
10824   mysql_mutex_lock(&LOCK_status);
10825 
10826   /* For all threads, add status to global status and then reset. */
10827   Reset_thd_status reset_thd_status;
10828   Global_THD_manager::get_instance()->do_for_all_thd_copy(&reset_thd_status);
10829 #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
10830   /* Reset aggregated status counters. */
10831   reset_pfs_status_stats();
10832 #endif
10833 
10834   /* Reset some global variables. */
10835   reset_status_vars();
10836 
10837   /* Reset the counters of all key caches (default and named). */
10838   process_key_caches(reset_key_cache_counters);
10839   flush_status_time = time((time_t *)nullptr);
10840   mysql_mutex_unlock(&LOCK_status);
10841 
10842   /*
10843     Set max_used_connections to the number of currently open
10844     connections.  Do this out of LOCK_status to avoid deadlocks.
10845     Status reset becomes not atomic, but status data is not exact anyway.
10846   */
10847   Connection_handler_manager::reset_max_used_connections();
10848 }
10849 
10850 /*****************************************************************************
10851   Instantiate variables for missing storage engines
10852   This section should go away soon
10853 *****************************************************************************/
10854 
10855 #ifdef HAVE_PSI_INTERFACE
10856 PSI_mutex_key key_LOCK_tc;
10857 PSI_mutex_key key_hash_filo_lock;
10858 PSI_mutex_key key_LOCK_error_log;
10859 PSI_mutex_key key_LOCK_thd_data;
10860 PSI_mutex_key key_LOCK_thd_sysvar;
10861 PSI_mutex_key key_LOCK_thd_protocol;
10862 PSI_mutex_key key_LOG_LOCK_log;
10863 PSI_mutex_key key_master_info_data_lock;
10864 PSI_mutex_key key_master_info_run_lock;
10865 PSI_mutex_key key_master_info_sleep_lock;
10866 PSI_mutex_key key_master_info_thd_lock;
10867 PSI_mutex_key key_master_info_rotate_lock;
10868 PSI_mutex_key key_mutex_slave_reporting_capability_err_lock;
10869 PSI_mutex_key key_relay_log_info_data_lock;
10870 PSI_mutex_key key_relay_log_info_sleep_lock;
10871 PSI_mutex_key key_relay_log_info_thd_lock;
10872 PSI_mutex_key key_relay_log_info_log_space_lock;
10873 PSI_mutex_key key_relay_log_info_run_lock;
10874 PSI_mutex_key key_mutex_slave_parallel_pend_jobs;
10875 PSI_mutex_key key_mutex_slave_parallel_worker_count;
10876 PSI_mutex_key key_mutex_slave_parallel_worker;
10877 PSI_mutex_key key_structure_guard_mutex;
10878 PSI_mutex_key key_TABLE_SHARE_LOCK_ha_data;
10879 PSI_mutex_key key_LOCK_query_plan;
10880 PSI_mutex_key key_LOCK_thd_query;
10881 PSI_mutex_key key_LOCK_cost_const;
10882 PSI_mutex_key key_LOCK_current_cond;
10883 PSI_mutex_key key_RELAYLOG_LOCK_commit;
10884 PSI_mutex_key key_RELAYLOG_LOCK_commit_queue;
10885 PSI_mutex_key key_RELAYLOG_LOCK_done;
10886 PSI_mutex_key key_RELAYLOG_LOCK_flush_queue;
10887 PSI_mutex_key key_RELAYLOG_LOCK_index;
10888 PSI_mutex_key key_RELAYLOG_LOCK_log;
10889 PSI_mutex_key key_RELAYLOG_LOCK_log_end_pos;
10890 PSI_mutex_key key_RELAYLOG_LOCK_sync;
10891 PSI_mutex_key key_RELAYLOG_LOCK_sync_queue;
10892 PSI_mutex_key key_RELAYLOG_LOCK_xids;
10893 PSI_mutex_key key_gtid_ensure_index_mutex;
10894 PSI_mutex_key key_object_cache_mutex;  // TODO need to initialize
10895 PSI_cond_key key_object_loading_cond;  // TODO need to initialize
10896 PSI_mutex_key key_mts_temp_table_LOCK;
10897 PSI_mutex_key key_mts_gaq_LOCK;
10898 PSI_mutex_key key_thd_timer_mutex;
10899 PSI_mutex_key key_commit_order_manager_mutex;
10900 PSI_mutex_key key_mutex_slave_worker_hash;
10901 
10902 /* clang-format off */
10903 static PSI_mutex_info all_server_mutexes[]=
10904 {
10905   { &key_LOCK_tc, "TC_LOG_MMAP::LOCK_tc", 0, 0, PSI_DOCUMENT_ME},
10906   { &key_BINLOG_LOCK_commit, "MYSQL_BIN_LOG::LOCK_commit", 0, 0, PSI_DOCUMENT_ME},
10907   { &key_BINLOG_LOCK_commit_queue, "MYSQL_BIN_LOG::LOCK_commit_queue", 0, 0, PSI_DOCUMENT_ME},
10908   { &key_BINLOG_LOCK_done, "MYSQL_BIN_LOG::LOCK_done", 0, 0, PSI_DOCUMENT_ME},
10909   { &key_BINLOG_LOCK_flush_queue, "MYSQL_BIN_LOG::LOCK_flush_queue", 0, 0, PSI_DOCUMENT_ME},
10910   { &key_BINLOG_LOCK_index, "MYSQL_BIN_LOG::LOCK_index", 0, 0, PSI_DOCUMENT_ME},
10911   { &key_BINLOG_LOCK_log, "MYSQL_BIN_LOG::LOCK_log", 0, 0, PSI_DOCUMENT_ME},
10912   { &key_BINLOG_LOCK_binlog_end_pos, "MYSQL_BIN_LOG::LOCK_binlog_end_pos", 0, 0, PSI_DOCUMENT_ME},
10913   { &key_BINLOG_LOCK_sync, "MYSQL_BIN_LOG::LOCK_sync", 0, 0, PSI_DOCUMENT_ME},
10914   { &key_BINLOG_LOCK_sync_queue, "MYSQL_BIN_LOG::LOCK_sync_queue", 0, 0, PSI_DOCUMENT_ME},
10915   { &key_BINLOG_LOCK_xids, "MYSQL_BIN_LOG::LOCK_xids", 0, 0, PSI_DOCUMENT_ME},
10916   { &key_RELAYLOG_LOCK_commit, "MYSQL_RELAY_LOG::LOCK_commit", 0, 0, PSI_DOCUMENT_ME},
10917   { &key_RELAYLOG_LOCK_commit_queue, "MYSQL_RELAY_LOG::LOCK_commit_queue", 0, 0, PSI_DOCUMENT_ME},
10918   { &key_RELAYLOG_LOCK_done, "MYSQL_RELAY_LOG::LOCK_done", 0, 0, PSI_DOCUMENT_ME},
10919   { &key_RELAYLOG_LOCK_flush_queue, "MYSQL_RELAY_LOG::LOCK_flush_queue", 0, 0, PSI_DOCUMENT_ME},
10920   { &key_RELAYLOG_LOCK_index, "MYSQL_RELAY_LOG::LOCK_index", 0, 0, PSI_DOCUMENT_ME},
10921   { &key_RELAYLOG_LOCK_log, "MYSQL_RELAY_LOG::LOCK_log", 0, 0, PSI_DOCUMENT_ME},
10922   { &key_RELAYLOG_LOCK_log_end_pos, "MYSQL_RELAY_LOG::LOCK_log_end_pos", 0, 0, PSI_DOCUMENT_ME},
10923   { &key_RELAYLOG_LOCK_sync, "MYSQL_RELAY_LOG::LOCK_sync", 0, 0, PSI_DOCUMENT_ME},
10924   { &key_RELAYLOG_LOCK_sync_queue, "MYSQL_RELAY_LOG::LOCK_sync_queue", 0, 0, PSI_DOCUMENT_ME},
10925   { &key_RELAYLOG_LOCK_xids, "MYSQL_RELAY_LOG::LOCK_xids", 0, 0, PSI_DOCUMENT_ME},
10926   { &key_hash_filo_lock, "hash_filo::lock", 0, 0, PSI_DOCUMENT_ME},
10927   { &Gtid_set::key_gtid_executed_free_intervals_mutex, "Gtid_set::gtid_executed::free_intervals_mutex", 0, 0, PSI_DOCUMENT_ME},
10928   { &key_LOCK_crypt, "LOCK_crypt", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10929   { &key_LOCK_error_log, "LOCK_error_log", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10930   { &key_LOCK_global_system_variables, "LOCK_global_system_variables", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10931 #if defined(_WIN32)
10932   { &key_LOCK_handler_count, "LOCK_handler_count", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10933 #endif
10934   { &key_LOCK_manager, "LOCK_manager", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10935   { &key_LOCK_prepared_stmt_count, "LOCK_prepared_stmt_count", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10936   { &key_LOCK_sql_slave_skip_counter, "LOCK_sql_slave_skip_counter", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10937   { &key_LOCK_slave_net_timeout, "LOCK_slave_net_timeout", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10938   { &key_LOCK_slave_trans_dep_tracker, "LOCK_slave_trans_dep_tracker", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10939   { &key_LOCK_server_started, "LOCK_server_started", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10940 #if !defined(_WIN32)
10941   { &key_LOCK_socket_listener_active, "LOCK_socket_listener_active", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10942   { &key_LOCK_start_signal_handler, "LOCK_start_signal_handler", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10943 #endif
10944   { &key_LOCK_status, "LOCK_status", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10945   { &key_LOCK_thd_data, "THD::LOCK_thd_data", 0, PSI_VOLATILITY_SESSION, PSI_DOCUMENT_ME},
10946   { &key_LOCK_thd_query, "THD::LOCK_thd_query", 0, PSI_VOLATILITY_SESSION, PSI_DOCUMENT_ME},
10947   { &key_LOCK_thd_sysvar, "THD::LOCK_thd_sysvar", 0, PSI_VOLATILITY_SESSION, PSI_DOCUMENT_ME},
10948   { &key_LOCK_thd_protocol, "THD::LOCK_thd_protocol", 0, PSI_VOLATILITY_SESSION, PSI_DOCUMENT_ME},
10949   { &key_LOCK_user_conn, "LOCK_user_conn", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10950   { &key_LOCK_uuid_generator, "LOCK_uuid_generator", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10951   { &key_LOCK_sql_rand, "LOCK_sql_rand", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10952   { &key_LOG_LOCK_log, "LOG::LOCK_log", 0, 0, PSI_DOCUMENT_ME},
10953   { &key_master_info_data_lock, "Master_info::data_lock", 0, 0, PSI_DOCUMENT_ME},
10954   { &key_master_info_run_lock, "Master_info::run_lock", 0, 0, PSI_DOCUMENT_ME},
10955   { &key_master_info_sleep_lock, "Master_info::sleep_lock", 0, 0, PSI_DOCUMENT_ME},
10956   { &key_master_info_thd_lock, "Master_info::info_thd_lock", 0, 0, PSI_DOCUMENT_ME},
10957   { &key_master_info_rotate_lock, "Master_info::rotate_lock", 0, 0, PSI_DOCUMENT_ME},
10958   { &key_mutex_slave_reporting_capability_err_lock, "Slave_reporting_capability::err_lock", 0, 0, PSI_DOCUMENT_ME},
10959   { &key_relay_log_info_data_lock, "Relay_log_info::data_lock", 0, 0, PSI_DOCUMENT_ME},
10960   { &key_relay_log_info_sleep_lock, "Relay_log_info::sleep_lock", 0, 0, PSI_DOCUMENT_ME},
10961   { &key_relay_log_info_thd_lock, "Relay_log_info::info_thd_lock", 0, 0, PSI_DOCUMENT_ME},
10962   { &key_relay_log_info_log_space_lock, "Relay_log_info::log_space_lock", 0, 0, PSI_DOCUMENT_ME},
10963   { &key_relay_log_info_run_lock, "Relay_log_info::run_lock", 0, 0, PSI_DOCUMENT_ME},
10964   { &key_mutex_slave_parallel_pend_jobs, "Relay_log_info::pending_jobs_lock", 0, 0, PSI_DOCUMENT_ME},
10965   { &key_mutex_slave_parallel_worker_count, "Relay_log_info::exit_count_lock", 0, 0, PSI_DOCUMENT_ME},
10966   { &key_mutex_slave_parallel_worker, "Worker_info::jobs_lock", 0, 0, PSI_DOCUMENT_ME},
10967   { &key_TABLE_SHARE_LOCK_ha_data, "TABLE_SHARE::LOCK_ha_data", 0, 0, PSI_DOCUMENT_ME},
10968   { &key_LOCK_error_messages, "LOCK_error_messages", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10969   { &key_LOCK_log_throttle_qni, "LOCK_log_throttle_qni", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10970   { &key_gtid_ensure_index_mutex, "Gtid_state", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10971   { &key_LOCK_query_plan, "THD::LOCK_query_plan", 0, PSI_VOLATILITY_SESSION, PSI_DOCUMENT_ME},
10972   { &key_LOCK_cost_const, "Cost_constant_cache::LOCK_cost_const", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10973   { &key_LOCK_current_cond, "THD::LOCK_current_cond", 0, PSI_VOLATILITY_SESSION, PSI_DOCUMENT_ME},
10974   { &key_mts_temp_table_LOCK, "key_mts_temp_table_LOCK", 0, 0, PSI_DOCUMENT_ME},
10975   { &key_LOCK_reset_gtid_table, "LOCK_reset_gtid_table", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10976   { &key_LOCK_compress_gtid_table, "LOCK_compress_gtid_table", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10977   { &key_LOCK_collect_instance_log, "LOCK_collect_instance_log", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10978   { &key_mts_gaq_LOCK, "key_mts_gaq_LOCK", 0, 0, PSI_DOCUMENT_ME},
10979   { &key_thd_timer_mutex, "thd_timer_mutex", 0, 0, PSI_DOCUMENT_ME},
10980   { &key_commit_order_manager_mutex, "Commit_order_manager::m_mutex", 0, 0, PSI_DOCUMENT_ME},
10981   { &key_mutex_slave_worker_hash, "Relay_log_info::slave_worker_hash_lock", 0, 0, PSI_DOCUMENT_ME},
10982   { &key_LOCK_default_password_lifetime, "LOCK_default_password_lifetime", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10983   { &key_LOCK_mandatory_roles, "LOCK_mandatory_roles", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10984   { &key_LOCK_password_history, "LOCK_password_history", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10985   { &key_LOCK_password_reuse_interval, "LOCK_password_reuse_interval", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10986   { &key_LOCK_keyring_operations, "LOCK_keyring_operations", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
10987   { &key_LOCK_tls_ctx_options, "LOCK_tls_ctx_options", 0, 0, "A lock to control all of the --ssl-* CTX related command line options for client server connection port"},
10988   { &key_LOCK_admin_tls_ctx_options, "LOCK_admin_tls_ctx_options", 0, 0, "A lock to control all of the --ssl-* CTX related command line options for administrative connection port"},
10989   { &key_LOCK_rotate_binlog_master_key, "LOCK_rotate_binlog_master_key", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME}
10990 };
10991 /* clang-format on */
10992 
10993 PSI_rwlock_key key_rwlock_LOCK_logger;
10994 PSI_rwlock_key key_rwlock_channel_map_lock;
10995 PSI_rwlock_key key_rwlock_channel_lock;
10996 PSI_rwlock_key key_rwlock_receiver_sid_lock;
10997 PSI_rwlock_key key_rwlock_rpl_filter_lock;
10998 PSI_rwlock_key key_rwlock_channel_to_filter_lock;
10999 
11000 PSI_rwlock_key key_rwlock_Trans_delegate_lock;
11001 PSI_rwlock_key key_rwlock_Server_state_delegate_lock;
11002 PSI_rwlock_key key_rwlock_Binlog_storage_delegate_lock;
11003 PSI_rwlock_key key_rwlock_Binlog_transmit_delegate_lock;
11004 PSI_rwlock_key key_rwlock_Binlog_relay_IO_delegate_lock;
11005 PSI_rwlock_key key_rwlock_resource_group_mgr_map_lock;
11006 
11007 /* clang-format off */
11008 static PSI_rwlock_info all_server_rwlocks[]=
11009 {
11010   { &key_rwlock_Binlog_transmit_delegate_lock, "Binlog_transmit_delegate::lock", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11011   { &key_rwlock_Binlog_relay_IO_delegate_lock, "Binlog_relay_IO_delegate::lock", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11012   { &key_rwlock_LOCK_logger, "LOGGER::LOCK_logger", 0, 0, PSI_DOCUMENT_ME},
11013   { &key_rwlock_LOCK_sys_init_connect, "LOCK_sys_init_connect", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11014   { &key_rwlock_LOCK_sys_init_slave, "LOCK_sys_init_slave", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11015   { &key_rwlock_LOCK_system_variables_hash, "LOCK_system_variables_hash", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11016   { &key_rwlock_global_sid_lock, "gtid_commit_rollback", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11017   { &key_rwlock_gtid_mode_lock, "gtid_mode_lock", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11018   { &key_rwlock_channel_map_lock, "channel_map_lock", 0, 0, PSI_DOCUMENT_ME},
11019   { &key_rwlock_channel_lock, "channel_lock", 0, 0, PSI_DOCUMENT_ME},
11020   { &key_rwlock_Trans_delegate_lock, "Trans_delegate::lock", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11021   { &key_rwlock_Server_state_delegate_lock, "Server_state_delegate::lock", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11022   { &key_rwlock_Binlog_storage_delegate_lock, "Binlog_storage_delegate::lock", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11023   { &key_rwlock_receiver_sid_lock, "gtid_retrieved", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11024   { &key_rwlock_rpl_filter_lock, "rpl_filter_lock", 0, 0, PSI_DOCUMENT_ME},
11025   { &key_rwlock_channel_to_filter_lock, "channel_to_filter_lock", 0, 0, PSI_DOCUMENT_ME},
11026   { &key_rwlock_resource_group_mgr_map_lock, "Resource_group_mgr::m_map_rwlock", 0, 0, PSI_DOCUMENT_ME},
11027 #ifdef _WIN32
11028   { &key_rwlock_LOCK_named_pipe_full_access_group, "LOCK_named_pipe_full_access_group", PSI_FLAG_SINGLETON, 0,
11029      "This lock protects named pipe security attributes, preventing their "
11030      "simultaneous application and modification."},
11031 #endif // _WIN32
11032 };
11033 /* clang-format on */
11034 
11035 PSI_cond_key key_PAGE_cond;
11036 PSI_cond_key key_COND_active;
11037 PSI_cond_key key_COND_pool;
11038 PSI_cond_key key_COND_cache_status_changed;
11039 PSI_cond_key key_item_func_sleep_cond;
11040 PSI_cond_key key_master_info_data_cond;
11041 PSI_cond_key key_master_info_start_cond;
11042 PSI_cond_key key_master_info_stop_cond;
11043 PSI_cond_key key_master_info_sleep_cond;
11044 PSI_cond_key key_master_info_rotate_cond;
11045 PSI_cond_key key_relay_log_info_data_cond;
11046 PSI_cond_key key_relay_log_info_log_space_cond;
11047 PSI_cond_key key_relay_log_info_start_cond;
11048 PSI_cond_key key_relay_log_info_stop_cond;
11049 PSI_cond_key key_relay_log_info_sleep_cond;
11050 PSI_cond_key key_cond_slave_parallel_pend_jobs;
11051 PSI_cond_key key_cond_slave_parallel_worker;
11052 PSI_cond_key key_cond_mts_gaq;
11053 PSI_cond_key key_RELAYLOG_update_cond;
11054 PSI_cond_key key_RELAYLOG_COND_done;
11055 PSI_cond_key key_RELAYLOG_prep_xids_cond;
11056 PSI_cond_key key_gtid_ensure_index_cond;
11057 PSI_cond_key key_COND_thr_lock;
11058 PSI_cond_key key_commit_order_manager_cond;
11059 PSI_cond_key key_cond_slave_worker_hash;
11060 
11061 /* clang-format off */
11062 static PSI_cond_info all_server_conds[]=
11063 {
11064   { &key_PAGE_cond, "PAGE::cond", 0, 0, PSI_DOCUMENT_ME},
11065   { &key_COND_active, "TC_LOG_MMAP::COND_active", 0, 0, PSI_DOCUMENT_ME},
11066   { &key_COND_pool, "TC_LOG_MMAP::COND_pool", 0, 0, PSI_DOCUMENT_ME},
11067   { &key_BINLOG_COND_done, "MYSQL_BIN_LOG::COND_done", 0, 0, PSI_DOCUMENT_ME},
11068   { &key_BINLOG_update_cond, "MYSQL_BIN_LOG::update_cond", 0, 0, PSI_DOCUMENT_ME},
11069   { &key_BINLOG_prep_xids_cond, "MYSQL_BIN_LOG::prep_xids_cond", 0, 0, PSI_DOCUMENT_ME},
11070   { &key_RELAYLOG_COND_done, "MYSQL_RELAY_LOG::COND_done", 0, 0, PSI_DOCUMENT_ME},
11071   { &key_RELAYLOG_update_cond, "MYSQL_RELAY_LOG::update_cond", 0, 0, PSI_DOCUMENT_ME},
11072   { &key_RELAYLOG_prep_xids_cond, "MYSQL_RELAY_LOG::prep_xids_cond", 0, 0, PSI_DOCUMENT_ME},
11073 #if defined(_WIN32)
11074   { &key_COND_handler_count, "COND_handler_count", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11075 #endif
11076   { &key_COND_manager, "COND_manager", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11077   { &key_COND_server_started, "COND_server_started", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11078 #if !defined(_WIN32)
11079   { &key_COND_socket_listener_active, "COND_socket_listener_active", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11080   { &key_COND_start_signal_handler, "COND_start_signal_handler", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11081 #endif
11082   { &key_COND_thr_lock, "COND_thr_lock", 0, 0, PSI_DOCUMENT_ME},
11083   { &key_item_func_sleep_cond, "Item_func_sleep::cond", 0, 0, PSI_DOCUMENT_ME},
11084   { &key_master_info_data_cond, "Master_info::data_cond", 0, 0, PSI_DOCUMENT_ME},
11085   { &key_master_info_start_cond, "Master_info::start_cond", 0, 0, PSI_DOCUMENT_ME},
11086   { &key_master_info_stop_cond, "Master_info::stop_cond", 0, 0, PSI_DOCUMENT_ME},
11087   { &key_master_info_sleep_cond, "Master_info::sleep_cond", 0, 0, PSI_DOCUMENT_ME},
11088   { &key_master_info_rotate_cond, "Master_info::rotate_cond", 0, 0, PSI_DOCUMENT_ME},
11089   { &key_relay_log_info_data_cond, "Relay_log_info::data_cond", 0, 0, PSI_DOCUMENT_ME},
11090   { &key_relay_log_info_log_space_cond, "Relay_log_info::log_space_cond", 0, 0, PSI_DOCUMENT_ME},
11091   { &key_relay_log_info_start_cond, "Relay_log_info::start_cond", 0, 0, PSI_DOCUMENT_ME},
11092   { &key_relay_log_info_stop_cond, "Relay_log_info::stop_cond", 0, 0, PSI_DOCUMENT_ME},
11093   { &key_relay_log_info_sleep_cond, "Relay_log_info::sleep_cond", 0, 0, PSI_DOCUMENT_ME},
11094   { &key_cond_slave_parallel_pend_jobs, "Relay_log_info::pending_jobs_cond", 0, 0, PSI_DOCUMENT_ME},
11095   { &key_cond_slave_parallel_worker, "Worker_info::jobs_cond", 0, 0, PSI_DOCUMENT_ME},
11096   { &key_cond_mts_gaq, "Relay_log_info::mts_gaq_cond", 0, 0, PSI_DOCUMENT_ME},
11097   { &key_gtid_ensure_index_cond, "Gtid_state", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11098   { &key_COND_compress_gtid_table, "COND_compress_gtid_table", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11099   { &key_commit_order_manager_cond, "Commit_order_manager::m_workers.cond", 0, 0, PSI_DOCUMENT_ME},
11100   { &key_cond_slave_worker_hash, "Relay_log_info::slave_worker_hash_lock", 0, 0, PSI_DOCUMENT_ME}
11101 };
11102 /* clang-format on */
11103 
11104 PSI_thread_key key_thread_bootstrap;
11105 PSI_thread_key key_thread_handle_manager;
11106 PSI_thread_key key_thread_one_connection;
11107 PSI_thread_key key_thread_compress_gtid_table;
11108 PSI_thread_key key_thread_parser_service;
11109 PSI_thread_key key_thread_handle_con_admin_sockets;
11110 
11111 /* clang-format off */
11112 static PSI_thread_info all_server_threads[]=
11113 {
11114 #if defined (_WIN32)
11115   { &key_thread_handle_con_namedpipes, "con_named_pipes", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11116   { &key_thread_handle_con_sharedmem, "con_shared_mem", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11117   { &key_thread_handle_con_sockets, "con_sockets", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11118   { &key_thread_handle_shutdown_restart, "shutdown_restart", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11119 #endif /* _WIN32 */
11120   { &key_thread_bootstrap, "bootstrap", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11121   { &key_thread_handle_manager, "manager", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11122   { &key_thread_main, "main", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11123   { &key_thread_one_connection, "one_connection", PSI_FLAG_USER, 0, PSI_DOCUMENT_ME},
11124   { &key_thread_signal_hand, "signal_handler", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11125   { &key_thread_compress_gtid_table, "compress_gtid_table", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11126   { &key_thread_parser_service, "parser_service", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11127   { &key_thread_handle_con_admin_sockets, "admin_interface", PSI_FLAG_USER, 0, PSI_DOCUMENT_ME},
11128 };
11129 /* clang-format on */
11130 
11131 PSI_file_key key_file_binlog;
11132 PSI_file_key key_file_binlog_index;
11133 PSI_file_key key_file_dbopt;
11134 PSI_file_key key_file_ERRMSG;
11135 PSI_file_key key_select_to_file;
11136 PSI_file_key key_file_fileparser;
11137 PSI_file_key key_file_frm;
11138 PSI_file_key key_file_load;
11139 PSI_file_key key_file_loadfile;
11140 PSI_file_key key_file_log_event_data;
11141 PSI_file_key key_file_log_event_info;
11142 PSI_file_key key_file_misc;
11143 PSI_file_key key_file_tclog;
11144 PSI_file_key key_file_trg;
11145 PSI_file_key key_file_trn;
11146 PSI_file_key key_file_init;
11147 PSI_file_key key_file_general_log;
11148 PSI_file_key key_file_slow_log;
11149 PSI_file_key key_file_relaylog;
11150 PSI_file_key key_file_relaylog_cache;
11151 PSI_file_key key_file_relaylog_index;
11152 PSI_file_key key_file_relaylog_index_cache;
11153 PSI_file_key key_file_sdi;
11154 PSI_file_key key_file_hash_join;
11155 
11156 /* clang-format off */
11157 static PSI_file_info all_server_files[]=
11158 {
11159   { &key_file_binlog, "binlog", 0, 0, PSI_DOCUMENT_ME},
11160   { &key_file_binlog_cache, "binlog_cache", 0, 0, PSI_DOCUMENT_ME},
11161   { &key_file_binlog_index, "binlog_index", 0, 0, PSI_DOCUMENT_ME},
11162   { &key_file_binlog_index_cache, "binlog_index_cache", 0, 0, PSI_DOCUMENT_ME},
11163   { &key_file_relaylog, "relaylog", 0, 0, PSI_DOCUMENT_ME},
11164   { &key_file_relaylog_cache, "relaylog_cache", 0, 0, PSI_DOCUMENT_ME},
11165   { &key_file_relaylog_index, "relaylog_index", 0, 0, PSI_DOCUMENT_ME},
11166   { &key_file_relaylog_index_cache, "relaylog_index_cache", 0, 0, PSI_DOCUMENT_ME},
11167   { &key_file_io_cache, "io_cache", 0, 0, PSI_DOCUMENT_ME},
11168   { &key_file_casetest, "casetest", 0, 0, PSI_DOCUMENT_ME},
11169   { &key_file_dbopt, "dbopt", 0, 0, PSI_DOCUMENT_ME},
11170   { &key_file_ERRMSG, "ERRMSG", 0, 0, PSI_DOCUMENT_ME},
11171   { &key_select_to_file, "select_to_file", 0, 0, PSI_DOCUMENT_ME},
11172   { &key_file_fileparser, "file_parser", 0, 0, PSI_DOCUMENT_ME},
11173   { &key_file_frm, "FRM", 0, 0, PSI_DOCUMENT_ME},
11174   { &key_file_load, "load", 0, 0, PSI_DOCUMENT_ME},
11175   { &key_file_loadfile, "LOAD_FILE", 0, 0, PSI_DOCUMENT_ME},
11176   { &key_file_log_event_data, "log_event_data", 0, 0, PSI_DOCUMENT_ME},
11177   { &key_file_log_event_info, "log_event_info", 0, 0, PSI_DOCUMENT_ME},
11178   { &key_file_misc, "misc", 0, 0, PSI_DOCUMENT_ME},
11179   { &key_file_pid, "pid", 0, 0, PSI_DOCUMENT_ME},
11180   { &key_file_general_log, "query_log", 0, 0, PSI_DOCUMENT_ME},
11181   { &key_file_slow_log, "slow_log", 0, 0, PSI_DOCUMENT_ME},
11182   { &key_file_tclog, "tclog", 0, 0, PSI_DOCUMENT_ME},
11183   { &key_file_trg, "trigger_name", 0, 0, PSI_DOCUMENT_ME},
11184   { &key_file_trn, "trigger", 0, 0, PSI_DOCUMENT_ME},
11185   { &key_file_init, "init", 0, 0, PSI_DOCUMENT_ME},
11186   { &key_file_sdi, "SDI", 0, 0, PSI_DOCUMENT_ME},
11187   { &key_file_hash_join, "hash_join", 0, 0, PSI_DOCUMENT_ME}
11188 };
11189 /* clang-format on */
11190 #endif /* HAVE_PSI_INTERFACE */
11191 
11192 /* clang-format off */
11193 PSI_stage_info stage_after_create= { 0, "After create", 0, PSI_DOCUMENT_ME};
11194 PSI_stage_info stage_alter_inplace_prepare= { 0, "preparing for alter table", 0, PSI_DOCUMENT_ME};
11195 PSI_stage_info stage_alter_inplace= { 0, "altering table", 0, PSI_DOCUMENT_ME};
11196 PSI_stage_info stage_alter_inplace_commit= { 0, "committing alter table to storage engine", 0, PSI_DOCUMENT_ME};
11197 PSI_stage_info stage_changing_master= { 0, "Changing master", 0, PSI_DOCUMENT_ME};
11198 PSI_stage_info stage_checking_master_version= { 0, "Checking master version", 0, PSI_DOCUMENT_ME};
11199 PSI_stage_info stage_checking_permissions= { 0, "checking permissions", 0, PSI_DOCUMENT_ME};
11200 PSI_stage_info stage_cleaning_up= { 0, "cleaning up", 0, PSI_DOCUMENT_ME};
11201 PSI_stage_info stage_closing_tables= { 0, "closing tables", 0, PSI_DOCUMENT_ME};
11202 PSI_stage_info stage_compressing_gtid_table= { 0, "Compressing gtid_executed table", 0, PSI_DOCUMENT_ME};
11203 PSI_stage_info stage_connecting_to_master= { 0, "Connecting to master", 0, PSI_DOCUMENT_ME};
11204 PSI_stage_info stage_converting_heap_to_ondisk= { 0, "converting HEAP to ondisk", 0, PSI_DOCUMENT_ME};
11205 PSI_stage_info stage_copy_to_tmp_table= { 0, "copy to tmp table", PSI_FLAG_STAGE_PROGRESS, PSI_DOCUMENT_ME};
11206 PSI_stage_info stage_creating_table= { 0, "creating table", 0, PSI_DOCUMENT_ME};
11207 PSI_stage_info stage_creating_tmp_table= { 0, "Creating tmp table", 0, PSI_DOCUMENT_ME};
11208 PSI_stage_info stage_deleting_from_main_table= { 0, "deleting from main table", 0, PSI_DOCUMENT_ME};
11209 PSI_stage_info stage_deleting_from_reference_tables= { 0, "deleting from reference tables", 0, PSI_DOCUMENT_ME};
11210 PSI_stage_info stage_discard_or_import_tablespace= { 0, "discard_or_import_tablespace", 0, PSI_DOCUMENT_ME};
11211 PSI_stage_info stage_end= { 0, "end", 0, PSI_DOCUMENT_ME};
11212 PSI_stage_info stage_executing= { 0, "executing", 0, PSI_DOCUMENT_ME};
11213 PSI_stage_info stage_execution_of_init_command= { 0, "Execution of init_command", 0, PSI_DOCUMENT_ME};
11214 PSI_stage_info stage_explaining= { 0, "explaining", 0, PSI_DOCUMENT_ME};
11215 PSI_stage_info stage_finished_reading_one_binlog_switching_to_next_binlog= { 0, "Finished reading one binlog; switching to next binlog", 0, PSI_DOCUMENT_ME};
11216 PSI_stage_info stage_flushing_relay_log_and_master_info_repository= { 0, "Flushing relay log and master info repository.", 0, PSI_DOCUMENT_ME};
11217 PSI_stage_info stage_flushing_relay_log_info_file= { 0, "Flushing relay-log info file.", 0, PSI_DOCUMENT_ME};
11218 PSI_stage_info stage_freeing_items= { 0, "freeing items", 0, PSI_DOCUMENT_ME};
11219 PSI_stage_info stage_fulltext_initialization= { 0, "FULLTEXT initialization", 0, PSI_DOCUMENT_ME};
11220 PSI_stage_info stage_init= { 0, "init", 0, PSI_DOCUMENT_ME};
11221 PSI_stage_info stage_killing_slave= { 0, "Killing slave", 0, PSI_DOCUMENT_ME};
11222 PSI_stage_info stage_logging_slow_query= { 0, "logging slow query", 0, PSI_DOCUMENT_ME};
11223 PSI_stage_info stage_making_temp_file_append_before_load_data= { 0, "Making temporary file (append) before replaying LOAD DATA INFILE", 0, PSI_DOCUMENT_ME};
11224 PSI_stage_info stage_manage_keys= { 0, "manage keys", 0, PSI_DOCUMENT_ME};
11225 PSI_stage_info stage_master_has_sent_all_binlog_to_slave= { 0, "Master has sent all binlog to slave; waiting for more updates", 0, PSI_DOCUMENT_ME};
11226 PSI_stage_info stage_opening_tables= { 0, "Opening tables", 0, PSI_DOCUMENT_ME};
11227 PSI_stage_info stage_optimizing= { 0, "optimizing", 0, PSI_DOCUMENT_ME};
11228 PSI_stage_info stage_preparing= { 0, "preparing", 0, PSI_DOCUMENT_ME};
11229 PSI_stage_info stage_purging_old_relay_logs= { 0, "Purging old relay logs", 0, PSI_DOCUMENT_ME};
11230 PSI_stage_info stage_query_end= { 0, "query end", 0, PSI_DOCUMENT_ME};
11231 PSI_stage_info stage_queueing_master_event_to_the_relay_log= { 0, "Queueing master event to the relay log", 0, PSI_DOCUMENT_ME};
11232 PSI_stage_info stage_reading_event_from_the_relay_log= { 0, "Reading event from the relay log", 0, PSI_DOCUMENT_ME};
11233 PSI_stage_info stage_registering_slave_on_master= { 0, "Registering slave on master", 0, PSI_DOCUMENT_ME};
11234 PSI_stage_info stage_removing_tmp_table= { 0, "removing tmp table", 0, PSI_DOCUMENT_ME};
11235 PSI_stage_info stage_rename= { 0, "rename", 0, PSI_DOCUMENT_ME};
11236 PSI_stage_info stage_rename_result_table= { 0, "rename result table", 0, PSI_DOCUMENT_ME};
11237 PSI_stage_info stage_requesting_binlog_dump= { 0, "Requesting binlog dump", 0, PSI_DOCUMENT_ME};
11238 PSI_stage_info stage_searching_rows_for_update= { 0, "Searching rows for update", 0, PSI_DOCUMENT_ME};
11239 PSI_stage_info stage_sending_binlog_event_to_slave= { 0, "Sending binlog event to slave", 0, PSI_DOCUMENT_ME};
11240 PSI_stage_info stage_setup= { 0, "setup", 0, PSI_DOCUMENT_ME};
11241 PSI_stage_info stage_slave_has_read_all_relay_log= { 0, "Slave has read all relay log; waiting for more updates", 0, PSI_DOCUMENT_ME};
11242 PSI_stage_info stage_slave_waiting_event_from_coordinator= { 0, "Waiting for an event from Coordinator", 0, PSI_DOCUMENT_ME};
11243 PSI_stage_info stage_slave_waiting_for_workers_to_process_queue= { 0, "Waiting for slave workers to process their queues", 0, PSI_DOCUMENT_ME};
11244 PSI_stage_info stage_slave_waiting_worker_queue= { 0, "Waiting for Slave Worker queue", 0, PSI_DOCUMENT_ME};
11245 PSI_stage_info stage_slave_waiting_worker_to_free_events= { 0, "Waiting for Slave Workers to free pending events", 0, PSI_DOCUMENT_ME};
11246 PSI_stage_info stage_slave_waiting_worker_to_release_partition= { 0, "Waiting for Slave Worker to release partition", 0, PSI_DOCUMENT_ME};
11247 PSI_stage_info stage_slave_waiting_workers_to_exit= { 0, "Waiting for workers to exit", 0, PSI_DOCUMENT_ME};
11248 PSI_stage_info stage_rpl_apply_row_evt_write= { 0, "Applying batch of row changes (write)", PSI_FLAG_STAGE_PROGRESS, PSI_DOCUMENT_ME};
11249 PSI_stage_info stage_rpl_apply_row_evt_update= { 0, "Applying batch of row changes (update)", PSI_FLAG_STAGE_PROGRESS, PSI_DOCUMENT_ME};
11250 PSI_stage_info stage_rpl_apply_row_evt_delete= { 0, "Applying batch of row changes (delete)", PSI_FLAG_STAGE_PROGRESS, PSI_DOCUMENT_ME};
11251 PSI_stage_info stage_statistics= { 0, "statistics", 0, PSI_DOCUMENT_ME};
11252 PSI_stage_info stage_sql_thd_waiting_until_delay= { 0, "Waiting until MASTER_DELAY seconds after master executed event", 0, PSI_DOCUMENT_ME};
11253 PSI_stage_info stage_system_lock= { 0, "System lock", 0, PSI_DOCUMENT_ME};
11254 PSI_stage_info stage_update= { 0, "update", 0, PSI_DOCUMENT_ME};
11255 PSI_stage_info stage_updating= { 0, "updating", 0, PSI_DOCUMENT_ME};
11256 PSI_stage_info stage_updating_main_table= { 0, "updating main table", 0, PSI_DOCUMENT_ME};
11257 PSI_stage_info stage_updating_reference_tables= { 0, "updating reference tables", 0, PSI_DOCUMENT_ME};
11258 PSI_stage_info stage_user_sleep= { 0, "User sleep", 0, PSI_DOCUMENT_ME};
11259 PSI_stage_info stage_verifying_table= { 0, "verifying table", 0, PSI_DOCUMENT_ME};
11260 PSI_stage_info stage_waiting_for_gtid_to_be_committed= { 0, "Waiting for GTID to be committed", 0, PSI_DOCUMENT_ME};
11261 PSI_stage_info stage_waiting_for_handler_commit= { 0, "waiting for handler commit", 0, PSI_DOCUMENT_ME};
11262 PSI_stage_info stage_waiting_for_master_to_send_event= { 0, "Waiting for master to send event", 0, PSI_DOCUMENT_ME};
11263 PSI_stage_info stage_waiting_for_master_update= { 0, "Waiting for master update", 0, PSI_DOCUMENT_ME};
11264 PSI_stage_info stage_waiting_for_relay_log_space= { 0, "Waiting for the slave SQL thread to free enough relay log space", 0, PSI_DOCUMENT_ME};
11265 PSI_stage_info stage_waiting_for_slave_mutex_on_exit= { 0, "Waiting for slave mutex on exit", 0, PSI_DOCUMENT_ME};
11266 PSI_stage_info stage_waiting_for_slave_thread_to_start= { 0, "Waiting for slave thread to start", 0, PSI_DOCUMENT_ME};
11267 PSI_stage_info stage_waiting_for_table_flush= { 0, "Waiting for table flush", 0, PSI_DOCUMENT_ME};
11268 PSI_stage_info stage_waiting_for_the_next_event_in_relay_log= { 0, "Waiting for the next event in relay log", 0, PSI_DOCUMENT_ME};
11269 PSI_stage_info stage_waiting_for_the_slave_thread_to_advance_position= { 0, "Waiting for the slave SQL thread to advance position", 0, PSI_DOCUMENT_ME};
11270 PSI_stage_info stage_waiting_to_finalize_termination= { 0, "Waiting to finalize termination", 0, PSI_DOCUMENT_ME};
11271 PSI_stage_info stage_worker_waiting_for_its_turn_to_commit= { 0, "Waiting for preceding transaction to commit", 0, PSI_DOCUMENT_ME};
11272 PSI_stage_info stage_worker_waiting_for_commit_parent= { 0, "Waiting for dependent transaction to commit", 0, PSI_DOCUMENT_ME};
11273 PSI_stage_info stage_suspending= { 0, "Suspending", 0, PSI_DOCUMENT_ME};
11274 PSI_stage_info stage_starting= { 0, "starting", 0, PSI_DOCUMENT_ME};
11275 PSI_stage_info stage_waiting_for_no_channel_reference= { 0, "Waiting for no channel reference.", 0, PSI_DOCUMENT_ME};
11276 PSI_stage_info stage_hook_begin_trans= { 0, "Executing hook on transaction begin.", 0, PSI_DOCUMENT_ME};
11277 PSI_stage_info stage_binlog_transaction_compress= { 0, "Compressing transaction changes.", 0, PSI_DOCUMENT_ME};
11278 PSI_stage_info stage_binlog_transaction_decompress= { 0, "Decompressing transaction changes.", 0, PSI_DOCUMENT_ME};
11279 /* clang-format on */
11280 
11281 extern PSI_stage_info stage_waiting_for_disk_space;
11282 
11283 #ifdef HAVE_PSI_INTERFACE
11284 
11285 PSI_stage_info *all_server_stages[] = {
11286     &stage_after_create,
11287     &stage_alter_inplace_prepare,
11288     &stage_alter_inplace,
11289     &stage_alter_inplace_commit,
11290     &stage_changing_master,
11291     &stage_checking_master_version,
11292     &stage_checking_permissions,
11293     &stage_cleaning_up,
11294     &stage_closing_tables,
11295     &stage_compressing_gtid_table,
11296     &stage_connecting_to_master,
11297     &stage_converting_heap_to_ondisk,
11298     &stage_copy_to_tmp_table,
11299     &stage_creating_table,
11300     &stage_creating_tmp_table,
11301     &stage_deleting_from_main_table,
11302     &stage_deleting_from_reference_tables,
11303     &stage_discard_or_import_tablespace,
11304     &stage_end,
11305     &stage_executing,
11306     &stage_execution_of_init_command,
11307     &stage_explaining,
11308     &stage_finished_reading_one_binlog_switching_to_next_binlog,
11309     &stage_flushing_relay_log_and_master_info_repository,
11310     &stage_flushing_relay_log_info_file,
11311     &stage_freeing_items,
11312     &stage_fulltext_initialization,
11313     &stage_init,
11314     &stage_killing_slave,
11315     &stage_logging_slow_query,
11316     &stage_making_temp_file_append_before_load_data,
11317     &stage_manage_keys,
11318     &stage_master_has_sent_all_binlog_to_slave,
11319     &stage_opening_tables,
11320     &stage_optimizing,
11321     &stage_preparing,
11322     &stage_purging_old_relay_logs,
11323     &stage_query_end,
11324     &stage_queueing_master_event_to_the_relay_log,
11325     &stage_reading_event_from_the_relay_log,
11326     &stage_registering_slave_on_master,
11327     &stage_removing_tmp_table,
11328     &stage_rename,
11329     &stage_rename_result_table,
11330     &stage_requesting_binlog_dump,
11331     &stage_searching_rows_for_update,
11332     &stage_sending_binlog_event_to_slave,
11333     &stage_setup,
11334     &stage_slave_has_read_all_relay_log,
11335     &stage_slave_waiting_event_from_coordinator,
11336     &stage_slave_waiting_for_workers_to_process_queue,
11337     &stage_slave_waiting_worker_queue,
11338     &stage_slave_waiting_worker_to_free_events,
11339     &stage_slave_waiting_worker_to_release_partition,
11340     &stage_slave_waiting_workers_to_exit,
11341     &stage_rpl_apply_row_evt_write,
11342     &stage_rpl_apply_row_evt_update,
11343     &stage_rpl_apply_row_evt_delete,
11344     &stage_sql_thd_waiting_until_delay,
11345     &stage_statistics,
11346     &stage_system_lock,
11347     &stage_update,
11348     &stage_updating,
11349     &stage_updating_main_table,
11350     &stage_updating_reference_tables,
11351     &stage_user_sleep,
11352     &stage_verifying_table,
11353     &stage_waiting_for_gtid_to_be_committed,
11354     &stage_waiting_for_handler_commit,
11355     &stage_waiting_for_master_to_send_event,
11356     &stage_waiting_for_master_update,
11357     &stage_waiting_for_relay_log_space,
11358     &stage_waiting_for_slave_mutex_on_exit,
11359     &stage_waiting_for_slave_thread_to_start,
11360     &stage_waiting_for_table_flush,
11361     &stage_waiting_for_the_next_event_in_relay_log,
11362     &stage_waiting_for_the_slave_thread_to_advance_position,
11363     &stage_waiting_to_finalize_termination,
11364     &stage_worker_waiting_for_its_turn_to_commit,
11365     &stage_worker_waiting_for_commit_parent,
11366     &stage_suspending,
11367     &stage_starting,
11368     &stage_waiting_for_no_channel_reference,
11369     &stage_hook_begin_trans,
11370     &stage_waiting_for_disk_space,
11371     &stage_binlog_transaction_compress,
11372     &stage_binlog_transaction_decompress};
11373 
11374 PSI_socket_key key_socket_tcpip;
11375 PSI_socket_key key_socket_unix;
11376 PSI_socket_key key_socket_client_connection;
11377 
11378 /* clang-format off */
11379 static PSI_socket_info all_server_sockets[]=
11380 {
11381   { &key_socket_tcpip, "server_tcpip_socket", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11382   { &key_socket_unix, "server_unix_socket", PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME},
11383   { &key_socket_client_connection, "client_connection", PSI_FLAG_USER, 0, PSI_DOCUMENT_ME}
11384 };
11385 /* clang-format on */
11386 
11387 /* TODO: find a good header */
11388 void init_client_psi_keys(void);
11389 
11390 /**
11391   Initialise all the performance schema instrumentation points
11392   used by the server.
11393 */
init_server_psi_keys(void)11394 static void init_server_psi_keys(void) {
11395   const char *category = "sql";
11396   int count;
11397 
11398   count = static_cast<int>(array_elements(all_server_mutexes));
11399   mysql_mutex_register(category, all_server_mutexes, count);
11400 
11401   count = static_cast<int>(array_elements(all_server_rwlocks));
11402   mysql_rwlock_register(category, all_server_rwlocks, count);
11403 
11404   count = static_cast<int>(array_elements(all_server_conds));
11405   mysql_cond_register(category, all_server_conds, count);
11406 
11407   count = static_cast<int>(array_elements(all_server_threads));
11408   mysql_thread_register(category, all_server_threads, count);
11409 
11410   count = static_cast<int>(array_elements(all_server_files));
11411   mysql_file_register(category, all_server_files, count);
11412 
11413   count = static_cast<int>(array_elements(all_server_stages));
11414   mysql_stage_register(category, all_server_stages, count);
11415 
11416   count = static_cast<int>(array_elements(all_server_sockets));
11417   mysql_socket_register(category, all_server_sockets, count);
11418 
11419   register_server_memory_keys();
11420 
11421 #ifdef HAVE_PSI_STATEMENT_INTERFACE
11422   init_sql_statement_info();
11423 
11424   /* Register [0 .. SQLCOM_CLONE - 1] as "statement/sql/..." */
11425   count = (int)SQLCOM_CLONE;
11426   mysql_statement_register(category, sql_statement_info, count);
11427 
11428   /* Exclude SQLCOM_CLONE as it mutates and is registered as abstract. */
11429   count = (int)SQLCOM_END - (int)SQLCOM_CLONE;
11430   mysql_statement_register(category, &sql_statement_info[(int)SQLCOM_CLONE + 1],
11431                            count);
11432   category = "abstract";
11433   mysql_statement_register(category, &sql_statement_info[(int)SQLCOM_CLONE], 1);
11434 
11435   init_sp_psi_keys();
11436 
11437   init_scheduler_psi_keys();
11438 
11439   category = "com";
11440   init_com_statement_info();
11441 
11442   /*
11443     Register [0 .. COM_QUERY - 1] as "statement/com/..."
11444   */
11445   count = (int)COM_QUERY;
11446   mysql_statement_register(category, com_statement_info, count);
11447 
11448   /* Exclude COM_CLONE as it would mutate */
11449   count = (int)COM_CLONE - (int)COM_QUERY - 1;
11450   mysql_statement_register(category, &com_statement_info[(int)COM_QUERY + 1],
11451                            count);
11452   /*
11453     Register [COM_CLONE + 1 .. COM_END] as "statement/com/..."
11454   */
11455   count = (int)COM_END - (int)COM_CLONE;
11456   mysql_statement_register(category, &com_statement_info[(int)COM_CLONE + 1],
11457                            count);
11458   category = "abstract";
11459   /*
11460     Register [COM_QUERY] as "statement/abstract/com_query"
11461   */
11462   mysql_statement_register(category, &com_statement_info[(int)COM_QUERY], 1);
11463   mysql_statement_register(category, &com_statement_info[(int)COM_CLONE], 1);
11464 
11465   /*
11466     When a new packet is received,
11467     it is instrumented as "statement/abstract/new_packet".
11468     Based on the packet type found, it later mutates to the
11469     proper narrow type, for example
11470     "statement/abstract/query" or "statement/com/ping".
11471     In cases of "statement/abstract/query", SQL queries are given to
11472     the parser, which mutates the statement type to an even more
11473     narrow classification, for example "statement/sql/select".
11474   */
11475   stmt_info_new_packet.m_key = 0;
11476   stmt_info_new_packet.m_name = "new_packet";
11477   stmt_info_new_packet.m_flags = PSI_FLAG_MUTABLE;
11478   stmt_info_new_packet.m_documentation =
11479       "New packet just received from the network. "
11480       "At this point, the real command type is unknown, "
11481       "the type will be refined after reading the packet header.";
11482   mysql_statement_register(category, &stmt_info_new_packet, 1);
11483 
11484   /*
11485     Statements processed from the relay log are initially instrumented as
11486     "statement/abstract/relay_log". The parser will mutate the statement type to
11487     a more specific classification, for example "statement/sql/insert".
11488   */
11489   stmt_info_rpl.m_key = 0;
11490   stmt_info_rpl.m_name = "relay_log";
11491   stmt_info_rpl.m_flags = PSI_FLAG_MUTABLE;
11492   stmt_info_rpl.m_documentation =
11493       "New event just read from the relay log. "
11494       "At this point, the real statement type is unknown, "
11495       "the type will be refined after parsing the event.";
11496   mysql_statement_register(category, &stmt_info_rpl, 1);
11497 #endif
11498 
11499   /* Common client and server code. */
11500   init_client_psi_keys();
11501   /* Vio */
11502   init_vio_psi_keys();
11503   /* TLS interfaces */
11504   init_tls_psi_keys();
11505 }
11506 #endif /* HAVE_PSI_INTERFACE */
11507 
do_create_native_table_for_pfs(THD * thd,const Plugin_table * t)11508 bool do_create_native_table_for_pfs(THD *thd, const Plugin_table *t) {
11509   const char *schema_name = t->get_schema_name();
11510   const char *table_name = t->get_name();
11511   MDL_request table_request;
11512   MDL_REQUEST_INIT(&table_request, MDL_key::TABLE, schema_name, table_name,
11513                    MDL_EXCLUSIVE, MDL_TRANSACTION);
11514 
11515   if (thd->mdl_context.acquire_lock(&table_request,
11516                                     thd->variables.lock_wait_timeout)) {
11517     /* Error, failed to get MDL lock. */
11518     return true;
11519   }
11520 
11521   tdc_remove_table(thd, TDC_RT_REMOVE_ALL, schema_name, table_name, false);
11522 
11523   if (dd::create_native_table(thd, t)) {
11524     /* Error, failed to create DD table. */
11525     return true;
11526   }
11527 
11528   return false;
11529 }
11530 
create_native_table_for_pfs(const Plugin_table * t)11531 bool create_native_table_for_pfs(const Plugin_table *t) {
11532   /* If InnoDB is not initialized yet, return error */
11533   if (!is_builtin_and_core_se_initialized()) return true;
11534 
11535   THD *thd = current_thd;
11536   DBUG_ASSERT(thd);
11537   return do_create_native_table_for_pfs(thd, t);
11538 }
11539 
do_drop_native_table_for_pfs(THD * thd,const char * schema_name,const char * table_name)11540 static bool do_drop_native_table_for_pfs(THD *thd, const char *schema_name,
11541                                          const char *table_name) {
11542   MDL_request table_request;
11543   MDL_REQUEST_INIT(&table_request, MDL_key::TABLE, schema_name, table_name,
11544                    MDL_EXCLUSIVE, MDL_TRANSACTION);
11545 
11546   if (thd->mdl_context.acquire_lock(&table_request,
11547                                     thd->variables.lock_wait_timeout)) {
11548     /* Error, failed to get MDL lock. */
11549     return true;
11550   }
11551 
11552   tdc_remove_table(thd, TDC_RT_REMOVE_ALL, schema_name, table_name, false);
11553 
11554   if (dd::drop_native_table(thd, schema_name, table_name)) {
11555     /* Error, failed to destroy DD table. */
11556     return true;
11557   }
11558 
11559   return false;
11560 }
11561 
drop_native_table_for_pfs(const char * schema_name,const char * table_name)11562 bool drop_native_table_for_pfs(const char *schema_name,
11563                                const char *table_name) {
11564   /* If server is shutting down, by the time control reaches here, DD would have
11565    * already been shut down. Therefore return success and tables won't be
11566    * deleted and would be available at next server start.
11567    */
11568   if (get_server_state() == SERVER_SHUTTING_DOWN) {
11569     return false;
11570   }
11571 
11572   /* During bootstrap error cleanup, we don't have THD. */
11573   THD *thd = current_thd;
11574   if (thd == nullptr) {
11575     DBUG_ASSERT(get_server_state() == SERVER_BOOTING);
11576     return false;
11577   }
11578   return do_drop_native_table_for_pfs(thd, schema_name, table_name);
11579 }
11580 
11581 #ifdef _WIN32
11582 // update_named_pipe_full_access_group returns false on success, true on failure
update_named_pipe_full_access_group(const char * new_group_name)11583 bool update_named_pipe_full_access_group(const char *new_group_name) {
11584   if (named_pipe_acceptor) {
11585     return named_pipe_listener->update_named_pipe_full_access_group(
11586         new_group_name);
11587   }
11588   return true;
11589 }
11590 
11591 #endif  // _WIN32
11592 
11593 /**
11594   Get status partial_revokes on server
11595 
11596   @return a bool indicating partial_revokes status of the server.
11597     @retval true  Parital revokes is ON
11598     @retval flase Partial revokes is OFF
11599 */
mysqld_partial_revokes()11600 bool mysqld_partial_revokes() {
11601   return partial_revokes.load(std::memory_order_relaxed);
11602 }
11603 
11604 /**
11605   Set partial_revokes with a given value
11606 
11607   @param value true or false indicating the status of partial revokes
11608                turned ON/OFF on server.
11609 */
set_mysqld_partial_revokes(bool value)11610 void set_mysqld_partial_revokes(bool value) {
11611   partial_revokes.store(value, std::memory_order_relaxed);
11612 }
11613 
11614 /**
11615   Set m_opt_tracking_mode with a user given value associated with sysvar.
11616 */
set_mysqld_opt_tracking_mode()11617 void set_mysqld_opt_tracking_mode() {
11618   mysql_bin_log.m_dependency_tracker.m_opt_tracking_mode.store(
11619       mysql_bin_log.m_dependency_tracker.m_opt_tracking_mode_value,
11620       std::memory_order_relaxed);
11621 }
11622